簡體   English   中英

檢查所有__m128i組件是否為0的最有效方法[使用<= SSE4.1內在函數]

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM