2016-07-05 23 views
6

我在內存中包含索引I0,I1,I2,I3的整數對齊數組。我的目標是讓它們進入包含I0,I0 + 1,I1,I1 + 1,I2,I2 + 1,I3,I3 + 1的__m256i寄存器。最難的部分是將它們放入256位寄存器I0,I0 ,I1,I1,I2,I2,I3,I3,之後我可以添加一個包含0,1,0,1,0,1,0,1的寄存器。AVX2,如何有效地將四個整數加載到256位寄存器的指數並複製到奇數指數?

我發現了固有的_mm256_castsi128_si256,它我可以將4個整數加載到256位寄存器的低128位中,但我努力從中找到最好的內在函數。

任何幫助,將不勝感激。我可以訪問所有SSE版本,AVX和AVX2,並希望僅使用內部函數來執行此操作。

編輯:

我想這樣的作品,但我也並不怎麼有效...在測試它的過程。

// _mm128_load_si128: Loads 4 integer values into a temporary 128bit register. 
// _mm256_broadcastsi128_si256: Copies 4 integer values in the 128 bit register to the low and high 128 bits of the 256 bit register. 
__m256i tmpStuff = _mm256_broadcastsi128_si256 ((_mm_load_si128((__m128i*) indicesArray))); 

// _mm256_unpacklo_epi32: Interleaves the integer values of source0 and source1. 
__m256i indices = _mm256_unpacklo_epi32(tmpStuff, tmpStuff); 

__m256i regToAdd = _mm256_set_epi32 (0, 1, 0, 1, 0, 1, 0, 1); 
indices = _mm256_add_epi32(indices, regToAdd); 

EDIT2:上面的代碼不起作用,因爲_mm256_unpacklo_epi32並不表現我的思維方式。上面的代碼將導致I0,I0 + 1,I1,I1 + 1,I0,I0 + 1,I1,I1 + 1。

EDIT3:下面的代碼工作,但再次我不知道這是否是最有效的:

__m256i tmpStuff = _mm256_castsi128_si256(_mm_loadu_si128((__m128i*) indicesArray)); 
__m256i mask = _mm256_set_epi32 (3, 3, 2, 2, 1, 1, 0, 0); 
__m256i indices= _mm256_permutevar8x32_epi32(tmpStuff, mask); 
__m256i regToAdd = _mm256_set_epi32 (1, 0, 1, 0, 1, 0, 1, 0); // Set in reverse order. 
indices= _mm256_add_epi32(indices, regToAdd); 

回答

6

你的第二個版本是有效的,因爲它可能是,除非我失去了一個辦法這可能會將洗牌轉化爲128b的負載。對於融合域uop吞吐量,這可能會有所幫助,但對於未融合域而言則不會。

1個負載(vmovdqa),1個洗牌(vpermd,又名_mm256_permutevar8x32_epi32)和1個添加(vpaddd)是相當輕量級的。除非通過元素1和元素2之間的拆分進行未對齊的256b加載,否則需要進行某種類型的車道交叉混洗以將上部2個元素置於上部128b中。

由於您可以使用AVX2,因此如果爲vpermd加載一個shuffle掩碼不成問題,那麼您的解決方案非常棒。 (註冊壓力/緩存未命中)。


避免混洗掩模矢量常數,但更糟糕的是,否則一種替代:

vpmovzxdq是用於獲取上部兩個元件到上部128bit的車道另一種選擇。

vpmovzxdq ymm0, [src] 
vpshufd ymm1, ymm0, _MM_SHUFFLE(2,2, 0,0) ; duplicate elements 
vpaddd  ... 

或者,如果可能更高吞吐量的洗牌端口是爲整個循環的一個瓶頸。 (仍比vpermd版本中的問題惡化,雖然)。

vpmovzxdq ymm0, [src] 
vpsrlq  ymm1, ymm0,32  ; left shift by 32 
vpaddd  ...     ; ymm1 +=1 in odd elements only 
vpor  ...     ; OR the incremented odd elements with the original even elements 

移,或更換通道內洗牌。

相關問題