elma
및 elmc
은 모두 unsigned long
어레이입니다. 따라서 res1
및 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++)
{
//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 루프 내에는 요소의 XOR의 비 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];
}
}
그러나이 결과는 많이 변경되지 않습니다 줄이기; 여전히 스칼라 코드의 두 배가 걸립니다.
정렬 RES1/RES2, 레지스터를 스위 즐링 (swizzle), 똑바로 그들에게 물품. simdstore를 제거하십시오. – EboMike
res1/res2는 코드에서 사용한 부호없는 long 배열입니다. 16 바이트 단위로 정렬하여 무엇을 의미하는지 확실하지 않으며 직접 작성하십시오. – anup
시작 주소가 16 바이트로 정렬되어 있는지 확인한 다음 _mm_store_si128을 사용하여 직접 작성하십시오. (분명히, 두 가지 결과를 가져 와서 벡터 레지스터를 섞어서 하나의 결과로 결합해야합니다.) 메모리에 기록한 다음 다시 읽으면 실속이 발생합니다. – EboMike