性能如何取决于基础数据值
How is performance dependent on the underlying data values
我有以下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
被初始化为[01]范围内的随机数时,与arr2
被初始化为约2/3的值为零的稀疏阵列的情况相比,代码运行速度快约10倍。我使用了编译器选项/fp
和/O
,这稍微改变了运行时间,但大致保持了1:10的比例。
- 为什么性能取决于实际值?CPU做了哪些不同的事情,使稀疏数据的运行速度慢了约10倍
- 有没有办法让"慢数据"运行得更快,或者任何优化(例如向量化计算)对两个数组都有相同的效果(即,"慢数据"仍将比"快数据"运行慢)
编辑
完整代码如下:https://gist.github.com/1676742,用于编译的命令行位于test.cpp
中的注释中。
数据文件在这里:
- https://ccrma.stanford.edu/~itakatz/tmp/I.bin
- https://ccrma.stanford.edu/~itakatz/tmp/I0.bin
这可能是因为你的"快"数据只由正常的浮点数字组成,但你的"慢"数据包含很多非规范化的数字。
至于你的第二个问题,你可以试着用这个来提高速度(并将所有非规范化的数字视为精确的零):
#include <xmmintrin.h>
_mm_setcsr(_mm_getcsr() | 0x8040);
我能想到两个原因。
首先,分支预测器可能正在做出错误的决策。这是在不更改代码的情况下更改数据导致性能差距的一个潜在原因。然而,在这种情况下,这似乎不太可能。
第二个可能的原因是,你的"大部分为零"的数据实际上并不是由零组成,而是由几乎为零组成,或者你将arr1
保持在几乎为零的范围内。请参阅此维基百科链接。
处理来自I.bin的数据需要更长的时间,这并不奇怪:您有很多数字,如"1.401e-045#DEN"或"2.214e-043#DEN’",其中#DEN表示数字无法标准化为标准浮点精度。假设你要把它乘以6.6e-14,你肯定会有下溢异常,这会大大减慢计算速度。
相关文章:
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- Writefile() 无法写入数据,具体取决于数据的长度
- 为什么c++中类的大小取决于数据成员的公共/私有状态
- 初始化数据成员取决于构造函数中的条件
- SVM 训练时间是否取决于输入数据的内容?
- 基类数据成员类型取决于派生类
- 为什么在所有数据类型中,int 取决于操作系统或编译器
- std::unordered_map:渐近{search,insert,remove}性能取决于密钥的大小和数据类型
- 最短路径的dijkstra算法的时间复杂度是否取决于所使用的数据结构?
- 为什么计算时会发生溢出取决于数据类型,而赋值的类型可以容纳它
- 对齐数据:速度取决于恒定数据读取的相对采样大小和采样频率
- 为什么类大小只取决于数据成员而不取决于成员函数
- 性能如何取决于基础数据值