【问题标题】:Armadillo inplace_plus significantly slower than "normal" plus operation犰狳 inplace_plus 明显慢于“正常”加操作
【发布时间】:2014-11-05 20:50:09
【问题描述】:

我正在使用 Armadillo 4.500.0 编写程序,并且我体验到诸如 s += v * v.t() * q; 之类的就地计算比等效的 s = s + v * v.t() * q; 慢得多,其中 svq 是大小合适。

当我运行以下代码时,结果发现就地版本比其他版本慢很多倍,对于 500 个元素,速度慢了约 480 倍(5.13 秒到 0.011 秒),并进行了积极优化(-O3 或 -Ofast;Apple LLVM 版本 6.0 (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 运算符的性能如此糟糕,尽管它可以使用已经可用的内存,所以它不需要复制任何东西?

【问题讨论】:

  • 测试未经优化编译的代码的性能会得到愚蠢的结果。通过优化进行测试,谜团可能会消失。有些函数在没有优化的情况下编译会慢数百倍。
  • @Schwartz:感谢您的提示,但即使采用积极优化(-O3 或 -Ofast),性能差异也约为 480 倍(5.13 秒到 0.011 秒)(我相应地更新了问题)。
  • @DavidK - 也​​许向 Armadillo 开发人员发送错误报告?

标签: c++ performance armadillo


【解决方案1】:

v.t() * q 周围加上括号可以解决问题:

for(int i = 0; i < REP; ++i) {
    s += v * (v.t() * q);
}

使用括号强制计算顺序。表达式 (v.t() * q) 将计算为一个标量(技术上是一个 1x1 矩阵),然后用于乘以 v 向量。方括号还可以防止 v * v.t() 变成显式的外部产品。

犰狳可以在使用s = s + v * v.t() * q 表达式时自动解决这个问题,但在使用就地运算符+= 时它(当前)需要更多提示。

【讨论】:

  • 谢谢,就像一个魅力!它甚至比我为解决它而编写的手动循环快约 10%。但由于我也必须先对向量进行范数,因此手动循环比使用两个版本中的任何一个都快 1.4 倍,因为我可以同时计算 v 和点积 v.t() * q 的范数。
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
相关资源
最近更新 更多