[英]Most efficient way to check if all __m128i components are 0 [using <= SSE4.1 intrinsics]
我正在使用SSE內在函數來確定矩形(由四個int32
值定義)是否已更改:
__m128i oldRect; // contains old left, top, right, bottom packed to 128 bits
__m128i newRect; // contains new left, top, right, bottom packed to 128 bits
__m128i xor = _mm_xor_si128(oldRect, newRect);
此時,如果矩形未更改,則生成的xor
值將全為零。 那么最有效的方法是什么呢?
目前我這樣做:
if (xor.m128i_u64[0] | xor.m128i_u64[1])
{
// rectangle changed
}
但我認為有一種更聰明的方法(可能使用了一些我還沒有找到的SSE指令)。
我在x64上定位SSE4.1,我在Visual Studio 2013中編寫C ++。
編輯:問題與__m128i變量零是不一樣的? ,因為它指定“在SSE-2和更早的處理器上”(盡管安東尼奧確實添加了一個“完整性”的答案,該問題在發布和回答此問題后的某個時間解決了4.1)。
您可以通過_mm_testz_si128內在函數(SSE4.1)使用PTEST instuction,如下所示:
#include "smmintrin.h" // SSE4.1 header
if (!_mm_testz_si128(xor, xor))
{
// rectangle has changed
}
請注意,如果兩個參數的按位AND
為零, _mm_testz_si128
將返回1。
具有諷刺意味的是,在某些情況下,SSE 4.1的ptest
指令可能比SSE2的pmovmskb
慢。 我建議簡單地使用:
__m128i cmp = _mm_cmpeq_epi32(oldRect, newRect);
if (_mm_movemask_epi8(cmp) != 0xFFFF)
//registers are different
請注意,如果您確實需要xor
值,則必須單獨計算它。
對於像Ivy Bridge這樣的英特爾處理器,PaulR與xor
和_mm_testz_si128
的版本轉換為4 _mm_testz_si128
,而沒有計算xor
建議版本轉換為3 uop(另請參見此主題 )。 這可能會提高我的版本的吞吐量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.