快取與交錯記憶體存取

最後更新: 2022-02-05 06:59:45 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

如果一個執行緒設定已清零陣列中的所有奇數位元,而另一個執行緒設定所有偶數位元,記憶體中會包含什麼?

簡短答案 #

除非更新是原子的,否則最終值並不確定。在 C 和 C++ 中,未同步地並行寫入同一儲存位置會形成資料競爭,因此程式具有未定義行為。

快取一致性會維持不同核心之間快取行的一致,但不會將 read-modify-write 序列轉換成單一不可分割的操作。如果兩個執行緒使用一般儲存操作更新同一個位元組或字組中的不同位元,其中一個更新可能覆寫另一個更新,因為兩個執行緒都可能讀取相同的舊值,在本機修改後,再寫回過時的副本。

為什麼快取行無法解決競爭 #

一致性協定以快取行為粒度運作。這會影響效能,因為存取同一快取行的兩個執行緒會反覆轉移其擁有權。

但這不會影響正確性,因為競爭發生在快取協定之上:

  1. 執行緒 A 讀取共享字組。
  2. 執行緒 B 讀取相同的字組。
  3. A 設定自己的位元並寫回。
  4. B 根據過時的值設定自己的位元並寫回。

對於它所寫入的位元組,最後一次寫入會生效,因此較早的位元更新可能會消失。

結果穩定的情況 #

如果每次更新都是原子的位元運算,結果就會變得確定:

c
atomic_fetch_or_explicit(&word, mask, memory_order_relaxed);

在這種情況下,硬體和語言執行階段會將對共享字組的修改序列化,因此最終值會成為所有更新的位元 OR 結果。

當每個執行緒寫入互不重疊的位元組、字組或快取行時,也會得到相同的結果。重要的不是「奇數位元與偶數位元」;重要的是兩個寫入是否可能在機器以原子方式更新的儲存單元上發生重疊。

實務規則 #

  • 對於封裝的位元集合,使用原子的 read-modify-write 操作。
  • 對於高並行的計數器或旗標,將資料分割,使執行緒不會共用同一個快取行。
  • 進行一般效能最佳化時,請記住,即使邏輯資料互不重疊,false sharing 仍會降低輸送量。

評論

在 GitHub 上閱讀或評論(發表評論需要登入)