gpt4 book ai didi

c - SIMD 代码运行速度比标量代码慢

转载 作者:太空狗 更新时间:2023-10-29 14:51:04 26 4
gpt4 key购买 nike

elmaelmc 都是 unsigned long 数组。 res1res2 也是如此。

unsigned long simdstore[2];  
__m128i *p, simda, simdb, simdc;
p = (__m128i *) simdstore;

for (i = 0; i < _polylen; i++)
{
u1 = (elma[i] >> l) & 15;
u2 = (elmc[i] >> l) & 15;
for (k = 0; k < 20; k++)
{
//res1[i + k] ^= _mulpre1[u1][k];
//res2[i + k] ^= _mulpre2[u2][k];

simda = _mm_set_epi64x (_mulpre2[u2][k], _mulpre1[u1][k]);
simdb = _mm_set_epi64x (res2[i + k], res1[i + k]);
simdc = _mm_xor_si128 (simda, simdb);
_mm_store_si128 (p, simdc);
res1[i + k] = simdstore[0];
res2[i + k] = simdstore[1];
}
}

for 循环中包含元素异或的非 simd 和 simd 版本。第二个 for 循环中的前两行执行显式 XOR,而其余部分实现相同操作的 simd 版本。

这个循环被外部调用了数百次,因此优化这个循环将有助于减少总计算时间。

问题是 simd 代码的运行速度比标量代码慢很多倍。

编辑:完成部分展开

__m128i *p1, *p2, *p3, *p4;  
p1 = (__m128i *) simdstore1;
p2 = (__m128i *) simdstore2;
p3 = (__m128i *) simdstore3;
p4 = (__m128i *) simdstore4;

for (i = 0; i < 20; i++)
{
u1 = (elma[i] >> l) & 15;
u2 = (elmc[i] >> l) & 15;
for (k = 0; k < 20; k = k + 4)
{
simda1 = _mm_set_epi64x (_mulpre2[u2][k], _mulpre1[u1][k]);
simda2 = _mm_set_epi64x (_mulpre2[u2][k + 1], _mulpre1[u1][k + 1]);
simda3 = _mm_set_epi64x (_mulpre2[u2][k + 2], _mulpre1[u1][k + 2]);
simda4 = _mm_set_epi64x (_mulpre2[u2][k + 3], _mulpre1[u1][k + 3]);

simdb1 = _mm_set_epi64x (res2[i + k], res1[i + k]);
simdb2 = _mm_set_epi64x (res2[i + k + 1], res1[i + k + 1]);
simdb3 = _mm_set_epi64x (res2[i + k + 2], res1[i + k + 2]);
simdb4 = _mm_set_epi64x (res2[i + k + 3], res1[i + k + 3]);

simdc1 = _mm_xor_si128 (simda1, simdb1);
simdc2 = _mm_xor_si128 (simda2, simdb2);
simdc3 = _mm_xor_si128 (simda3, simdb3);
simdc4 = _mm_xor_si128 (simda4, simdb4);

_mm_store_si128 (p1, simdc1);
_mm_store_si128 (p2, simdc2);
_mm_store_si128 (p3, simdc3);
_mm_store_si128 (p4, simdc4);

res1[i + k]= simdstore1[0];
res2[i + k]= simdstore1[1];
res1[i + k + 1]= simdstore2[0];
res2[i + k + 1]= simdstore2[1];
res1[i + k + 2]= simdstore3[0];
res2[i + k + 2]= simdstore3[1];
res1[i + k + 3]= simdstore4[0];
res2[i + k + 3]= simdstore4[1];
}
}

但是,结果并没有太大变化;它仍然需要两倍于标量代码的时间。

最佳答案

免责声明:我有 PowerPC 背景,所以我在这里说的可能完全是废话。但是,由于您试图立即访问结果,因此您正在拖延 vector 管道。

最好将所有内容都保留在 vector 管道中。一旦您进行了从 vector 到 int 或 float 的任何类型的转换,或者将结果存储到内存中,您就会停滞不前。

处理SSE或VMX时最好的操作方式是:Load、process、store。将数据加载到 vector 寄存器中,进行所有 vector 处理,然后将其存储到内存中。

我会建议:保留几个 __m128i 寄存器,多次展开循环,然后存储它。

编辑:此外,如果展开,并且将 res1 和 res2 对齐 16 个字节,则可以将结果直接存储在内存中,而无需通过这个 simdstore 间接寻址,这可能是一个 LHS 和另一个摊位。

编辑:忘记了显而易见的事情。如果您的 polylen 通常很大,请不要忘记在每次迭代时进行数据缓存预取。

关于c - SIMD 代码运行速度比标量代码慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4394930/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com