簡體   English   中英

SSE 內在函數中的 if/else 語句

[英]if/else statement in SSE intrinsics

我正在嘗試使用 SSE 內在函數優化一小段代碼(我是該主題的完整初學者),但我對條件的使用有點堅持。

我的原始代碼是:

unsigned long c;
unsigned long constant = 0x12345678;
unsigned long table[256];
int n, k;

for( n = 0; n < 256; n++ )
{
  c = n;
  for( k = 0; k < 8; k++ )
    {
      if( c & 1 ) c = constant ^ (c >> 1);
      else c >>= 1;
    }
  table[n] = c;
}

這段代碼的目標是計算一個 crc 表(常數可以是任何多項式,它在這里不起作用),

我想我的優化代碼是這樣的:

__m128 x;
__m128 y;
__m128 *table;

x = _mm_set_ps(3, 2, 1, 0);
y = _mm_set_ps(3, 2, 1, 0);
//offset for incrementation
offset = _mm_set1_ps(4);

for( n = 0; n < 64; n++ )
{
    y = x;
    for( k = 0; k < 8; k++ )
    {
        //if do something with y
        //else do something with y
    }
    table[n] = y;
    x = _mm_add_epi32 (x, offset);
}

我不知道如何通過 if-else 語句來 go,但我懷疑有一個聰明的技巧。 有人知道如何做到這一點嗎?

(除此之外,我的優化可能很差 - 任何關於它的建議或更正都會受到最大的同情)

您可以完全擺脫 if/else。 早在我編寫 MMX 匯編代碼的時候,那是一種常見的編程活動。 讓我從對“假”陳述的一系列轉換開始:

c >>= 1;

c = c >> 1;

c = 0 ^ (c >> 1);

為什么我要介紹異或? 因為在“真”語句中也可以找到異或:

c = constant ^ (c >> 1);

注意相似之處? 在“真”部分,我們與一個常數異或,而在假部分,我們與零異或。

現在,我將向您展示整個 if/else 語句的一系列轉換:

if (c & 1)
    c = constant ^ (c >> 1);          // same as before
else
    c =        0 ^ (c >> 1);          // just different layout

if (c & 1)
    c =  constant      ^ (c >> 1);
else
    c = (constant & 0) ^ (c >> 1);    // 0 == x & 0

if (c & 1)
    c = (constant & -1) ^ (c >> 1);   // x == x & -1
else
    c = (constant &  0) ^ (c >> 1);

現在,這兩個分支僅在二元與的第二個參數上有所不同,它可以從條件本身簡單地計算出來,從而使我們能夠擺脫 if/else:

c = (constant & -(c & 1)) ^ (c >> 1);

免責聲明:此解決方案僅適用於二進制補碼架構,其中 -1 表示“所有位設置”。

SSE 的想法是構建兩個結果,然后將結果混合在一起。

例如:

__m128i mask = ...; // some way to build mask[n] = 0x1
__m128i constant = ...;

__m128i tmp_c = _mm_xor_si128( _mm_srli_epis32( c, 1 ), constant );
__m128i tmp_c2 = _mm_srli_epis32( c, 1 );

__m128i v = _mm_cmpeq_epi32( c, mask );
tmp_c = _mm_and_epi32( tmp_c, mask );
tmp_c2 = _mm_andnot_si128( mask, tmp_c2 );
c = _mm_or_si128( tmp_c, tmp_c2 );
// or in sse4_1
c = _mm_blendv_epi8( tmp_c, tmp_c2, mask );

另外注意,這不是完整的代碼,只是為了演示原理。

高效計算 CRC 的第一步是使用比位更寬的基本單位。 有關如何按字節執行此字節的示例,請參見此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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