2013-08-31 141 views
1

從英特爾的Compiler Autovectorization Guide有一個與我不明白的對齊有關的例子。該代碼是Autovectorization alignment

double a[N], b[N]; 
... 
for(i = 0; i < N; i++) 
    a[i+1] = b[i] * 3; 

它說

如果兩個陣列的第一個元素在一個16字節邊界對齊, 然後從b或不對齊的元件的任一個未對齊加載 將元素存儲到a,必須在矢量化之後使用。 然而,程序員可以執行如下所示的對準,這 將導致兩個對準的訪問模式矢量 (假設雙打一個8字節的大小)後

_declspec(align(16, 8)) double a[N]; 
_declspec(align(16, 0)) double b[N]; 

如何看到錯位配矢量化之後?對齊不會取決於數組的大小嗎?

+0

嗯,是的,一個有意將索引[]超出範圍的代碼片段確實令人困惑。我認爲這是試圖說這個循環總是導致錯位的訪問。如果b [i]對齊,那麼[i + 1]將會失準。或者相反。所以它提出的做法是在內存中有意識地錯誤對齊[8],而現在這兩個訪問都是對齊的。 –

+0

那麼這個例子本身沒有錯位?我的意思是,我不明白它會如何產生錯位或爲何會產生錯位。 – BRabbit27

回答

1

漢斯帕桑特基本上涵蓋了所有正確的想法,但讓我解釋一點:

ab都對齊到16個字節。比如說,它們的地址是0x100和0x200,舉例來說。

現在,讓我們來看看代碼是如何看起來像i=3(奇)和i=6(偶數)...

a[i+1] = b[i] * 3;會做[0x120] = [0x318] * 3(I = 3的sizeof翻一番8)

a[i+1] = b[i] * 3;將盡[0x138] = [0x330] * 3

在兩種情況下,無論是左手側或右手側被對齊,而另一種是不對準(對齊ed訪問總是以十六進制0結尾,其他的則沒有對齊)。

現在...讓我們有意將a與8模16地址錯位(比如說保留我們的例子)。

讓我們來看看代碼是如何看起來像i=3(奇)和i=6(偶數)...

a[i+1] = b[i] * 3;會做[0x128] = [0x318] * 3(I = 3的sizeof翻一番8)

a[i+1] = b[i] * 3;會做[0x140] = [0x330] * 3

都會保持實際訪問同時對齊和未對齊。

+0

我懂了!最後,8模16.8是因爲使用的數據類型(在我們的例子中是'double')和16是因爲某個體系結構的地址與此對齊,對吧? – BRabbit27

+0

實際上,如果數組與8位或32位字節邊界對齊,會發生什麼情況?這與所有這些有什麼關係? – BRabbit27

+0

那麼,你可以做數學來確信:一個32字節對齊的地址是16字節對齊的,所以沒有改變。一個8字節對齊可以有一個地址爲0模16,或8模16,所以你不知道。這取決於分配器的實施...... – Bahbar