如何确定计划的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。如果一条指令需要两个时钟周期,而另一条指令需要一个时钟周期,后者可以在前者的第一个时钟周期后启动吗?任何帮助,将不胜感激。感谢
答案 0 :(得分:3)
如果你想知道它需要多长时间,你应该测量它。执行循环大约10 ^ 10次,花费它所需的时间并乘以时钟频率。得到周期总数,除以10 ^ 10,得到每次循环迭代的时钟周期数。
执行时间的理论预测几乎永远不会正确(并且大部分时间都是正确的)因为有很多影响决定速度的因素:
cmp
和jl
可能会融合)根据CPU的不同而且所提供的内存访问都是L1缓存,我相信每次迭代循环应该至少需要3个时钟周期,因为最长的依赖链是3个元素长。在较慢的mulss
或addss
指令较慢的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