지난 몇 달간 C 멀티 코어에서 프로그램을 만들려고 노력했지만 아직 이상한 문제가 있습니다. 어쩌면 당신 중 일부가 좀 도와 줄 수 있을까요?OpenMP 다른 결과 1 코어 vs 복수
내가 겪고있는 문제는 하나의 스레드 만 사용하여 계산할 때 내 프로그램이 적절한 결과를 제공한다는 것입니다. 그러나 더 많은 스레드를 선택하면 수행 한 계산이 정확히 같아야하지만 (임의의 숫자 생성기를 제외하고는) 값이 변경되기 시작합니다.하지만 각 코어가 고유 한 시드를 가지고 있으므로 문제가되어서는 안됩니다. 생성기는 openmp 멀티 코어 처리와 함께 작동하는 것으로 알려져 있음).
어쨌든 프로그램 자체는 기밀 사항이므로 전체 코드를 제공 할 수는 없습니다 (어쨌든 편리한 용도로는 너무 큽니다). 따라서 코드의 일부를 설명하기 위해 최선을 다할 것이며, 문제.
먼저 라이브러리는 I 포함 :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <omp.h> /* openmp header */
#include <limits.h>
#include <float.h>
#include <gsl/gsl_rng.h> /*RNG header*/
#include <gsl/gsl_randist.h> /*RNG header*/
가 그럼 난 등 일부 구조를 정의하지만, 프로그램이 단일 코어 모드에서 작업을 수행 나는이 일을 알고있다. 그럼 난 내 OpenMP를 병렬 루프는 다음과 같습니다되는 주요 기능이 있습니다이 하위 기능에서
//perform multicore calculations (loop over all photons)
#pragma omp parallel for default(none) \
num_threads(thread_cnt) \
private(icount,thread_id,i) \
shared(calc,imstr,sum_irefl,leaks) \
copyin(scat,cap,pcap_ini,profile,absmu,ctvar,lib)
for(icount=0; icount <= cap.ndet; icount++){
thread_id = omp_get_thread_num();
printf("\nthread %d scat:\n",thread_id);
for(i=0;i<NDIM;i++) printf("%f\t",scat[i]);
do{
do{
start(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, calc, &thread_id);
do capil(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, leaks, scat,
calc, &thread_id);
while (calc[thread_id].iesc == 0); /* perform capil until iesc not equal to 0 anymore */
}
while(calc[thread_id].iesc == -2); /* only do count etc if iesc!=-2, else redo start */
count(absmu, ctvar, &cap, &icount, profile, leaks, &imstr,calc, &thread_id);
}
while(calc[thread_id].iesc == -3);
sum_irefl[thread_id] = sum_irefl[thread_id] + calc[thread_id].i_refl;
if(icount%1000 == 0 && thread_id == 0) printf("%d\t%ld\t%f\n",icount,calc[0].i_refl,
calc[0].rh[2]);
}
(start, capil, count
) 일부 변수는 새 값으로 작성됩니다,이 calc,imstr,sum_irefl
및 leaks
의 경우입니다. 공유로 설정하여 각 스레드가 액세스 할 수 있도록합니다. 그러나, 예를 들어 calc
같은 메모리 경주에 대한 기회가 있다고 생각하지 않는다. 각 스레드는 (고유 한 thread_id
을 통해 액세스되는) 자체 변수를 가지며 다른 공유 변수는 다음과 같이 경쟁 할 수있다. 그들은 어느 시점에서 읽히지 않습니다. 아마도 나는 메모리 경주의 위험을 오해하고 있습니다. 그러나 여기에 문제가 있다고 생각하지 않습니다 ...
변수는 이전에 threadsafe로 만들어졌지만 문제가 아닌 것으로 가정) 병렬 루프 중에 만 읽혀 지므로 다시 문제가 무엇인지 알 수 없습니다. 또한 병렬 루프의 시작 부분에있는 각 변수에 있어야하는 값이 있는지 확인했습니다. 그래서 병렬 섹션에서 하나 이상의 코어를 사용하여 프로그램을 실행할 때 다른 값을 얻을 수 있습니다.
나는 이것이 앞으로 나아갈 것이 많지 않다는 것을 알고 있지만, 그럼에도 불구하고 여러분 중 일부는 아이디어가 있기를 바랍니다. 더 많은 정보가 필요하다면, 나에게 더 많이 제공 할 수 있기 때문에 언제든지 물어보십시오.
내가 궁금해하는 것들 : 결국 유해한 메모리 경쟁이 가능할 수 있습니까? 잘못 될 수있는 다른 것을 본 적이 있습니까? 멀티 코어 프로그램을 확인하는 데 사용할 수있는 (상대적으로) 사용하기 쉬운 프로그램을 알고 있습니까?
여기에 분명히 누락 된 것이 있습니다. 병렬 루프 컨텍스트에서 스레드 ID를 가져와 사용하는 이유는 무엇입니까? 루프와 완전히 독립적 인 calc 변수에 액세스하고 있습니까? 나중에 다른 곳으로 병합됩니까?최소한 스레드 ID를 가져 와서 스레드 별 작업을 수행하는 omp 병렬 영역과 스레드 독립적 작업을 분산시키는 작업 공유 구조를 위해 포함 된 omp 병렬 영역으로 분할해야합니다. – njustn
calc 변수는 병렬 for 루프 다음에 실제로 병합됩니다. 나는 또한 당신의 마지막 발언을 이해한다고 생각하지만, '문제'는 for 루프 동안 스레드 특정 작업 (예 : calc [thread_id] .iesc는 새로운 값과 같은 것을 얻는다. 그래서 내가 보는 방법은 for 루프 스레드를 독립적으로 만들 수 없습니다. 하지만 아마도 내가 너를 오해하고있다. 내가 원래의 질문에서 언급 한 코드를 사용하여 나눌 수있는 병렬 코드 예제와 지역 코드 예제를 작성할 수 있습니까? – user2257570
@ user2257570 어떤 난수 생성기를 사용하고 있는지 알려주시겠습니까? openmp에서 안전하게 사용할 수있는 생성기에 관심이 있습니다. – altroware