c++ - 比较 blitz++、 Armadillo 、boost::MultiArray

标签 c++ multidimensional-array armadillo boost-multi-array blitz++

我用下面的代码对比了blitz++、armadillo、boost::MultiArray(借用自an old post)

#include <iostream>
using namespace std;
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS
#define BOOST_DISABLE_ASSERTS 
#include <boost/multi_array.hpp>
#include <blitz/array.h>
#include <armadillo>

int main(int argc, char* argv[])
{
    const int X_SIZE = 1000;
    const int Y_SIZE = 1000;
    const int ITERATIONS = 100;
    unsigned int startTime = 0;
    unsigned int endTime = 0;

    // Create the boost array


    //------------------Measure boost Loop------------------------------------------
    {
        typedef boost::multi_array<double, 2> ImageArrayType;
        ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                for (int y = 0; y < Y_SIZE; ++y)
                {
                    boostMatrix[x][y] = 1.0001;
                }
            }
        }
        endTime = ::GetTickCount();
        printf("[Boost Loop] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
    }
    //------------------Measure blitz Loop-------------------------------------------
    {
        blitz::Array<double, 2> blitzArray( X_SIZE, Y_SIZE );
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                for (int y = 0; y < Y_SIZE; ++y)
                {
                    blitzArray(x,y) = 1.0001;
                }
            }
        }
        endTime = ::GetTickCount();
        printf("[Blitz Loop] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
    }

    //------------------Measure armadillo loop----------------------------------------
    {
        arma::mat matArray( X_SIZE, Y_SIZE );
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            for (int y = 0; y < Y_SIZE; ++y)
            {
                for (int x = 0; x < X_SIZE; ++x)
                {
                    matArray(x,y) = 1.0001;
                }
            }
        }
        endTime = ::GetTickCount();
        printf("[arma  Loop]  Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
    }

    //------------------Measure native loop----------------------------------------
    // Create the native array
    {
        double *nativeMatrix = new double [X_SIZE * Y_SIZE];
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            for (int y = 0; y < Y_SIZE*X_SIZE; ++y)
            {
                nativeMatrix[y] = 1.0001;
            }
        }
        endTime = ::GetTickCount();
        printf("[Native Loop]Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
        delete[] nativeMatrix;
    }

    //------------------Measure boost computation-----------------------------------
    {
        typedef boost::multi_array<double, 2> ImageArrayType;
        ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);
        for (int x = 0; x < X_SIZE; ++x)
        {
            for (int y = 0; y < Y_SIZE; ++y)
            {
                boostMatrix[x][y] = 1.0001;
            }
        }
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                for (int y = 0; y < Y_SIZE; ++y)
                {
                    boostMatrix[x][y] += boostMatrix[x][y] * 0.5;
                }
            }
        }
        endTime = ::GetTickCount();
        printf("[Boost computation] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
    }

    //------------------Measure blitz computation-----------------------------------
    {
        blitz::Array<double, 2> blitzArray( X_SIZE, Y_SIZE );
        blitzArray = 1.0001;
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            blitzArray += blitzArray*0.5;
        }
        endTime = ::GetTickCount();
        printf("[Blitz computation] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
    }

    //------------------Measure armadillo computation-------------------------------
    {
        arma::mat matArray( X_SIZE, Y_SIZE );
        matArray.fill(1.0001);
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            //matArray.fill(1.0001);
            matArray += matArray*0.5;
        }
        endTime = ::GetTickCount();
        printf("[arma  computation] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
    }

    //------------------Measure native computation------------------------------------------
    // Create the native array
    {
        double *nativeMatrix = new double [X_SIZE * Y_SIZE];
        for (int y = 0; y < Y_SIZE*X_SIZE; ++y)
        {
            nativeMatrix[y] = 1.0001;
        }
        startTime = ::GetTickCount();
        for (int i = 0; i < ITERATIONS; ++i)
        {
            for (int y = 0; y < Y_SIZE*X_SIZE; ++y)
            {
                nativeMatrix[y] += nativeMatrix[y] * 0.5;
            }
        }
        endTime = ::GetTickCount();
        printf("[Native computation]Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
        delete[] nativeMatrix;
    }

    return 0;
}

在windows,VS2010上,结果是

[Boost Loop] Elapsed time:  1.217 seconds
[Blitz Loop] Elapsed time:  0.046 seconds
[arma  Loop]  Elapsed time:  0.078 seconds
[Native Loop]Elapsed time:  0.172 seconds
[Boost computation] Elapsed time:  2.152 seconds
[Blitz computation] Elapsed time:  0.156 seconds
[arma  computation] Elapsed time:  0.078 seconds
[Native computation]Elapsed time:  0.078 seconds

在windows,intel c++上,结果是

[Boost Loop] Elapsed time:  0.468 seconds
[Blitz Loop] Elapsed time:  0.125 seconds
[arma  Loop]  Elapsed time:  0.046 seconds
[Native Loop]Elapsed time:  0.047 seconds
[Boost computation] Elapsed time:  0.796 seconds
[Blitz computation] Elapsed time:  0.109 seconds
[arma  computation] Elapsed time:  0.078 seconds
[Native computation]Elapsed time:  0.062 seconds

有些奇怪:

(1) with VS2010, native computation (including loop) is faster than native loop
(2) blitz loop behave so different under VS2010 and intel C++. 

要使用 intel c++ 编译器编译 blitz++,blitz/intel/文件夹中需要一个名为 bzconfig.h 的文件。但是没有。我只是复制 blitz/ms/bzconfig.h 中的那个。这可能会给出非最佳配置。任何人都可以告诉我如何使用 intel c++ 编译器编译 blitz++?在手册中,它说运行 bzconfig 脚本以获取正确的 bzconfig.h。但我不明白这是什么意思。

非常感谢!

添加一些我的结论:

1. Boost multi array is the slowest.
2. With intel c++ compiler, native pointers are very fast.
3. With intel c++ compiler,  armadillo can achieve the performance of native pointers.
4. Also test eigen, it is x0% slower than armadillo in my simple cases.
5. Curious about blitz++'s behavior in intel c++ compiler with proper configuration.
   Please see my question.

最佳答案

简答:./configure CXX=icpc,通过阅读 Blitz++ 用户指南找到。

长答案:

To compile blitz++ with intel c++ compiler, a file called bzconfig.h is required in blitz/intel/ folder. But there isn't.

是的,是的。 Blitz++ 应该自己生成文件。根据 blitz-0.10.tar.gz 中包含的 Blitz++ 用户指南 blitz.pdf,“安装”部分,

Blitz++ uses GNU Autoconf, which handles rewriting Makefiles for various platforms and compilers.

更准确地说,Blitz++ 使用 GNU autotools 工具链(automake、autoconf、configure),可以生成 makefile、配置脚本、头文件等。 bzconfig.h 文件应该是由 Blitz++ 自带的 configure 脚本生成的,可以直接使用。

I just copy the one in blitz/ms/bzconfig.h in. That may give an non-optimal configuration.

如果“非最佳”对您来说意味着“不工作”,那么是的。 :-) 您需要一个准确代表您的编译器的 intel/bzconfig.h

Anyone can tell me how to compile blitz++ with intel c++ compiler?

阅读并遵循精美的手册,尤其是上面提到的“安装”部分。

go into the ‘blitz-VERSION’ directory, and type: ./configure CXX=[compiler] where [compiler] is one of xlc++, icpc, pathCC, xlC, cxx, aCC, CC, g++, KCC, pgCC or FCC. (If you do not choose a C++ compiler, the configure script will attempt to find an appropriate compiler for the current platform.)

你做过吗?对于英特尔编译器,您需要使用 ./configure CXX=icpc.

In the manual, it said run bzconfig script to get the right bzconfig.h. But I don't understand what it means.

我假设“它”是指“那个”。 “手动”是什么意思?我的 Blitz++ 用户指南没有提到 bzconfig。您确定您使用的是与您的 Blitz++ 版本对应的手册吗?

PS:在blitz-0.10的内容中寻找“bzconfig” ,看起来“bzconfig”不再是 Blitz++ 的一部分,而是曾经是:

找到 . -name bzconfig -> 没有结果

找到 . -print0 | xargs -0 grep -a -i -n -e bzconfig:

./blitz/compiler.h:44:    #error  In <blitz/config.h>: A working template implementation is required by Blitz++ (you may need to rerun the compiler/bzconfig script)

这需要更新。

./blitz/gnu/bzconfig.h:4:/* blitz/gnu/bzconfig.h. Generated automatically at end of configure. */
./configure.ac:159:# autoconf replacement of bzconfig

你有它,这些 bzconfig.h 文件应该由 configure 生成。

./ChangeLog.1:1787: will now replace the old file that was generate with the bzconfig

这可能是切换到 autoconf 的变化。

./INSTALL:107:  2. Go into the compiler subdirectory and run the bzconfig

这需要更新。这就是让你寻找 bzconfig 的原因吗?

./README:27:compiler      Compiler tests (used with obsolete bzconfig script)  

需要更新,不再包含compiler目录。

关于c++ - 比较 blitz++、 Armadillo 、boost::MultiArray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14414906/

相关文章:

c++ - 为什么这些内存值在 GDB 中永远不会改变?

c++: 函数不能重载

c++ - 二维数组错误c++

php - 将二维数组转换为多维

c++ - 如何围绕表达式模板编写第三方库包装类

c++ - Armadillo 整数特征分解

c++ - 修改task.json以编译多个c++文件

c++ - Qt : constructors with arguments or default constructors with setters afterwards? 哪个效率更高

php - 将使用循环创建的数组附加到另​​一个数组

c++ - push_back/append 或在 C++ Armadillo 中附加带有循环的 vector