试图弄清楚我的代码的内循环是否会遇到硬件设计障碍或者我的部分障碍缺乏理解。还有一点,但我能回答的最简单的问题如下:
如果我有以下代码:
float px[32768],py[32768],pz[32768];
float xref, yref, zref, deltax, deltay, deltaz;
initialize_with_random(px);
initialize_with_random(py);
initialize_with_random(pz);
for(i=0;i<32768-1;i++) {
xref=px[i];
yref=py[i];
zref=pz[i];
for(j=0;j<32768-1;j++ {
deltx=xref-px[j];
delty=yref-py[j];
deltz=zref-pz[j];
} }
在我完全控制代码(程序集,内在函数,无论如何)的情况下,通过转到SSE指令,我可以看到什么类型的最大理论加速,但是除了体系结构之外没有对运行时环境的控制(即,它是一个多用户环境,所以我无法对操作系统内核如何为我的特定进程分配时间做任何事情。)
现在我看到我的代码加速了3倍,当我想到使用SSE会给我更多的矢量深度比3倍加速指示(可能是3倍加速告诉我我有一个4倍最大理论吞吐量)。 (我已经尝试过让deltx / delty / deltz成为数组,以防编译器不够智能自动提升它们,但我仍然看到只有3倍加速。)我正在使用intel C编译器适用于矢量化的编译器标志,但显然没有内在函数。
答案 0 :(得分:4)
这取决于CPU。但理论上的最大值不会高于4倍。我不知道每个时钟周期可以执行多个SSE指令的CPU,这意味着它最多每个周期计算4个值。
大多数CPU每个周期至少至少一个浮点标量指令,所以在这种情况下你会看到理论上最大加速度为4倍。
但是您必须查找正在运行的CPU的特定指令吞吐量。
实际的3倍加速是非常好的。
答案 1 :(得分:2)
我认为你可能不得不以某种方式交错内循环。 3分量矢量一次完成,但这只是一次3个操作。要达到4,你将从第一个向量中做3个组件,从下一个向量做1个组件,然后是2和2,依此类推。如果您建立了某种类型的队列,一次加载和处理数据4组件,那么之后将其分开,这可能会有效。
编辑:您可以展开内部循环,每次迭代执行4个向量(假设数组大小始终是4的倍数)。这将完成我上面所说的。
答案 2 :(得分:1)
考虑:浮子有多宽? SSEx指令有多宽?这个比例应该给你一些合理的上限。
值得注意的是,无序管道在获得加速预测方面发挥了重要作用。
答案 3 :(得分:0)
您应该考虑loop tiling - 您在内循环中访问值的方式可能会导致L1数据缓存中的大量颠簸。这并不算太糟糕,因为所有内容可能仍然适用于384 KB的L2,但是在L1缓存命中和L2缓存命中之间容易产生一个数量级的差异,所以这可能会对你产生很大的影响。