2013-12-11 57 views
5

我有一個布爾表達式,我已經設法在SSE2中實現。現在我希望嘗試在AVX中實現它,利用並行性增加的另外一個因子2(從128位SIMD類型到256)。但是,AVX不支持整數運算(AVX2,但我正在使用Sandy Bridge處理器,因此目前它不是一種選擇)。但是,因爲有AVX intrinsics for bitwise operations。我想我可以嘗試通過將我的整數類型轉換爲浮點類型並查看它是否工作。有沒有辦法在AVX上模擬_m256類型的整數按位運算?

第一次測試是成功的:

__m256 ones = _mm256_set_ps(1,1,1,1,1,1,1,1); 
__m256 twos = _mm256_set_ps(2,2,2,2,2,2,2,2); 
__m256 result = _mm256_and_ps(ones, twos); 

我guetting全部爲0,因爲我應該。 Simularly AND'ing的二進制補碼,而不是我得到的2的結果,但嘗試11 XOR 4因此,當:

__m256 elevens = _mm256_set_ps(11,11,11,11,11,11,11,11); 
__m256 fours = _mm256_set_ps(4,4,4,4,4,4,4,4); 
__m256 result2 = _mm256_xor_ps(elevens, fours); 

結果是6.46e-46(即接近於0),而不是15 Simularly做11或4給我的價值是22而不是15,因爲它應該是。我不明白這是爲什麼。這是一個錯誤或缺少一些配置嗎?

我實際上期待我的假設是使用float,就好像它們是不能工作的整數一樣,因爲初始化爲float值的整數實際上可能不是精確值,而是近似值。但即使如此,我對我得到的結果感到驚訝。

有沒有人有這個問題的解決方案,或者我必須升級我的CPU來獲得支持AVX2的支持?

+0

這聽起來像你打印一個整數作爲一個浮動得到6.46e-46。你確定你的'printf()'格式說明符正確嗎? –

+0

我沒有打印。我剛剛檢查了Visual Studio調試器中的值。 – Toby999

回答

7

第一次測試意外。

1作爲float是0x3f800000,2是0x40000000。一般來說,它不會那樣工作。

但是你絕對可以做到這一點,你只需要確保你使用正確的位模式。不要將整數轉換爲浮動 - 重新解釋它們。這對應於intrinsics,如_mm256_castsi256_ps,或將你的int存儲到內存中並將它們讀爲浮點數(不會改變它們,一般來說只有數學運算只關心浮點數意味着,剩下的工作與原始位模式,檢查指令可以確保的異常列表)。

+0

啊哈。謝謝。這就說得通了。我試試看,如果有效,請將您的答案標記爲正確。 – Toby999

+2

@ Toby999但請注意,在所有當前的英特爾處理器上,按位邏輯指令的浮點版本的吞吐量僅爲整數版本的1/3。所以如果你是爲了表現而做這件事,你可能要考慮三次。除非你受解碼器帶寬的限制,否則它可能會適得其反。 – Mysticial

+2

在Sandy和Ivy Bridge上,整數SSE按位邏輯可以以一個/週期進入端口0,1或5中的任意端口。這是每個週期3。但浮點SSE按位邏輯只能以一個/週期進入端口5。所以它每個週期限制爲1個。在Haswell,它是一樣的,但它有AVX2 - 這使得這一點毫無爭議。 – Mysticial

4

您不需要AVX2來使用AVX整數加載和存儲操作:請參閱intel intrinsic guide。因此,您可以使用AVX加載整數,將reinterpret-cast轉換爲float,使用浮點位運算,然後重新解釋回到int。重新解釋不會產生任何指令,它們只是讓編譯器感到高興。試試這個:

//compiled and ran on an Ivy Bridge system with AVX but without AVX2 
#include <stdio.h> 
#include <immintrin.h> 
int main() { 
    int a[8] = {0, 2, 4, 6, 8, 10, 12, 14}; 
    int b[8] = {1, 1, 1, 1, 1, 1, 1, 1}; 
    int c[8]; 

    __m256i a8 = _mm256_loadu_si256((__m256i*)a); 
    __m256i b8 = _mm256_loadu_si256((__m256i*)b); 
    __m256i c8 = _mm256_castps_si256(
     _mm256_or_ps(_mm256_castsi256_ps(a8), _mm256_castsi256_ps(b8))); 
    _mm256_storeu_si256((__m256i*)c, c8); 
    for(int i=0; i<8; i++) printf("%d ", c[i]); printf("\n"); 
    //output: 1 3 5 7 9 11 13 15 
} 

當然,正如神祕指出這可能不值得做,但這並不意味着你不能這樣做。

+0

)感謝您的輸入,這很有幫助,因爲它很耗時挖掘正確的內在函數方法 – Toby999

+0

有對齊變量的選項,因此您不需要處理未對齊的加載 –

+0

@LưuVĩnhPhúc,我正在使用假設它是無關緊要的對齊和未對齊的加載/存儲指令的吞吐量和延遲在對齊的內存上是相同的這就是理論但在實踐中我仍然看到了差異所以我同意你應使用對齊的加載指令。 –

相關問題