以下循环执行了数百次。
elma and elmc are both unsigned long (64-bit) arrays, so is res1 and res2.
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++)
{
1. //res1[i + k] ^= _mulpre1[u1][k];
2. //res2[i + k] ^= _mulpre2[u2][k];
3. _mm_prefetch ((const void *) &_mulpre2[u2][k], _MM_HINT_T0);
4. _mm_prefetch ((const void *) &_mulpre1[u1][k], _MM_HINT_T0);
5. simda = _mm_set_epi64x (_mulpre2[u2][k], _mulpre1[u1][k]);
6. _mm_prefetch ((const void *) &res2[i + k], _MM_HINT_T0);
7. _mm_prefetch ((const void *) &res1[i + k], _MM_HINT_T0);
8. simdb = _mm_set_epi64x (res2[i + k], res1[i + k]);
9. simdc = _mm_xor_si128 (simda, simdb);
10. _mm_store_si128 (p, simdc);
11. res1[i + k] = simdstore[0];
12. res2[i + k] = simdstore[1];
}
}
在 for 循环中,标量版本的代码(已注释)运行速度是 simd 代码的两倍。下面提到了上述行的 cachegrind 输出(指令读取)。
行1:668,460,000 2 2
行2:668,460,000 1 1 1
行3:89,985,000 1 1 1 1
行4:89,985,000 1 1 1 1
行5:617,040,000 2 2行2
行6:44,992,500 0 0 0 0 LINE 0
LINE 7:44,992,500 0 0
LINE LINE LINE 8:44,992,500 0
LINE : : 128,550,000 0 0
第 10 行: . . .
第 11 行:205,680,000 0 0
第 12 行:205,680,000 0 0
从上图中可以看出,注释(标量代码)所需的指令数量明显少于 simd 代码。
如何使这段代码更快?