3

如何确定课程的 CPE?例如,我有一个循环的汇编代码:

# inner4: data_t = float
# udata in %rbx, vdata in %rax, limit in %rcx,
# i in %rdx, sum in %xmm1
1 .L87:                                   # loop:
2   movss  (%rbx,%rdx,4), %xmm0           #  Get udata[i]
3   mulss  (%rax,%rdx,4), %xmm0           #  Multiply by vdata[i]
4   addss  %xmm0, %xmm1                   #  Add to sum
5   addq  $1, %rdx                        #  Increment i
6   cmpq  %rcx, %rdx                      #  Compare i:limit
7   jl .L87                               #  If <, goto loop

我必须使用数据类型浮点数找到由关键路径确定的 CPE 的下限。我相信关键路径是指可能的最慢路径,因此是程序必须执行 mulss 指令的路径,因为它占用了最长的时钟周期数。

但是,似乎没有任何明确的方法来确定 CPE。如果一条指令需要两个时钟周期,而另一条需要一个时钟周期,那么后者可以在前者的第一个时钟周期之后开始吗?任何帮助,将不胜感激。谢谢

4

2 回答 2

4

如果你想知道它需要多长时间,你应该测量它。执行循环大约 10 ^ 10 次,花费它需要的时间并乘以时钟频率。你得到周期的总数,除以 10^10 得到每个循环迭代的时钟周期数。

执行时间的理论预测几乎永远不会是正确的(而且大部分时间都是低的),因为决定速度的因素有很多:

  • 流水线(流水线中很容易有大约 20 个阶段)
  • 超标量执行(最多并行 5 条指令,cmp并且jl可以融合)
  • 解码为 µOps 并重新排序
  • 缓存或内存的延迟
  • 指令的吞吐量(是否有足够的空闲执行端口)
  • 指令的延迟
  • 银行冲突、别名问题和更深奥的东西

根据 CPU 和内存访问都命中 L1 缓存,我相信循环每次迭代至少需要 3 个时钟周期,因为最长的依赖链是 3 个元素长。在较慢mulssaddss指令较慢的旧 CPU 上,所需时间会增加。

如果您真的对加速代码感兴趣,而不仅仅是一些理论观察,您应该对其进行矢量化。您可以使用类似的方法将性能提高 4-8 倍

.L87:                               # loop:
vmovdqa (%rbx,%rdx,4), %ymm0        #  Get udata[i]..udata[i+7]
vmulps  (%rax,%rdx,4), %ymm0, %ymm0 #  Multiply by vdata[i]..vdata[i+7]
vaddps  %ymm0, %ymm1, %ymm1         #  Add to sum
addq    $8, %rdx                    #  Increment i
cmpq    %rcx, %rdx                  #  Compare i:limit
jl .L87                             #  If <, goto loop

之后您需要水平添加所有 8 个元素,当然要确保对齐为 32 并且循环计数器可被 8 整除。

于 2012-05-02T23:36:29.437 回答
0

如果您运行的是 Intel CPU,您可以找到一些关于各种 CPU 的指令延迟和吞吐量的优秀文档。这是链接:

英特尔® 64 和 IA-32 架构优化参考手册

于 2012-05-02T22:44:28.387 回答