2012-03-26 19 views
12

我剛開始使用SSE,我很困惑如何獲得__m128i的最大整數值(max)。例如:使用SSE在__m128i向量中獲取最大值?

__m128i t = _mm_setr_ps(0,1,2,3); 
// max(t) = 3; 

搜索周圍使我MAXPS指令,但我似乎無法找到如何使用與"xmmintrin.h"

另外,是否有任何文檔"xmmintrin.h",你會推薦,而不是看着頭文件本身?

+0

你需要的洗牌是相同水平總和,或者幾乎任何其它水平降低。請參閱https://stackoverflow.com/questions/6996764/fastest-way-to-do-horizo​​ntal-float-vector-sum-on-x86獲取一些針對float,integer和double的優化版本,以及SSE2,SSE3和AVX。還討論什麼洗牌是哪些CPU的最佳選擇。 – 2017-09-09 02:36:09

+0

這個問題似乎對浮點型和整數型都感到困惑。 '__m128i'是一個整數向量。 '* _ps'和'MAXPS'是壓縮單浮點。有關文檔,請參閱[SSE標記wiki](https://stackoverflow.com/tags/sse/info)鏈接以及更多鏈接,網址爲https://stackoverflow.com/tags/x86/info。一個非常好的資源是[** Intel的內部函數搜索/查找程序**](https://software.intel.com/sites/landingpage/IntrinsicsGuide/),它詳細介紹了每個程序的功能,但沒有詳細asm指令參考手冊。 – 2017-09-09 02:39:09

回答

11

如果你發現自己需要做載體水平的操作,尤其是如果它是一個內循環中,那麼它的通常你正在接近你的SIMD執行中的標誌錯誤的方法。 SIMD喜歡在矢量上操作元素 - 如果你願意的話,「垂直」,而不是水平。

至於文檔,有一個very useful reference on intel.com,其中包含所有從MMX到各種SSE一直到AVX和AVX-512的所有操作碼和內部函數。

+0

謝謝你的鏈接。水平部分僅適用於循環條件,但我會修改我的方法 – Shane 2012-03-26 20:23:15

+0

鏈接當前是:https://software.intel.com/sites/landingpage/IntrinsicsGuide/ – 2014-12-05 00:09:19

+0

@MarkLakata:謝謝 - 答案更新 - 我想念老脫機指南 - 以及沒有互聯網連接的工作,這也是有用的,你可以刮數據用於其他用途。沒關係 - 新的在線版本仍然不錯。 – 2014-12-05 07:28:51

4

SSE中沒有水平最大操作碼(至少直到我停止跟蹤新的SSE指令爲止)。

所以你被困在做一些洗牌。你最終得到的是...

movhlps %xmm0, %xmm1   # Move top two floats to lower part of %xmm1 
maxps %xmm1, %xmm0   # Get minimum of sets of two floats 
pshufd $0x55, %xmm0, %xmm1  # Move second float to lower part of %xmm1 
maxps %xmm1, %xmm0   # Get minimum of all four floats originally in %xmm0 

http://locklessinc.com/articles/instruction_wishlist/

MSDN具有內在的和宏功能映射記錄

http://msdn.microsoft.com/en-us/library/t467de55.aspx

8

this page,沒有水平最高,和您需要垂直測試元素:

movhlps xmm1,xmm0   ; Move top two floats to lower part of xmm1 
maxps xmm0,xmm1   ; Get maximum of the two sets of floats 
pshufd xmm1,xmm0,$55  ; Move second float to lower part of xmm1 
maxps xmm0,xmm1   ; Get minimum of the two remaining floats 

相反,得到了最低:

movhlps xmm1,xmm0 
minps xmm0,xmm1 
pshufd xmm1,xmm0,$55 
minps xmm0,xmm1 
+1

'maxps'指令之間的'pshufd'在許多CPU(包括Intel)上有額外的延遲。 SSE3'movshdup'將在寄存器的每一半中複製較高的浮點數,因此您可以使用它來避免movaps複製。 – 2017-09-09 01:54:24

+0

@PeterCordes,你能寫出你自己的優化解決方案嗎?如果它是一個浮動矢量,它會不同嗎?謝謝。 – Royi 2017-10-10 23:05:42

+0

@羅伊:這個答案*是*爲'float'的一個向量(因爲問題是錯誤的標題或關於float和integer的混淆,請參閱我對這個問題的評論)。針對哪些微體系結構和哪些級別的SSE進行了優化? SSE3?還是僅限於SSE2?還是AVX2?請參閱https://stackoverflow.com/questions/6996764/fastest-way-to-do-horizo​​ntal-float-vector-sum-on-x86(但用'max'替換'add')以獲得各種優化的浮點和整數洗牌。 – 2017-10-10 23:18:08

14

如果有人關心,並且因爲內在函數似乎是今天的方式,這裏是內在的解決方案。

int horizontal_max_Vec4i(__m128i x) { 
    __m128i max1 = _mm_shuffle_epi32(x, _MM_SHUFFLE(0,0,3,2)); 
    __m128i max2 = _mm_max_epi32(x,max1); 
    __m128i max3 = _mm_shuffle_epi32(max2, _MM_SHUFFLE(0,0,0,1)); 
    __m128i max4 = _mm_max_epi32(max2,max3); 
    return _mm_cvtsi128_si32(max4); 
} 

我不知道這是比這更好:

int horizontal_max_Vec4i(__m128i x) { 
    int result[4] __attribute__((aligned(16))) = {0}; 
    _mm_store_si128((__m128i *) result, x); 
    return max(max(max(result[0], result[1]), result[2]), result[3]); 
} 
+1

當然,它更好。 – user1095108 2014-08-18 10:27:08