我正在尝试使用 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 语句,但我怀疑有一个聪明的技巧。有没有人知道如何做到这一点?
(除此之外,我的优化可能很差 - 任何关于它的建议或更正都会受到最大的同情)
最佳答案
您可以完全摆脱 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 表示“所有位设置”。
关于c++ - SSE 内在函数中的 if/else 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6290460/