0

例如,假設我們有像下面的代碼,其中d是一個字典或其它數據結構針對索引是非平凡:在多線程的情況下,某些編譯器優化是否無效?

x = d[a] 
y = d[b] 
z = (x + y) * (x + y) 
return z + d[a] 

可能會優化編譯器的最後一行有效地改變到return z + x

如果是這樣,這個優化在多線程的情況下是無效的嗎?當該線程正在計算z的值時,如果另一個線程更改了d[a]的值(甚至是類型),會發生什麼情況?

+1

是的。 UB有另一個線程修改值而不提供必要的同步。 –

+0

@HansPassant +1,它必須是UB,因爲獲取值d [a]可能需要幾條指令,並且如果在中間被中斷,將返回一半修改後的數據 –

+0

直接支持線程的語言(而不是作爲附加組件)必須在這裏定義整個語義。將它作爲附加組件的語言通常會提供某種附加同步或屏障操作,然後必須提供一種方法來確保編譯器不會進行無效優化。考慮一下,例如,提供線程本地存儲的語言(你可以聲明d本身,也許所有存儲的項目都是線程本地的,因此優化是有效的)。 – torek

回答

0

這個問題合併了多個。

1:線程

在運行時創建。因此編譯器可能不知道有多少線程存在。他們假定多個線程可以隨時出現。因此,這組優化不受程序級別的線程數量的影響。但是,是的,它在編譯器級受到影響。編譯器必須考慮到數據競爭的威脅。至少對於較老的編程語言。在現代編程語言技術中,這個問題處理的是靜態類型系統的強度[見Rust]functional purity

2:即使在確保沒有穿線的情況下,您具體提到的優化類型看起來也很困難。在其完整的普遍性[「非平凡索引」中]:它要求優化器識別表達式之間的等式。我懷疑這在大多數編譯器中並沒有完成,因爲它需要運行時間。

+0

*「因此,編譯器可能不知道有多少線程存在。」*這怎麼可能是真的?編譯器生成代碼來創建線程,因此它肯定知道有多少。 *「這種優化......看起來很難......它要求優化器識別表達式之間的等式。」*呃,C和C++編譯器會定期執行這樣的優化。它並不像你想象的那麼困難,並不是你一旦將樣板代碼內聯並將所有東西壓縮到抽象語法樹中。 –

+0

@ [Cody Gray]編譯器(至少是C/C++編譯器 - 不知道JIT編譯器)不能分辨正在運行的線程的數量,因爲這隻在運行時才被知道。 – valiano

+0

@valiano,這沒有任何意義。編譯器必須發出啓動線程的代碼,因此它確切知道已啓動了多少個線程。你是否正在討論*不同應用程序中的線程*?如果是這樣,我看不出與這個問題有什麼關係。 –

相關問題