我正在写与犰狳4.500.0一个计划,我体验就地计算,例如s += v * v.t() * q;
有显著慢于同等s = s + v * v.t() * q;
哪里s
,v
以及q
适当大小的矢量。
当我运行以下代码时,发现就位版本比其他版本慢了好几倍,在进行积极优化(-O3或-Ofast; Apple LLVM 6.0版)的情况下,速度降低了500个元素(从5.13秒到0.011秒)降低了480倍。 (clang-600.0.54))。
#include <iostream>
#include <armadillo>
#include <sys/time.h>
using namespace arma;
using namespace std;
#define N_ELEM 500
#define REP 10000
int main(int argc, const char * argv[]) {
timeval start;
timeval end;
double tInplace, tNormal;
vec s = randu<vec>(N_ELEM);
vec v = randu<vec>(N_ELEM);
vec q = randu<vec>(N_ELEM);
gettimeofday(&start, NULL);
for(int i = 0; i < REP; ++i) {
s += v * v.t() * q;
}
gettimeofday(&end, NULL);
tInplace = (end.tv_sec - start.tv_sec + ((end.tv_usec - start.tv_usec) / 1e6));
gettimeofday(&start, NULL);
for(int i = 0; i < REP; ++i) {
s = s + v * v.t() * q;
}
gettimeofday(&end, NULL);
tNormal = (end.tv_sec - start.tv_sec + ((end.tv_usec - start.tv_usec) / 1e6));
cout << "Inplace: " << tInplace << "; Normal: " << tNormal << " --> " << "Normal is " << tInplace / tNormal << " times faster" << endl;
return 0;
}
谁能解释为什么inplace运算符虽然可以使用已经可用的内存,但性能却如此差劲,所以它不需要复制任何内容?
用括号括起来v.t() * q
将解决问题:
for(int i = 0; i < REP; ++i) {
s += v * (v.t() * q);
}
使用方括号强制评估的顺序。该表达式(v.t() * q)
将计算为标量(技术上为1x1矩阵),然后将其用于乘以v
向量。括号也将防止v * v.t()
变成明显的外部产品。
Armadillo可以在使用s = s + v * v.t() * q
表达式时自动解决此问题,但是(当前)在使用inplace运算符时需要更多提示+=
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句