我用下面的代码(借用自an old post)比较了blitz++、armadillo、boost::MultiArray。
#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、英特尔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++. 要使用英特尔c++编译器编译blitz++,需要在blitz/ intel /文件夹中创建一个名为bzconfig.h的文件。但是没有,我只是把blitz/ms/bzconfig.h中的文件复制进去。这可能会给出一个非最佳配置。谁能告诉我如何用英特尔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.发布于 2015-10-22 20:23:53
简短的答案:./configure CXX=icpc,可以通过阅读Blitz++用户指南找到它。
长长的答案:
要使用英特尔c++编译器编译blitz++,在blitz/ intel / c++中需要一个名为bzconfig.h的文件。但实际上并没有。
是的,是的。Blitz++应该自己生成文件。根据blitz-0.10.tar.gz中包含的Blitz++用户指南blitz.pdf的“安装”一节,
Blitz++使用GNU Autoconf,它为各种平台和编译器处理重写Makefiles。
更准确地说,Blitz++使用GNU autotools工具链(automake、autoconf、configure),它可以生成makefile、配置脚本、头文件等。bzconfig.h文件应该由configure脚本生成,该脚本随Blitz++一起提供,可以随时使用。
我只需将
/ms/bzconfig.h中的文件复制进去。这可能会给出一个非最佳配置。
如果“非最优”对你来说意味着“不工作”,那么是的。:-)您需要一个能够准确表示您的编译器的intel/bzconfig.h。
谁能告诉我如何用英特尔c++编译器编译blitz++?
阅读并遵循详细的手册,特别是上面提到的“安装”部分。
进入‘blitz-VERSION’目录,输入:
./configure CXX=[compiler],其中编译器是xlc++、icpc、pathCC、xlC、cxx、aCC、CC、g++、KCC、pgCC或FCC之一。(如果不选择C++编译器,配置脚本将尝试查找适合当前平台的编译器。)
你做过这件事吗?对于英特尔编译器,您需要使用./configure CXX=icpc。
在手册中,它说运行bzconfig脚本来获得正确的bzconfig.h。但我不明白这是什么意思。
我想你说的“它”就是“那个”。你说的“手册”是什么意思?我的Blitz++用户指南中没有提到bzconfig。您确定使用的是与您的Blitz++版本对应的手册吗?
PS:在blitz-0.10的内容中查找"bzconfig“,看起来"bzconfig”不再是Blitz++的一部分,而是曾经的:
find . -name bzconfig ->无结果
find . -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目录。
发布于 2015-12-23 05:45:12
据我所知,您正在通过测量单个矩阵乘以标量的速度来判断每个矩阵库的性能。由于其基于模板的策略,Armadillo将在这方面做得非常好,它将每个乘法分解为可并行化的代码,供大多数编译器使用。
但我建议你需要重新考虑你的测试范围和方法。例如,您遗漏了所有BLAS实现。您需要的BLAS函数是dscal。供应商为您的特定CPU提供的实现可能会做得很好。
更重要的是,任何合理的向量库都需要做更多的事情:矩阵乘法、点积、向量长度、转置等等,这些都不是您的测试所能解决的。您的测试恰好解决了两件事:元素赋值和标量/向量乘法,元素赋值实际上从来不是矢量库的瓶颈,标量/向量乘法是每个CPU制造商提供的BLAS级别1功能。
这里讨论了BLAS级别1与编译器发出的代码here。
tl:dr;use Armadillo with BLAS and LAPACK native libraries linked in for your platform。
发布于 2016-06-08 17:51:26
我的测试表明boost数组与原生/硬编码的C++代码具有相同的性能。
您需要使用激活的编译器优化来比较它们。即:-O3 -DNDEBUG -DBOOST_UBLAS_NDEBUG -DBOOST_DISABLE_ASSERTS -DARMA_NO_DEBUG ...当我测试(em++)时,当您停用Boost的断言、使用-O3启用3级优化等时,Boost的执行速度至少要快10倍。
https://stackoverflow.com/questions/14414906
复制相似问题