내 문제는 관련되거나 심지어 동일한 문제로 묘사 된 것 같아 here. 그러나 실제로 일어나는 일을 이해하지 못합니다.병렬 환경에서 서브 루틴 호출
I는 gfortran 컴파일러 OpenMP를 사용하고 난 할 다음 태스크있다 : I는 X
및 Y
y는 좌표 x 좌표와 이차원 표면 밀도 분포 F(X, Y)
있다. 행렬 F
은 크기가 Nx
x Ny
입니다.
이제 좌표가 Xp(i)
및 Yp(i)
이므로이 점에 밀도를 보간해야합니다 (F
). 이 문제는 병렬 처리를 위해 만들어졌습니다.
i
을 제외한 모든 항목이 공유됩니다. interp2d
함수는 몇 가지 간단한 선형 보간 작업을 수행하고 있습니다.
하나의 스레드에서는 문제가 없지만 멀티 스레드에서는 실패합니다. Numerical Recipes에서 가져온 hunt
-subroutine으로이 문제를 추적 한 결과, interp2d
이 호출되었습니다. hunt
- 서브 루틴은 기본적으로 과 같은 인덱스 ix
을 계산합니다. 이것은 보간의 시작점을 얻는 데 필요합니다. 그것을 멀티 스레딩으로
하나 개의 스레드가 hunt
에서 올바른 인덱스 ix
및 Xp(i)
그 시점에 근처에도없는 경우에도 다음 hunt
를 호출 동일한 인덱스를 가져옵니다 스레드를 얻는 것을, 이제 다음마다 발생합니다.
!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(i)
do i=1, Nmax
! Some stuff to be done here
!$OMP CRITICAL
Fint(i) = interp2d(Xp(i), Yp(i), X, Y, F, Nx, Ny)
!$OMP END CRITICAL
! Some other stuff to be done here
end do
!$OMP END PARALLEL DO
을하지만 이것은 효율성을 감소 :
나는 CRITICAL
환경을 사용하여 이러한 문제를 방지 할 수 있습니다. 예를 들어 세 개의 스레드를 사용하면 CRITICAL
환경에서 평균 1.5의로드가 발생합니다. 내가 평균 2.75의로드 평균을 가지고 있지 않더라도 잘못된 결과와 경우에 따라 SIGSEGV
런타임 오류가 발생합니다.
정확히 여기서 무엇이 일어나고 있습니까? 모든 스레드가 동일한 hunt
-subroutine을 호출하고 있으며 동시에 처리하는 경우 충돌이있는 것으로 보입니다. 말이 돼?
어떻게 방지 할 수 있습니까?
'hunt' 서브 루틴이 스레드로부터 안전하지 않은 것처럼 보입니다. 'critical2' 지시자를'interp2d' 호출에서'interp2d' 호출로 옮깁니다. (가능한 한 낮은 수준으로). – Gilles
'interp2d'와'hunt' 루틴의 코드를 게시 할 수 있습니까? 일반적으로 코드를 작성하는 데 '중요'해야하는 것은 동시에 여러 스레드가 읽고 쓰는 공유 리소스 (예 : 변수)가 있기 때문입니다. – smateo
Numerical Recipes에서 서브 루틴을 게시 할 수 있는지 확실하지 않습니다. 그러나 나는 나중에 단순화 된 것을 게시 할 것이다. 지금까지 모든 스레드가 동일한 스택에 액세스하고 때로는 루틴의 실행 시간에 따라 스택에서 올바른 순서로 더미 변수를 읽지 않는다고 생각합니다. 그게 말이 되니? 모든 스레드가 자신의 전용 스택을 갖도록 강제 할 수 있습니까? – Sebastian