2017-01-19 14 views
0

코드 목적은 문자열 str의 각 문자를 키 배열의 값에서 뺍니다. 벡터화되지 않은 버전의 프로그램은 두 프로그램의 마지막주기에 해당합니다. 이 코드는 어떻게이에서인텔로드 본질적인 문제

void decode(const char* key, int m, char* str) { 
    int i; int n = strlen(str); 
    __m128i k = _mm_loadu_si128((const __m128i*) key); 
    for (int i = 0; i + 16 < n; i+=m) { 
    __m128i s = _mm_loadu_si128((__m128i*) (str + i)); 
    s = _mm_sub_epi8(s, k); 
    _mm_storeu_si128((__m128i*) (str + i), s); 
    } 
    for(; i<n; i++) str[i] -= key[i%m]; 
} 

다른?

void decode(const char* key, int m, char* str) { 
    int i, n = strlen(str); 
    char keybuf[16] = { 0 }; 
    memcpy(keybuf, key, m); 
    __m128i k = _mm_loadu_si128((__m128i*)keybuf); 
    for (i=0; i+16 < n; i += m) { 
    __m128i s = _mm_loadu_si128((__m128i*)(str+i)); 
    s = _mm_sub_epi8(s,k); 
    _mm_storeu_si128((__m128i*)(str+i), s); 
    } 
    for (; i<n; i++) str[i] -= key[i % m]; } 

메모리 복사본이 없으면 동일한 코드가 동일한 방식으로 작동하지 않습니다. gcc -msse2로 컴파일 중입니다. 왜 메모리 복사본이 필요합니까?

+0

for 루프는 두 경우 모두 잘못되었습니다 - for (int i = 0; i + 16 <= n; i + = m) 아마 당신의 주요 문제가 아닙니다. –

+0

그것이 내 생각에 제 교수의 코드입니다. 그것은 문자열 터미네이터에 대해 뭔가 있어야합니다 ... – spallas

+0

내가 말했듯이, 그것은 주된 문제는 아니지만, 수정하지 않으면 특정 값의'n'에 대해 최종 스칼라 루프에서 너무 많은 불필요한 작업을 할 수도 있습니다 이. –

답변

1

차이점은 두 번째 경우에는 m 문자를 keybuf에로드하고 나머지 요소는 0으로 초기화 상태를 유지합니다. 그러면이 추가 요소가 str에 영향을 미치지 않습니다.

그러나 첫 번째 버전에서는 키의 실제 길이에 관계없이 key에서 16 개의 요소를 모두 맹목적으로로드하기 때문에 벡터 끝에 0이 아닌 요소가있을 가능성이 큽니다.

첫 번째 버전을 올바로 작동하게하려면 16 - m 요소 인 을 가려야합니다 (예 : k).

const int8_t mask[32] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 
__m128i k = _mm_loadu_si128((const __m128i*) key); // load 16 elements 
k = _mm_and_si128(k, _mm_loadu_si128((const __m128i*)&mask[16 - m])); 
                // mask out final 16 - m elements 

(참고 :.이 마스킹을 수행하는보다 효율적인 방법은 아마이지만, 나는 짧은 시간에 가지고 올 수있는 최선의 방법이 여전히 memcpy 버전보다 더 효율적으로 될 것 같아요 것 . 일부 다른 방법에 대해서는 this question and its answers을 참조하십시오.