2014-02-25 10 views
0

인텔 Cilk Plus 배열 표기법을 사용하여 벡터 프로그래밍을 연습하고 있습니다. 그러나 배열 할당의 이상한 복사 동작을 만났습니다.인텔 Cilk Plus 배열 표기법의 이상한 복사 동작

해결해야 할 문제는 병렬 접두어입니다. D가 입력되고 P가 출력됩니다.

// 잘못된 결과 코드. Intel icc 14.0.2에서 테스트되었습니다.

void vec_prefix(int n, int D[n], int P[n]) { 
    P[0:n] = D[0:n]; //initial copy 
    int bound=1; 
    int * Buf1 = _mm_malloc(n*sizeof(int), 16); 
    int * Buf2 = _mm_malloc(n*sizeof(int), 16); 

    while(bound<n){ 
    Buf1[0:n-bound] = P[0:n-bound]; 
    Buf2[0:n-bound] = P[bound:n-bound]; 
    //printf("WHY??\n"); //Add this fence, the result will be correct. 
    P[bound:n-bound] = Buf1[0:n-bound] + Buf2[0:n-bound]; 
    bound<<=1; 
    } 
    _mm_free(Buf1); _mm_free(Buf2); 
} 

"printf"행의 주석을 제거하면 결과가 정확합니다. 그렇지 않으면 잘못되었습니다. 그러나 모든 사본이 인텔 문서의 설명을 따르는 경우 코드가 정확해야합니다.

메모리 펜스가 없으면 첫 번째 두 줄의 Buf1/Buf2 복사본이 완료되지 않은 것 같으며 나중에 추가 작업이 일부 불안정한 값을 사용합니다. 또는 컴파일러 최적화 프로그램은 copy-propagation을 사용하여 복사본을 제거하고 "P [bound : n-bound] = P [0 : n-bound] + P [bound : n-bound]" " 이것은 인텔의 문서에서 정의되지 않았습니다.

// 올바른 결과 코드

void vec_prefix(int n, int D[n], int P[n]) { 
    P[0:n] = D[0:n]; //initial copy 
    int bound=1; 
    int * Buf1 = _mm_malloc(n*sizeof(int), 16); 

    while(bound<n){ 
    //direct copy part 
    Buf1[0:bound] = P[0:bound]; 
    //add part 
    Buf1[bound:n-bound] = P[bound:n-bound] + P[0:n-bound]; 
    //copy back 
    P[0:n] = Buf1[0:n]; 
    bound<<=1; 
    } 
    _mm_free(Buf1); 
} 

참조 : 인텔의 문서

답변

0

코드는 나에게 올바른 보인다. "울타리"가 필요하지 않습니다. 필자는 Intel 컴파일러 그룹에 대한 내부 버그 보고서를 작성하여 모든 예제를 입력으로했습니다. 예를 들어 주셔서 감사합니다. P에 대한 중복 정확히 때문에

while(bound<n){ 
    Buf1[0:n-bound] = P[0:n-bound]; 
    P[bound:n-bound] = Buf1[0:n-bound] + P[bound:n-bound]; 
    bound<<=1; 
} 

두 번째 배열 섹션 할당이 괜찮 : 컴파일러가 제대로 작동한다면

은, 당신도에 while 루프를 단축 할 수있다. Alas icc는이 예제에서도 버그를 보여줍니다.

+0

도움 주셔서 감사합니다. – hwang