如何确定CPE:每个元素的周期

时间:2012-05-02 18:09:57

标签: performance architecture assembly x86 sse

如何确定计划的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

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

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

2 个答案:

答案 0 :(得分:3)

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

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

  • 流水线操作(管道中可容纳约20个阶段)
  • 超标量执行(并行最多5条指令,cmpjl可能会融合)
  • 解码为μ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整除。

答案 1 :(得分:0)

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

Intel® 64 and IA-32 Architectures Optimization Reference Manual