[英]Compare and swap with SIMD intrinsics
如果發生某種情況,是否可以在SIMD指令中進行比較並交換值。 換句話說,我有4個整數:
(100 5) (1 42)
我想收到:
(5 100) (1 42)
即我想成對比較(第一個值與第二個,第三個與第四個),並在左操作數較大的情況下-交換值。 只能使用1張SIMD嗎?
PS:這是我第一次嘗試SIMD,可能是我使用了錯誤的術語-如果我輸入錯了,請修復我。
對於支持AVX2的系統,有一個使用最小/最大並與imm
混合的解決方案(其延遲為1個周期,而變量1為2個周期)。
以下代碼具有3個周期的延遲,並且在HSW +上的吞吐量應小於2個周期
__m128i tmp = _mm_shuffle_epi32(in, _MM_SHUFFLE(2,3,0,1));
__m128i min = _mm_min_epi32(in, tmp);
__m128i max = _mm_max_epi32(in, tmp);
// __m128i res = _mm_blend_epi32(min, max, 0xA); // AVX2 only
__m128i res = _mm_blend_epi16(min, max, 0xCC); // SSE4.1
我已經在我的HSW系統上對其進行了測試(處理了20000對,進行了10萬次),它的性能比stgatilov
的代碼高約26%。
CMP + VARIABLE BLEND 1.18sec
MIN/MAX + BLEND_32 0.87sec // AVX2 only code
MIN/MAX + BLEND_PS 0.86sec // SSE
MIN/MAX + PLEND_16 0.88sec // Preferred for SSE
更新 :Per stgatilov
在下面的評論。 所有的MIN / MAX實現幾乎都具有相同的性能(很可能只是卡在了內存中,黑白)
似乎您想在單個XMM寄存器中對32位整數對進行排序。 當然,尚無現成的說明,但是您可以使用SSE4.1編寫一些說明( 請注意:未經測試的代碼):
//input = [100, 5, 1, 42]
__m128i swapped = _mm_shuffle_epi32(input, _MM_SHUFFLE(2,3,0,1)); // [5, 100, 42, 1]
__m128i comp = _mm_cmplt_epi32(input, swapped); // [0, -1, -1, 0]
comp = _mm_xor_si128(comp, _mm_set_epi32(-1, 0, -1, 0)); // [0, 0, -1, -1]
input = _mm_blendv_epi8(swapped, input, comp); // [5, 100, 1, 42]
在Ivy Bridge上,似乎是7微秒,需要2個CPU周期(吞吐量)。
如果需要,可以輕松將其移植到AVX2。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.