最近我遇到了英特爾TBB可擴展分配器的問題。基本使用模式是作爲以下,緩存對齊英特爾CPU上的內存分配
- 大小
N * sizeof(double)
的幾個矢量分配 - 生成一個隨機整數
M
使得M >= N/2 && M <= N
。 - 訪問每個向量的第一個
M
元素。 - 重複第2步1000次。
我將M
設爲隨機,因爲我不想將基準性能定爲固定長度。相反,我想獲得一系列矢量長度的平均性能。
對於不同的值N
,程序性能差別很大。這並不罕見,因爲我測試的功能旨在優先考慮大型N
的性能。但是,當我試圖對性能和N
之間的關係進行基準測試時,我發現在某個點上,當N
從1016
增加到1017
時,會有兩倍的差異。
我的第一個直覺是N = 1016
的性能變差與較小的向量大小無關,而是它有一定的緩存。很有可能存在虛假分享。品嚐下的功能使用SIMD指令,但不使用堆棧內存。它從第一個向量中讀取一個32字節的元素,並在計算之後,它將第二個(和第三個)向量寫入32個字節。如果發生虛假共享,可能會丟失幾十個週期,這正是我觀察到的性能損失。一些分析證實了這一點。
本來我將每個向量與32字節邊界對齊,用於AVX指令。爲了解決這個問題,我將矢量與64字節的邊界對齊。但是,我仍然觀察到相同的性能損失。通過128字節對齊解決問題。
我做了一些更多的挖掘。英特爾TBB有一個cache_aligned_allocator
。在它的源代碼中,內存也由128字節對齊。
這是我不明白。如果我沒有弄錯,現代的x86 CPU有一個64字節的緩存行。 CPUID
證實了這一點。以下是正在使用的CPU,從我寫使用CPUID檢查功能的小程序提取的基本緩存信息,
Vendor GenuineIntel
Brand Intel(R) Core(TM) i7-4960HQ CPU @ 2.60GHz
====================================================================================================
Deterministic Cache Parameters (EAX = 0x04, ECX = 0x00)
----------------------------------------------------------------------------------------------------
Cache level 1 1 2 3 4
Cache type Data Instruction Unified Unified Unified
Cache size (byte) 32K 32K 256K 6M 128M
Maximum Proc sharing 2 2 2 16 16
Maximum Proc physical 8 8 8 8 8
Coherency line size (byte) 64 64 64 64 64
Physical line partitions 1 1 1 1 16
Ways of associative 8 8 8 12 16
Number of sets 64 64 512 8192 8192
Self initializing Yes Yes Yes Yes Yes
Fully associative No No No No No
Write-back invalidate No No No No No
Cache inclusiveness No No No Yes No
Complex cache indexing No No No Yes Yes
----------------------------------------------------------------------------------------------------
此外,英特爾TBB的源代碼,128個字節對齊的特點是評論這是爲了向後兼容。
那麼爲什麼在我的情況下64字節對齊不夠?
感謝您的詳細說明。這是我知道的,儘管解釋得更清楚。然而,如果不增加分配的內存大小,是否有辦法避免這種衝突呢?我的印象是,通過對齊63字節的邊界足以避免兩個向量在大多數情況下共享相同的緩存行。相反,我觀察到需要128字節的對齊方式 –
感謝您的圖表和鏈接。我會先閱讀一下。 –
對齊並不重要,因爲它是set-associativesnes,這是問題在這裏,意思是向量使用的總內存。 – Surt