我们的软件之一是使用 Eigen (3.2.5)来执行一些基质/矢量相关的计算。该软件在这方面进行了仔细开发,首先禁用所有选项和优化(包括使用-DEIGEN_DONT_VECTORIZE
),并设置准确性测试。
由于我们现在对更快的数值吞吐量感兴趣,我们已经开始在Eigen中启用矢量化。但是,我们注意到我们的一个测试现在提供了稍微不同的输出:与参考实现的差异大约为1e-4
,而之前为1e-5
。
我们将在这个测试中放松一点精度(因为我们并不真正知道参考数据的准确性,我们还有另一个合成数据的测试用例,我们有一个确切的解决方案,但仍然但是出于好奇:这种变化可能是什么原因?
如果它是相关的,这个计算涉及欧几里德规范。
答案 0 :(得分:3)
这是必须的,因为当您启用矢量化时,浮点运算不会以完全相同的顺序执行。这通常发生在涉及减少的表达式中,例如求和,范数,矩阵乘积等。例如,让我们考虑以下简单的总和:
float s = 0;
for(int i=0;i<n;i++)
s += v[i];
矢量化版本可能看起来像(伪代码):
Packet ps = {0,0,0,0};
for(int i=0;i<n;i+=4)
ps += load_packet(&v[i]);
float s = ps[0]+ps[1]+ps[2]+ps[3];
由于舍入错误,每个版本将返回不同的值。在Eigen中,这方面更加棘手,因为缩减是以最大化指令流水线的方式实现的。