2016-05-13 22 views
2

我有一個關於GCC優化標誌以及它們如何工作的問題。C++ GCC優化當局部變量被複制到全局變量時,速度變慢

我有一段很長的代碼,利用所有本地數組和變量。在代碼的最後,我將本地數組的內容複製到全局數組中。下面是我的代碼非常精簡例如:

uint8_t globalArray[16]={0}; 
void func() 
{ 
    unsigned char localArray[16]={0}; 
    for (int r=0; r<1000000; r++) 
    {  
     **manipulate localArray with a lot of calculations** 
    } 
    memcpy(&globalArray,localArray,16); 
}  

下面的代碼在三個不同的場景近似速度:

  1. 沒有「-O3」優化:3.203s

  2. 隨着 「-O3」 優化:1.457s

  3. 隨着「-O3」優化和最終memcpy(&globalArray,localArray,16);聲明:0.015s

沒有本地陣列複製到全局數組,代碼運行快了近100倍。我知道全局數組存儲在內存中,本地數組存儲在寄存器中。我的問題是:

  1. 爲什麼只複製本地數組的16個元素到一個全局數組導致執行速度降低100倍?我已經搜索了這個論壇和在線,我無法找到這個特定場景的明確答案。

  2. 有沒有什麼辦法可以在沒有速度損失的情況下提取本地變量的內容?

非常感謝任何能幫助我解決這個問題的人。

+6

在情況3中,編譯器可能會刪除所有計算,因爲它們不會導致可觀察的行爲。您可以通過檢查彙編代碼 –

+0

來驗證這一點。您也可以從函數返回localArray指針,這也會阻止編譯器優化整個函數的內容。這會提供更好的比較。 – Conor

+2

@Conor這是未定義的行爲。 – TartanLlama

回答

7

如果沒有memcpy,編譯器可能會看到localArray從不讀取,因此它不需要在循環體中進行任何計算。

以將該代碼作爲一個例子:

uint8_t globalArray[16]={0}; 
void func() 
{ 
    unsigned char localArray[16]={0}; 
    for (int r=0; r<1000000; r++) 
    { 
     localArray[r%16] = r; 
    } 
    memcpy(&globalArray,localArray,16); 
} 

鏘3.7.1與-O3輸出該組件:

func():        # @func() 
# BB#0: 
     xorps %xmm0, %xmm0 
     movaps %xmm0, -24(%rsp) 
     #DEBUG_VALUE: r <- 0 
     xorl %eax, %eax 
.LBB0_1:        # =>This Inner Loop Header: Depth=1 
     #DEBUG_VALUE: r <- 0 
     movl %eax, %ecx 
     sarl $31, %ecx 
     shrl $28, %ecx 
     leal (%rcx,%rax), %ecx 
     andl $-16, %ecx 
     movl %eax, %edx 
     subl %ecx, %edx 
     movslq %edx, %rcx 
     movb %al, -24(%rsp,%rcx) 
     leal 1(%rax), %ecx 
     #DEBUG_VALUE: r <- ECX 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 1(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 1(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     leal 2(%rax), %ecx 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 2(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 2(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     leal 3(%rax), %ecx 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 3(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 3(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     leal 4(%rax), %ecx 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 4(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 4(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     addl $5, %eax 
     cmpl $1000000, %eax   # imm = 0xF4240 
     jne  .LBB0_1 
# BB#2: 
     movaps -24(%rsp), %xmm0 
     movaps %xmm0, globalArray(%rip) 
     retq 

對於相同的代碼而不memcpy,它輸出這樣:

func():        # @func() 
# BB#0: 
     #DEBUG_VALUE: r <- 0 
     retq 

即使你對裝配一無所知,看到後者什麼都不做。

+0

謝謝。完美地回答了它。 –