int u1, u2;
unsigned long elm1[20], _mulpre[16][20], res1[40], res2[40]; 64 bits long
res1, res2 initialized to zero.
l = 60;
while (l)
{
for (i = 0; i < 20; i += 2)
{
u1 = (elm1[i] >> l) & 15;
u2 = (elm1[i + 1] >> l) & 15;
for (k = 0; k < 20; k += 2)
{
simda = _mm_load_si128 ((__m128i *) &_mulpre[u1][k]);
simdb = _mm_load_si128 ((__m128i *) &res1[i + k]);
simdb = _mm_xor_si128 (simda, simdb);
_mm_store_si128 ((__m128i *)&res1[i + k], simdb);
simda = _mm_load_si128 ((__m128i *)&_mulpre[u2][k]);
simdb = _mm_load_si128 ((__m128i *)&res2[i + k]);
simdb = _mm_xor_si128 (simda, simdb);
_mm_store_si128 ((__m128i *)&res2[i + k], simdb);
}
}
l -= 4;
All res1, res2 values are left shifted by 4 bits.
}
在我的程序中多次调用上面提到的代码(分析器显示98%)。
编辑:在内部循环中,对于相同的(i + k)值,res1 [i + k]值被多次加载。我在while循环中尝试了这个,我将所有res1值加载到simd寄存器(数组)中,并使用最里面for循环内的数组元素来更新数组元素。完成两个for循环后,我将数组值存储回res1,re2。但是计算时间随之增加。知道我哪里错了吗?这个想法似乎是正确的
欢迎任何提高速度的建议。
答案 0 :(得分:2)
不幸的是,编译器可能已经完成了最明显的优化:
&_mulpre[u1]
和&mulpre[u2]
。&res1[i]
我们的内循环。可能交换外部循环将改善elm1
上的缓存局部性。
答案 1 :(得分:0)
嗯,你总是可以少打电话: - )
总投入&amp;输出数据看起来相对较小,取决于您的设计和预期输入,只是缓存计算或进行延迟评估而不是预先进行可能是可行的。
答案 2 :(得分:0)
你可以用这样的例程做很少的事情,因为加载和存储将是主导因素(对于单个计算指令,你正在做2个加载+ 1个存储= 4个总线周期)。
答案 3 :(得分:0)
l = 60;
while (l)
{
for (i = 0; i < 20; i += 2)
{
u1 = (elm1[i] >> l) & 15;
u2 = (elm1[i + 1] >> l) & 15;
for (k = 0; k < 20; k += 2)
{
_mm_stream_si128 ((__m128i *)&res1[i + k],
_mm_xor_si128 (
_mm_load_si128 ((__m128i *) &_mulpre[u1][k]),
_mm_load_si128 ((__m128i *) &res1[i + k]
));
mm_stream_si128 ((__m128i *)&res2[i + k],
_mm_xor_si128 (
_mm_load_si128 ((__m128i *)&_mulpre[u2][k]),
_mm_load_si128 ((__m128i *)&res2[i + k])
));
}
}
l -= 4;
All res1, res2 values are left shifted by 4 bits.
}