電腦科學中,偽共用(英語:False sharing)是一種會導致效能下降的使用模式,它可能出現在具有分散式快取且維持快取一致性的系統中。當系統參與者嘗試定期訪問未被另一方更改的數據,但欲訪問的數據與正被更改的另一數據共用同一快取塊時,快取協定可能會強制第一個參與者重新載入整個快取塊,儘管在邏輯上這麼做是不必要的。 [1]快取系統不知道此塊內的活動,所以強制第一個參與者承擔資源的真共用訪問(true shared access)所需的快取系統開銷。

多處理器CPU快取

編輯

目前為止,該術語最常見的用法是在現代多處理器CPU快取中,其中主記憶體以 2的較小的(例如,64個對齊、連續的位元組)為單位的快取行的形式進行高速緩衝記憶體。如果兩個處理器對同一主記憶體地址區域中可儲存在單行的獨立數據進行操作,系統中的高速緩衝記憶體一致性機制可能每次數據寫入時都要將整行數據通過匯流排或互連傳輸,除了浪費系統頻寬外,還引發主記憶體停頓。在某些情況下,消除偽共用可以帶來若干數量級的效能改進。 [2]偽共用是自動同步快取協定的原生產物,儘管也可能存在於分散式檔案系統或資料庫等環境中,但目前僅在RAM快取中比較常見。

例子

編輯
#include <thread>
#include <new>
#include <atomic>

using namespace std;

constexpr bool FALSE_SHARING = true;
constexpr size_t
#if defined(__cpp_lib_hardware_interference_size)
	CACHE_LINE_SIZE = hardware_destructive_interference_size,
#else
	CACHE_LINE_SIZE = 64,
#endif
	SECOND_ALIGN = FALSE_SHARING ? sizeof(int) : CACHE_LINE_SIZE;

using atomic_type = atomic<int>;

struct shared_or_not
{
	atomic_type a alignas(CACHE_LINE_SIZE);
	atomic_type b alignas(SECOND_ALIGN);
};

int main()
{
	shared_or_not sharedOrNot;
	auto theThread = []( atomic_type &atomicValue )
	{
		for( size_t r = 100'000'000; r--; )
			++atomicValue;
	};
	jthread
		threadA( theThread, sharedOrNot.a ),
		threadB( theThread, sharedOrNot.b );
}

此 C++20 代碼顯示了偽共用的影響。shared_or_not 的第一個成員 a 始終對齊到快取行的開頭,以防止數據結構跨越快取行,從而造成 a 和 b 被意外拆分,而無法演示偽共用的效果。第二個成員 b 直接放置在同一個快取行中的 a 之後,或者在下一個快取行上對齊,具體取決於 FALSE_SHARING 設置為 true 還是 false。如果 FALSE_SHARING 設置為 false,代碼執行速度通常會快好幾倍。

緩解措施

編輯

有一些方法可以緩解偽共用的影響。例如,可以通過重新排序變數或在變數之間添加填充(未使用的位元組)來防止CPU快取中的偽共用。但是,其中一些更改可能會增加對象的大小,從而導致主記憶體使用量增加。 [2]編譯時數據轉換也可以緩解偽共用。 [3]然而,其中一些轉換可能並不總是被允許的。例如,C++ 23 的 C++ 程式語言標準草案要求對數據成員進行佈局時必須使後面的成員具有更高的地址。 [4]

市面上已有檢測偽共用的工具。 [5] [6]還有一些系統可以檢測和修復執行程式中的偽共用。然而,這些系統會產生一些執行開銷。 [7] [8]

參考資料

編輯
  1. ^ Patterson, David. Computer organization and design: the hardware/software interface. Waltham, MA: Morgan Kaufmann. 2012: 537. ISBN 978-0-12-374750-1. OCLC 746618653. 
  2. ^ 2.0 2.1 Bolosky, William J.; Scott, Michael L. False sharing and its effect on shared memory performance. Sedms'93: USENIX Systems on USENIX Experiences with Distributed and Multiprocessor Systems. 1993-09-22, 4 [11 July 2021]. (原始內容存檔於2023-01-20). 
  3. ^ Jeremiassen, Tor E.; Eggers, Susan J. Reducing false sharing on shared memory multiprocessors through compile time data transformations. ACM SIGPLAN Notices (Association for Computing Machinery (ACM)). 1995, 30 (8): 179–188. ISSN 0362-1340. doi:10.1145/209937.209955 . 
  4. ^ Working Draft, Standard for Programming Language C++ [class]. eel.is. [2021-07-11]. (原始內容存檔於2023-02-02). 
  5. ^ perf-c2c(1). Linux manual page. 2016-09-01 [2021-08-08]. (原始內容存檔於2023-01-18). 
  6. ^ Chabbi, Milind; Wen, Shasha; Liu, Xu. Featherlight on-the-fly false-sharing detection. New York, NY, USA: ACM. 2018-02-10. doi:10.1145/3178487.3178499. 
  7. ^ Nanavati, Mihir; Spear, Mark; Taylor, Nathan; Rajagopalan, Shriram; Meyer, Dutch T.; Aiello, William; Warfield, Andrew. Whose cache line is it anyway?. New York, New York, USA: ACM Press. 2013. doi:10.1145/2465351.2465366. 
  8. ^ Liu, Tongping; Berger, Emery D. SHERIFF: precise detection and automatic mitigation of false sharing. ACM SIGPLAN Notices (Association for Computing Machinery (ACM)). 2011-10-18, 46 (10): 3–18. ISSN 0362-1340. doi:10.1145/2076021.2048070. 

外部連結

編輯