벡터 내장 함수를 사용하여 개인용 이미지 처리 라이브러리를 다시 작성하여 SIMD 기능을 사용하는 방법을 배우고 있습니다. 하나 개의 기본 기능은 간단한 "배열 +=
,"즉 임의의 배열 길이에 대한임의의 배열 길이에 대한 SIMD 배열 추가
void arrayAdd(unsigned char* A, unsigned char* B, size_t n) {
for(size_t i=0; i < n; i++) { B[i] += A[i] };
}
, 명백한 SIMD 코드 (16 정렬 가정)입니다 같은 것입니다 :
size_t i = 0;
__m128i xmm0, xmm1;
n16 = n - (n % 16);
for (; i < n16; i+=16) {
xmm0 = _mm_load_si128((__m128i*) (A + i));
xmm1 = _mm_load_si128((__m128i*) (B + i));
xmm1 = _mm_add_epi8(xmm0, xmm1);
_mm_store_si128((__m128i*) (B + i), xmm1);
}
for (; i < n; i++) { B[i] += A[i]; }
는하지만 할 수 있습니다 모두 SIMD 지침이 추가 되었습니까? 나는이하려고 생각 : 여분의 요소에 대한
__m128i mask = (0x100<<8*(n - n16))-1;
_mm_maskmoveu_si128(xmm1, mask, (__m128i*) (B + i));
,하지만 정의되지 않은 동작에 그 결과를 것인가? mask
은 배열 경계를 지나서 실제로 액세스 할 수 없음을 보장해야합니다 (필자는 생각합니다). 다른 방법으로 여분의 요소를 먼저 처리하는 것이지만 배열을 n-n16
으로 정렬해야합니다.
벡터화 된 루프와 같은 다른 최적의 패턴이 있습니까?
. 그러나 에필로그는 속도 측면에서 중요하지 않습니다. – Walter