为什么此程序的自动矢量化版本比简单版本慢

时间:2016-01-12 10:56:14

标签: c++ performance visual-c++ vectorization

在更大的数值计算中,我必须执行总结两个向量元素的乘积的微不足道的任务。由于此任务需要经常进行,因此我尝试使用编译器(VC2015)的自动矢量化功能。我引入了一个临时向量,其中产品保存在第一个循环中,然后在第二个循环中执行求和。优化设置为完整,快速代码是首选。这样,第一个循环由编译器进行矢量化(我从编译器输出中知道这一点)。

结果令人惊讶。矢量化代码在我的机器(核心i5-4570 3.20 GHz)上比简单代码慢3倍。任何人都可以解释为什么以及可能改善性能的原因?我已将算法片段的两个版本放入一个最小的运行示例中,我自己用于测试:

index_room_number

1 个答案:

答案 0 :(得分:3)

通过将产品存储在临时载体中,您添加了大量工作。

对于大数据的这种简单计算,您希望通过矢量化保存的CPU时间并不重要。只有内存引用很重要。

您添加了内存引用,因此运行速度较慢。

我原本希望编译器优化该循环的原始版本。我怀疑优化会影响执行时间(因为无论如何它都由内存访问控制)。但它应该在生成的代码中可见。如果你想像这样手动优化代码,临时向量总是错误的方法。正确的方向如下(为简单起见,我假设size是偶数):

for (int p = 0; p < size; p+=2)
{
    v += tt[p] * dd[p];
    v1 += tt[p+1] * dd[p+1];
}
v += v1;

请注意,您的数据足够大且操作非常简单, NO 优化应该能够在最简单的版本上进行改进。这包括我的样本手优化。但我认为你的测试并不能完全代表你真正想做或理解的事情。因此,对于较小的数据或更复杂的操作,我展示的方法可能会有所帮助。

另请注意,我的版本依赖于添加是可交换的。对于实数,加法是可交换的。但在浮点方面,它并不是。答案很可能因为你太小而无法照顾的数量而有所不同。但这与数据有关。如果你在原始序列的早期有奇数/偶数位置相反的相反符号的大值,那么通过分离偶数和奇数位置我的优化&#34;会完全破坏答案。 (当然,相反的情况也可能是正确的。例如,如果所有偶数位置都很小并且赔率包括相互抵消的大值,则原始序列产生垃圾并且更改的序列将更正确。)