2013-04-24 46 views
11

在AVX2 intrinsic文檔尋找有聚集負載指令,例如VPGATHERDDAVX2指令集 - 加載地址計算

__m128i _mm_i32gather_epi32 (int const * base, __m128i index, const int scale); 

的不是很清楚,我從文檔是否計算負載地址是元件地址或字節地址,即是負載地址元件i

load_addr = base + index[i] * scale;    // (1) element addressing ? 

或:

load_addr = (char *)base + index[i] * scale;  // (2) byte addressing ? 

從它看起來像它可能是(2),但是這並沒有多大意義,因爲對於聚集的負荷最小單元尺寸是32位的Intel docs - 爲什麼你想從錯位地址加載(即使用量表< 4)?

回答

8

收集指令沒有任何對齊要求。所以這將是太嚴格,不允許字節尋址。

其他原因是一致性。隨着SIB解決我們顯然有字節地址:

MOV eax, [rcx + rdx * 2] 

由於VPGATHERDD是這個MOV指令只是一個量化的變體,我們不應該指望什麼用VSIB不同的處理:

VPGATHERDD ymm0, [rcx + ymm2 * 2], ymm3 

至於真正的字節尋址,我們可以有一個24位彩色圖像,其中每個像素是3字節對齊。只有在VSIB中的「縮放」字段爲「1」且VPGATHERDD使用字節尋址時,我們才能用單個VPGATHERDD指令加載8個像素。

+1

好的 - 謝謝 - 我認爲這是有道理的,並且與文檔一致。您在加載過程中有一個很好的觀點。 3個字節的像素值。 – 2013-04-24 16:52:17

4

根據英特爾AVX programming reference document available here中的描述判斷,看起來收集指令使用字節尋址。具體來說,請參閱下面的報價從VPGATHERDD指令的說明(389頁):

DISP: optional 1, 2, 4 byte displacement; 
DATA_ADDR = BASE_ADDR + (SignExtend(VINDEX[i+31:i])*SCALE + DISP; 

既然你可以使用1/2/4字節的位移,我將認爲總體內存地址是一個字節地址。雖然它可能不是一個常用的應用程序,但可能會出現您想要從未對齊的地址讀取32位或64位值的情況。與ARM相比,這是x86體系結構更靈活的一點;如果您願意,您可以靈活地執行未對齊的訪問,而不像其他人那樣觸發CPU異常。

+1

僅供參考,自ARMv6以來ARM支持未對齊的內存訪問 – 2013-04-24 14:50:54

+0

感謝您的更正。我的ARM體驗現在已經變得有點過時了。 – 2013-04-24 15:24:44

1

爲什麼要從未對齊的地址加載(即使用比例爲< 4)?

未對齊的加載不是尺寸爲<元素大小的唯一用例。您可能只是具有預先縮放的字節偏移量的索引。或者考慮向指向結構的指針數組的向量進行向量化:您可以將基地址「零」或小整數偏移量收集到結構中。

支持這種用例是英特爾設計asm指令來支持這種用法的一個原因,因爲收集應該可以幫助編譯器自動向量化更多的代碼。它也適合VSIB字節在機器碼編碼中非常接近SIB,但它們可以很容易地預先偏置比例因子,以便選擇scale = 4,8,16,32(或8 ,16,32,64用於qword收集)與2比特縮放字段。

大於元素大小的比例因子在許多情況下也不明顯有用,並且在聚集之前很容易用單個左移指令來模擬。但是這是不可能的,因爲它可以解決烘烤的比例因子,所以允許非標度索引顯然是更靈活的設計選擇。


其他用例:收集16位元素。在收集之後,使用32位集合並遮蓋每個元素的上半部分。 (或者讓它保持垃圾)。如果您的任何索引都是奇數的(對於2的比例因子),那麼這會導致未對齊的負載,所以如果它們跨過4k邊界可能會很慢(不像真正的16位集合)。

你也可以想象使用一個集合作爲解壓縮函數的一部分,在解碼之後,你有一個偏移向量進入緩衝區,並且你想要任意的4字節或者8字節的數據窗口。