2012-05-02 22 views
1

如何確定程序的CPE? 例如,我有這樣的彙編代碼爲一個循環:如何確定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。如果一條指令需要兩個時鐘週期,另一條指令需要一條指令,那麼後者可以在前一個時鐘週期之後啓動?任何幫助,將不勝感激。謝謝

+1

這是一個難以回答的問題,因爲所需的週期非常依賴於目標CPU。對於單個指令,不同的cpus可能需要不同的週期數。某些CPU可能能夠在並行流水線中亂序執行某些指令(如line5 + 6,而4正在等待3的結果),而另一些則不能。 –

回答

2

如果你想知道它需要多長時間,你應該衡量它。執行循環約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