我有以下C ++代码片段(C ++部分是此处省略的分析器类),使用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倍/ 3的值为零。我使用了编译器选项/fp
和/O
,它们稍微改变了运行时间,但是大约保持了1:10的比率。
修改
完整代码在此处:https://gist.github.com/1676742,用于编译的命令行位于test.cpp
的注释中。
数据文件在这里:
答案 0 :(得分:7)
可能这是因为你的“快速”数据只包含正常的浮点数,但你的“慢”数据包含大量非规范化数字。
至于你的第二个问题,你可以尝试用这个提高速度(并将所有非规范化数字视为精确零):
#include <xmmintrin.h>
_mm_setcsr(_mm_getcsr() | 0x8040);
答案 1 :(得分:2)
我可以想到两个原因。
首先,分支预测器可能做出错误的决定。这是由数据更改引起的性能差距的一个潜在原因,无需更改代码。但是,在这种情况下,似乎不太可能。
第二个可能的原因是你的“大部分零”数据并不真正由零组成,而是几乎为零,或者你将arr1
保持在几乎为零的范围内。请参阅this Wikipedia link。
答案 2 :(得分:1)
来自I.bin的数据需要更长的处理时间并不奇怪:你有很多数字,比如'1.401e-045#DEN'或'2.214e-043 #DEN',其中#DEN表示数字不能标准化为标准浮点精度。鉴于你要将它乘以6.6e-14,你肯定会有下溢异常,这会大大减慢计算速度。