計算機科學中,偽共享(英語: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. 

外部連結

編輯