【问题标题】:How is performance dependent on the underlying data values性能如何依赖于基础数据值
【发布时间】:2012-01-25 15:00:52
【问题描述】:

我有以下C++代码sn-p(C++部分是profiler类,这里省略),用VS2010(64位Intel机器)编译。该代码只是将浮点数数组 (arr2) 与一个标量相乘,然后将结果放入另一个数组 (arr1):

int M = 150, N = 150;
int niter = 20000; // do many iterations to have a significant run-time
float *arr1 = (float *)calloc (M*N, sizeof(float));
float *arr2 = (float *)calloc (M*N, sizeof(float));

// Read data from file into arr2

float scale = float(6.6e-14);

// START_PROFILING
for (int iter = 0; iter < niter; ++iter) {
    for (int n = 0; n < M*N; ++n) {         
        arr1[n] += scale * arr2[n];
    }
}
// END_PROFILING

free(arr1);
free(arr2); 

为简单起见,此处省略了从文件读取部分和分析(即运行时测量)。

arr2 被初始化为[0 1] 范围内的随机数时,与arr2 被初始化为稀疏数组的情况相比,代码的运行速度大约快10 倍,其中大约2/3 的值为零。我玩过编译器选项/fp/O,它们稍微改变了运行时间,但大约保持了1:10 的比例。

  • 为什么性能取决于实际值? CPU 有何不同之处使稀疏数据的运行速度慢了约 10 倍?
  • 有没有办法让“慢数据”运行得更快,或者任何优化(例如向量化计算)对两个数组都有相同的效果(即“慢数据”仍然会比“快数据”运行得更慢数据”)?

编辑

完整代码在这里:https://gist.github.com/1676742,用于编译的命令行在test.cpp的注释中。

数据文件在这里:

【问题讨论】:

  • 请您提供两个测试的完整、可编译的版本,以便我们进行实验?
  • 会不会是当您将0 传递给稀疏矩阵中的浮点数时,从intfloat 的转换会引入一些开销?
  • 你只更新不为0的元素?那么,会不会是零不在缓存中呢?
  • @duedl0r:我也有这个想法。但是,此参数仅适用于 20,000 的第一次迭代,因为加法循环遍历整个数组。
  • @aix:嗯,是的,你可能是对的。但是你永远不知道编译器会生成 :) 在这种情况下,他可以切换 for 循环,所以 niter 循环是内部循环,不是吗?如果他真的疯了,也许他甚至会生成arr1[n] += niter * scale * arr2[n] ;)

标签: c++ c performance visual-studio-2010


【解决方案1】:

这可能是因为您的“快速”数据仅包含正常的浮点数,但您的“慢速”数据包含大量非规范化数字。

至于您的第二个问题,您可以尝试以此提高速度(并将所有非规范化数字视为精确零):

#include <xmmintrin.h>
_mm_setcsr(_mm_getcsr() | 0x8040);

【讨论】:

    【解决方案2】:

    我可以想到两个原因。

    首先,分支预测器可能会做出错误的决定。这是由于数据更改而不更改代码而导致性能差距的潜在原因之一。但是,在这种情况下,这似乎不太可能。

    第二个可能的原因是您的“大部分为零”数据实际上并非由零组成,而是几乎为零,或者您将arr1 保持在几乎为零的范围内。见this Wikipedia link

    【讨论】:

      【解决方案3】:

      处理来自 I.bin 的数据需要更长的时间并不奇怪:您有很多数字,例如“1.401e-045#DEN”或“2.214e-043#DEN”,其中#DEN 表示该数字不能标准化为标准浮点精度。鉴于您要将它乘以 6.6e-14,您肯定会出现下溢异常,这会显着减慢计算速度。

      【讨论】:

        猜你喜欢
        • 2014-11-20
        • 2012-03-28
        • 2015-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-23
        • 2020-05-31
        • 2017-11-11
        相关资源
        最近更新 更多