2013-06-26 59 views
2

我一直在閱讀關於優化代碼中的代碼執行保證的相當多的問題,所以我想編譯一個列表,說明允許/停止編譯器重新排序代碼序列的原因。C++優化中的代碼重新排序在什麼時候停止了?

我已經開始答案,通常是真實的,但我沒有從標準中添加引號(這取自我的經驗)。如果有遺忘或擴大/改正的地方,我會問你是否添加了答案。

此外,有人可以驗證,如果代碼塊不受重新排序。即

void fn() 
{ 
    { /* code block 1 */ ... } 
    { /* code block 2 */ ... } 
} 

是否有可能在代碼code block 1混合或執行之前code block 2

+4

許多優化過程不是在C++語句上完成的,而是在彙編指令或某些編譯器特定的內部表示形式上完成的。在這個級別上,沒有C++塊(甚至是單個語句)的概念,因此優化器肯定可以重新安排塊之間的事情。 –

+1

哪個編譯器?優化工具?版?什麼編譯器標誌? – kfsone

+2

@kfsone我在說話,一般來說,考慮到標準什麼是允許的。 – Adrian

回答

5

該標準爲編譯器重新訂購代碼和進行各種其他優化提供了很多便利。對優化器的唯一真正約束是,執行代碼的可觀察結果應該是'好像'代碼是按程序員寫的順序執行的。只要遵循'as if'規則,編譯器/鏈接器/ CPU /內存子系統可以自由地重新排序他們喜歡的任何東西。變量上的volatile修飾符限制了對該變量進行重新排序(或減少)讀取和寫入的機會,因爲它告訴編譯器它不能對從一次讀取或寫入到另一次讀取或寫入的變量狀態做出任何假設,但通常不會影響對同一段代碼中的其他非易失性變量的讀寫。

C++ 11標準增加了額外的語言,明確說明在多線程的世界中存在什麼保證,事情有點複雜。在這裏,該標準保證了「數據競賽免費程序的連續一致性」。如果程序員使用正確的同步並且不寫任何數據競賽,這實際上就是「如果」規則。如果你的代碼有一個數據競爭,但是當有多個併發執行線程時,如果代碼按照你寫的順序執行,你可能會觀察到不可能的結果。 C++ 11原子和內存屏障提供了向編譯器表達附加約束的途徑,以便在存在多個併發執行線程的情況下安全地執行哪種重新排序。

-1

代碼重新排序相對於其它代碼可能是因爲:執行

  1. 代碼是正交的代碼圍繞它的序列(不依賴於前面的代碼或取決於由將來的代碼)。

代碼不能被重新排序,如果:

  1. 信息,以什麼代碼將修改無法使用編譯器。即調用聲明的函數是可用的,但不是定義。
  2. 訪問易變變量需要它們不能重新排序w.r.t. (但也有額外的限制,它們的值不被編譯器高速緩存,但可能會被硬件高速緩存)。
+1

而不是downvoting沒有說明什麼是錯的,修復它。或者用一個理由downvote。 – Adrian

+1

我沒有downvote,但答案的問題是它沒有真正引用任何C++定義。例如,你是正確的,'volatile'變量不能重新排序,但不能解釋*爲什麼*。 (原因是對volatile變量的讀寫操作是可觀察的,只要可觀察到的行爲是相同的,編譯器就可以做任何事情。)然後繼續討論緩存,這與緩存沒有任何關係C++允許重新排序(只要我們觀察到的內容不會改變,它就是* anything *)。另一個答案是*討論這些C++概念。 – GManNickG

+1

也許更多的「文化」,自我回答的問題通常預計會有很高的質量;這是很長的,儘管與強大的參考和推理。如果你自己回答的話,通常可能忽略質量較低的答案的人可能會被迫下臺。看到我以前的評論爲什麼有人可能認爲這是一個低質量的答案。 – GManNickG