Performance 如何确定CPE:每个元素的周期
如何确定程序的CPE? 例如,我有一个循环的汇编代码:Performance 如何确定CPE:每个元素的周期,performance,architecture,assembly,x86,sse,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
# 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
#inner4:data\u t=float
#%rbx中的udata,%rax中的vdata,%rcx中的限制,
#i以%rdx表示,总和以%xmm1表示
1.L87:#循环:
2个movss(%rbx,%rdx,4),%xmm0#获取udata[i]
3乘(%rax,%rdx,4),%xmm0乘以vdata[i]
4添加%xmm0,%xmm1#添加到总和
5增加1美元,增加1%rdx
6 cmpq%rcx%rdx#比较i:极限
7 jl.L87#如果您运行的是Intel CPU,您可以找到一些关于各种CPU的指令延迟和吞吐量的好文档。以下是链接:
如果你想知道它需要多长时间,你应该测量它。执行循环大约10^10次,取所需时间乘以时钟频率。得到循环总数,除以10^10得到每个循环迭代的时钟周期数
执行时间的理论预测几乎永远不会正确(大部分时间都很低),因为决定速度的因素很多:
- 管道(管道中可能有20个阶段)
- 超标量执行(最多可并行执行5条指令,
cmp
和jl
)
- 解码到µOps并重新排序
- 缓存或内存的延迟
- 指令的吞吐量(是否有足够的空闲执行端口)
- 指令的延迟
- 银行冲突、别名问题和更深奥的东西
根据CPU的不同,如果内存访问全部命中一级缓存,我认为循环每次迭代至少需要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
.L87:#循环:
vmovdqa(%rbx,%rdx,4),%ymm0#获取udata[i]…udata[i+7]
vmulps(%rax,%rdx,4),%ymm0,%ymm0乘以vdata[i]…vdata[i+7]
vaddps%ymm0,%ymm1,%ymm1#相加
增加8美元,增加1%rdx
cmpq%rcx,%rdx#比较i:极限
jl.L87#如果这是一个很难回答的问题,因为所需的周期非常依赖于目标cpu。对于一条指令,不同的CPU可能需要不同数量的周期。一些CPU可能能够在并行管道中无序地运行某些指令(如line5+6,而4正在等待3的结果),而其他CPU则不能。