【问题标题】:Why is std::inner_product slower than the naive implementation?为什么 std::inner_product 比天真的实现慢?
【发布时间】:2017-08-22 02:44:48
【问题描述】:

这是我对点积的幼稚实现:

float simple_dot(int N, float *A, float *B) {
    float dot = 0;
    for(int i = 0; i < N; ++i) {
    dot += A[i] * B[i];
    }

    return dot;
}

这是使用 C++ 库:

float library_dot(int N, float *A, float *B) {
    return std::inner_product(A, A+N, B, 0);
}

我跑了一些基准测试(代码在这里https://github.com/ijklr/sse),库版本慢了很多。 我的编译器标志是-Ofast -march=native

【问题讨论】:

  • 使用0.0f作为初始值。
  • 如果在对 inner_product 的调用中将 0 更改为 0f 会发生什么?
  • 您应该能够查看库实现,因为它是一个模板。
  • 我现在就试试。
  • @NathanOliver:编译器错误,因为f 不是有效的八进制数字。

标签: c++ floating-point sse numeric fast-math


【解决方案1】:

你的两个函数做的不是同一件事。该算法使用一个累加器,其类型是从初始值推导出,在您的情况下(0)是int。将浮点数累积到 int 不仅比累积到浮点数花费更长的时间,而且还会产生不同的结果。

原始循环代码的等价物是使用初始值0.0f,或等价于float{}。

(注意std::accumulate在这方面非常相似。)

【讨论】:

  • 谢谢。这有帮助!
  • GCC 不会展开循环,-funroll-loops 不会破坏依赖链。 Clang 展开 4 次,这很棒。所以至少使用 GCC std::inner_product 不是最优的,即你必须手动优化减少。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 2013-01-10
  • 2017-07-22
相关资源
最近更新 更多