인텔 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);
}
참조 : 인텔의 문서
- http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011Update/compiler_c/optaps/common/optaps_par_cean_prog.htm
- https://www.cilkplus.org/tutorial-array-notation
도움 주셔서 감사합니다. – hwang