高效能運算-探究迴圈分塊最佳化cache miss(13)(接2-1)

安洛8發表於2024-11-24

1. 目標:分析迴圈分塊最佳化技術,並分析cache 命中情況

假設每個cacheline可以儲存b個資料元素。

2. 原始碼分析

for( int i=0;i<N;i++)
{
	for(int j=0;j<M;j++)
	{
		A[i] += B[j];
	}
}

cache miss分析:

對A總訪問次數為 NM,每次訪存載入一個cacheline 可以載入b個元素,並且連續訪問,該cacheline所有元素在依次被訪問前不會被替換掉,共需訪存載入cacheline N/b次,每次載入都有一次miss,所以A共有N/b次miss;對B共訪問 NM次,當M足夠大時,cache無法裝載整個陣列B,內層一次迴圈需訪存M/b次,N個迴圈共訪存載入cacaheline NM/b次,每載入一次cacheline有一次miss,所以B在全部迴圈中 miss NM/b。總共 N/b + NM/b次 miss。

3. 迴圈分塊最佳化

原理:原始碼中對B的訪問miss過高,B cacheline被反覆載入,考慮提高B cacheline 載入一次的利用效率,可考慮每載入一次,完成相應所有A元素的訪問,假設L1 cache可以滿足 A所有元素 cacheline 遍歷和 若干組 B cacheline 的計算需求;載入 B cacheline 組的數量不應太大,假設裡面包含了 T 個元素應有 T=nb , T,b << M,N。保證訪問B[T-1]時,B[0]仍在 cache 中。

程式碼思路:對高miss 資料的訪問索引分塊,作為最外層迴圈控制變數,並在最內層迴圈控制塊內迴圈。

for(int j=0;j<M;j+=T)
{
	for(int i=0;i<N;i++)
	{
		for(int t=0;t<T;t++)
			A[i] += B[j]; 
	}
}

cache miss分析:

A元素索引i的訪問在內2層迴圈,每次迴圈共訪問N次,每次訪問一個cacheline有一個misss,所以每次迴圈有N/b個不命中,由於j是分塊訪問,共有 M/b個迴圈,所以A元素miss為 N/b *(M/T);B元素的訪問最內層迴圈每次迴圈有 T/b個miss,T的取值為b的倍數並且不能太大,當訪問B[T-1]時B[0]仍在cache中,對於第二層i的遍歷,此時B[j]元素都在cache中,不影響第三層B元素 miss 數量,共有 M/T 次迴圈,所有B元素miss為 T/b *(M/T) = M/b。總共 MN/bT + M/b 次 miss。

4. 對比總結

分塊前後AB全部miss比為(N/b+MN/b)/ (MN/bT + M/b) ,當MN足夠大時,計算極限得 T。

分塊後 A的miss增加,B的miss減少,總misss數為原來的 1/T。

相關文章