C++ 犰狳+;OpenBLAS比MATLAB慢?

C++ 犰狳+;OpenBLAS比MATLAB慢?,c++,blas,armadillo,C++,Blas,Armadillo,对这样的人来说是新的。我正在试驾Armadillo+OpenBLAS,一个简单的蒙特卡罗几何布朗运动逻辑显示了比MATLAB更长的运行时间。我相信一定是出了什么问题 环境: 英特尔i-5 4核, 8GB内存, VS 2012 Express, 犰狳4.2, OpenBLAS(官方x64二进制)v0.2.9.rc2 对于相同的逻辑,MATLAB需要2秒,但是Armadillo+OB需要12秒。我还注意到该程序是在单线程上运行的,但我转向OpenBLAS,因为我听说它具有多核功能 谢谢你的建议 #i

对这样的人来说是新的。我正在试驾Armadillo+OpenBLAS,一个简单的蒙特卡罗几何布朗运动逻辑显示了比MATLAB更长的运行时间。我相信一定是出了什么问题

环境: 英特尔i-5 4核, 8GB内存, VS 2012 Express, 犰狳4.2, OpenBLAS(官方x64二进制)v0.2.9.rc2

对于相同的逻辑,MATLAB需要2秒,但是Armadillo+OB需要12秒。我还注意到该程序是在单线程上运行的,但我转向OpenBLAS,因为我听说它具有多核功能

谢谢你的建议

#include <iostream>
#include <armadillo>
#include <ctime>

using namespace std;
using namespace arma;

int main()
{
clock_t start;
start = clock();
unsigned int R=100000;
vec Spre = 100*ones<vec> (R);
vec S = zeros<vec> (R);
double r = 0.03;
double Vol = 0.2;
double TTM = 5;
unsigned int T=260*TTM;
double dt = TTM/T;
for (unsigned int iT=0; iT<T; ++iT)
{
    S = Spre%exp((r-0.5*Vol*Vol)*dt + Vol*sqrt(dt)*randn(R));
    Spre = S;
}
cout << mean(S) << endl;
cout << (clock()-start) / (double) CLOCKS_PER_SEC << endl;
system("pause");
return 0;
}
#包括
#包括
#包括
使用名称空间std;
使用arma;
int main()
{
时钟没有启动;
开始=时钟();
无符号整数R=100000;
vec Spre=100*个(R);
vec S=零(R);
双r=0.03;
双体积=0.2;
双TTM=5;
无符号整数T=260*TTM;
双dt=TTM/T;

for(unsigned int iT=0;它只是一个猜测,但看起来您需要通过
OpenBLAS\u NUM\u threads
环境变量设置要在OpenBLAS中使用的线程数

尝试以下方法:

set OPENBLAS_NUM_THREADS=4

…在运行程序之前,请在命令行上。将系统中的内核数替换为“4”(有些人会说将其设置为系统中内核数的两倍--YMMV)。
在log()、pow()和sqrt()中也观察到类似的开销。

首先,瓶颈不是exp(),尽管std::exp很慢。问题是randn()

在我的机器上,randn()占用了大部分时间。当我使用MKL_VSL的randn实现时,时间成本从12秒下降到4秒,与matlab的3秒左右相当

#include <iostream>
#include <armadillo>
#include <ctime>
#include "mkl_vml.h"
#include "mkl_vsl.h"
using namespace std;
using namespace arma;

#define SEED 0
#define BRNG VSL_BRNG_MCG31
#define METHOD 0
int main()
{
clock_t start;
VSLStreamStatePtr stream;
start = clock();
vslNewStream(&stream, BRNG, SEED);
unsigned int R=100000;
vec Spre = 100*ones<vec> (R);
vec S = zeros<vec> (R);
double r = 0.03;
double Vol = 0.2;
double TTM = 5;
unsigned int T=260*TTM;
double dt = TTM/T;
double tmp = sqrt(dt);
vec tmp2=100*zeros<vec>(R);
vec tmp3=100*zeros<vec>(R);
for (unsigned int iT=0; iT<T; ++iT)
{
    vdRngGaussian(METHOD,stream, R, tmp3.memptr(), 0, 1);
    tmp2 =(r - 0.5 * Vol * Vol) * dt + Vol * tmp * tmp3;
    vdExp(R, tmp2.memptr(), tmp3.memptr());
    S = Spre%tmp3;
    Spre = S;
}
cout << mean(S) << endl;
cout << (clock()-start) / (double) CLOCKS_PER_SEC << endl;
vslDeleteStream(&stream);
//system("pause");
return 0;
}
#包括
#包括
#包括
#包括“mkl_vml.h”
#包括“mkl_vsl.h”
使用名称空间std;
使用arma;
#定义种子0
#定义BRNG VSL_BRNG_MCG31
#定义方法0
int main()
{
时钟没有启动;
VSLStreamStatePtr流;
开始=时钟();
vslNewStream(流、BRNG、种子);
无符号整数R=100000;
vec Spre=100*个(R);
vec S=零(R);
双r=0.03;
双体积=0.2;
双TTM=5;
无符号整数T=260*TTM;
双dt=TTM/T;
双tmp=sqrt(dt);
向量tmp2=100*零(R);
向量tmp3=100*零(R);

对于(unsigned int iT=0;它感谢快速响应。我尝试了以下方法:“C:\Release>set OPENBLAS_NUM_THREADS=4 C:\Release>TestOpenBLAS 116.44 12.434按任意键继续…”我是否正确理解了您的建议?它仍然需要12秒以上的时间,并且仍然作为单个线程运行。@AndreasBVB:首先,您是从IDE还是从命令行运行?可能最好只为您的系统一次性设置环境变量(在大多数Windows版本上通过系统属性->高级->环境变量)。然后确保重新启动IDE以获得一个新的环境。在启动IDE时,确保正在构建一个“版本”通过调试器编译而不是运行。然后我们将看到还有什么样的性能差距。谢谢@Drew Hall。我设置了系统ev,重新启动并重新启动了VS2012。在x64版本下再次编译,仍然得到相同的结果。现在我怀疑这是二进制文件的制作方式。让我找个时间测试一下英特尔MKL,然后我会有一个更好的主意。@AndreasBVB:您是通过调试器运行,还是清除?如果您是从VS IDE执行此操作,则需要按“不带调试运行(shift-F5)”按钮,否则调试器将破坏您的性能。我实际上尝试了两种方法:1)不带调试运行2)从系统命令行运行。没有任何帮助。我已经用ArrayFire GPU库测试了相同的逻辑,这非常令人印象深刻,所以现在我倾向于怀疑二进制文件被编译为单线程…但是12秒运行时间对于单线程来说仍然太长。谢谢。看起来循环不会调用任何BLAS函数,所以OpenBLAS可能不是问题所在。我怀疑优化和矢量化需要在编译器中显式启用。Armadillo是一个模板库,对于所有模板库来说,在编译过程中进行优化是绝对必要的。还请记住,MS VS编译器不具备健壮性或生成快速code。GCC或可以实现更好的性能。您可以通过获得Windows GCC。进一步更新:似乎是randn(R)降低了整个逻辑的速度。切换到零(R),然后在不到2秒的时间内完成。切换到randn(R)然后又是12秒…这更可能是Armadillo问题而不是OpenBLAS问题。非常令人沮丧…@mtall切换到Eclipse+MinGW,现在运行52秒…真的丢失了…你的编译器调用是什么?如果你正在运行一个未优化的构建,事情一定会很慢。Armadillo最终调用std::exp(),std::log()等等,这意味着速度问题是用STD::函数(例如,从标准C++库)。这些函数的实现方式取决于每个操作系统和/或编译器。在Windows+VS上,这可能没有那么好。感谢@mtall。我切换到了MinGW64,并以同样令人失望的性能结束。我应该尝试Linux+GCC吗?试着在GCC中使用
-ffast math
选项,这可以放松一些严格的安全限制rantees。通常这会加快程序的速度。否则,您可能会想看看如何使用Intel MKL的函数,该函数可以与犰狳向量和矩阵一起使用。Matlab内部使用MKL,因此您将获得与Matlab相同的性能。