4

在试图弄清楚我的代码的内部循环是否遇到了硬件设计障碍或对我的部分障碍缺乏理解。还有更多内容,但我能想到的最简单的问题如下:

如果我有以下代码:

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];
  } }

在我完全控制代码(汇编、内在函数等)但无法控制架构以外的运行时环境(即它是一个多用户环境,所以我无法对操作系统内核如何为我的特定进程分配时间做任何事情)。

现在我看到我的代码速度提高了 3 倍,而我本以为使用 SSE 会给我带来比 3 倍加速所指示的更多的向量深度(大概 3 倍加速告诉我我有 4 倍的最大理论值)吞吐量)。(我尝试过让 deltx/delty/deltz 成为数组,以防编译器不够聪明而无法自动提升它们,但我仍然看到只有 3 倍的速度。)我正在使用英特尔 C 编译器用于矢量化的适当编译器标志,但显然没有内在函数。

4

4 回答 4

4

这取决于 CPU。但理论上的最大值不会超过 4 倍。我不知道每个时钟周期可以执行多个 SSE 指令的 CPU,这意味着它每个周期最多可以计算 4 个值。

大多数 CPU每个周期至少可以执行一条浮点标量指令,因此在这种情况下,您会看到理论上的最大值为 4 倍加速。

但是您必须查看正在运行的 CPU 的特定指令吞吐量。

不过,实际的 3 倍加速已经相当不错了。

于 2009-09-23T15:58:49.567 回答
2

我认为您可能不得不以某种方式交错内部循环。3 分量向量一次完成,但一次只有 3 个操作。要达到 4,您将从第一个向量执行 3 个分量,从下一个向量执行 1 个分量,然后是 2 和 2,依此类推。如果您建立了某种队列,一次加载和处理 4 个数据组件,然后将其分开,那可能会起作用。

编辑:您可以展开内部循环以每次迭代执行 4 个向量(假设数组大小始终是 4 的倍数)。这将完成我上面所说的。

于 2009-09-23T15:59:34.933 回答
1

考虑:浮子有多宽?SSEx 指令有多宽?该比率应该为您提供某种合理的上限。

还值得注意的是,乱序管道对获得良好的加速估计有很大影响。

于 2009-09-23T16:00:07.293 回答
1

您应该考虑循环平铺- 您在内部循环中访问值的方式可能会导致 L1 数据缓存中出现大量抖动。这还不错,因为所有内容可能仍然适合 384 KB 的 L2,但是 L1 缓存命中和 L2 缓存命中之间很容易存在一个数量级的差异,因此这可能会对您产生很大的影响。

于 2009-10-10T20:05:23.903 回答