Следующий цикл выполняется сотни раз.
elma and elmc are both unsigned long (64-bit) arrays, so is res1 and res2.
Код SIMD против Скалярного кода
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: 668460000 2 2
Строка 2: 668460000 1 1
Строка 3: 89985000 1 1
Строка 4: 89985000 1 1
Строка 5: 617040000 2 2
Строка 6: 44992500 0 0
Строка 7: 44992500 0 0
Строка 8: 539910000 1 1
Строка 9: 128550000 0 0
Строка 10:. , ,
Строка 11: 205680000 0 0
Строка 12: 205.680.000 0 0
Из приведенного выше рисунка, оказывается, что заметили (скалярный код) требует значительно меньшего количества инструкций SIMD, чем код.
Как этот код можно сделать быстрее?
Это дубликат вашего собственного вопроса.Вернитесь туда и поймите, почему этот ответ (а не ответ, который вы отметили как правильный) решает проблему: http://stackoverflow.com/questions/4394930/simd-code-runs-slower-than-scalar-code/4395337# 4395337 – 2010-12-09 12:27:29