2012-04-22 3 views
1

Fortran과 OpenMP를 사용하고 있지만, 큰 배열이있을 때 OpenMP를 사용하여 루프를 병렬 처리하려고 할 때 계속 문제가 발생합니다. 예를 들어, 다음 코드는이 Makefile을 사용OpenMP 대형 배열에서의 충돌

PROGRAM main 
IMPLICIT NONE 
INTEGER, PARAMETER :: NUMLOOPS = 300000 
REAL(8) :: TESTMAT(NUMLOOPS) 
INTEGER :: i,j 

!$OMP PARALLEL SHARED(TESTMAT) 
!$OMP DO 
DO i=1,NUMLOOPS   
    TESTMAT(i) = i 
END DO 
!$OMP END DO 
!$OMP END PARALLEL 

write(*,*) SUM(TESTMAT)/(NUMLOOPS) 

END PROGRAM main 

을 컴파일 :

.SUFFIXES: .f90 

F90 = gfortran 
FFLAGS_PFM = -ffree-form -ffree-line-length-none -fopenmp 
LIB = -llapack 
OBJ90 = main.o 

main: $(OBJ90) 
    $(F90) $(FFLAGS_PFM) -o [email protected] $(LIB) $(OBJ90) 

${OBJ90}: %.o: %.f90 
    $(F90) $(FFLAGS_PFM) $(LIB) -c -o [email protected] $< 

충돌을 윈도우 머신에, gfortran을 사용하여 컴파일 할 때. 그러나 NUMLOOPS 값을 약 260000보다 작게 변경하면 프로그램이 정상적으로 실행됩니다. 비슷하게 약 1000x1000의 행렬이 충돌합니다 (실제로는 500x500을 초과하는 것이 작동하지 않습니다). 따라서 OpenMP를 사용할 때 최대 배열 크기가 허용되는 것 같습니다. 나는이 종류의 무엇이든을 우연히 만나지 않았다. 나는 동일한 결과를 가진 여러 개의 윈도우 머신을 시도했지만, 모두 동일한 설정을 사용한다. gfortran 컴파일러가있는 Windows 7. 코드는 항상 문제없이 컴파일되지만 실행하면 충돌합니다.

답변

3

OpenMP는 인스턴스화 할 수있는 배열의 크기에 제한을 두지 않습니다. 포트란 컴파일러는; 그 문서를 확인하십시오.

사용하는 하드웨어에 한계가 있습니다. 컴퓨터에서 HUGE (int)보다 큰 인덱스 값을 가진 배열을 선언 할 수 없습니다. HUGE (int)는 (2^31) -1 또는 (2^63) -1 (Fortran에는 부호없는 정수가 없음)이 될 가능성이 있기 때문에 이것은 현재 당신에게 영향을 미치지 않을 것입니다.

다른 제한 사항은 컴파일러에서 선언 할 수있는 변수의 크기에 제한이있을 수 있다는 것입니다. 나는 gfortran에 익숙하지 않지만, Google을 둘러 보거나 문서를 살펴 보는 것이 좋습니다. 많은 플랫폼에서 gfortran이 처리 할 수있는 스택의 크기에는 제한이있을 수 있습니다. 정적으로 선언 된 (즉, ALLOCATABLE이 아닌) Fortran 변수는 스택에 배치됩니다. 나는 이것이 당신의 문제의 뿌리라고 생각합니다.

컴파일 타임에 더 큰 배열을 선언하도록 컴파일러를 설득 할 수 없다면, 배열을 ALLOCATABLE로 만들고 런타임에 할당하십시오.

+1

답장을 보내 주셔서 감사합니다. TESTMAT를 할당 가능하게 만드는 것은 실제로 작동합니다!그러나, 나는 이것이 왜 처음에 발생하는지에 관해서는 여전히 궁금합니다. OpenMP 비트 (예 : OMP 선언 및 makefile의 -fopenmp 플래그)를 제거하면 위의 코드가 작동한다는 것을 잊었을 것입니다. 따라서 gfortran + openmp에만 해당하는 것으로 보입니다. 그러나 어느쪽으로 든 앞으로 나아가십시오, 다시 한번 감사드립니다! – user870029

+2

OpenMP 버전에서는 컴파일러가 실행 파일의 정적 위치 대신 스택에 배열을 넣을 수 있습니다.이 경우 스택 크기를 무제한으로 설정하여 문제를 해결할 수 있습니다. 일반적으로 "ulimit -s 무제한. – haraldkl

3

GNU Fortran에서 -fopenmp을 지정하면 -frecursive을 의미하므로 모든 로컬 변수 (대용량 배열 포함)가 자동으로 (즉 스택에 할당 됨) 의미합니다. Windows에서 스택 크기는 PE 실행 헤더 파일에서 고정되어 있으며 링크 단계에서 지정해야합니다. 이는 제한 메커니즘으로 동적으로 제어 할 수있는 Unix 시스템과 달리 대단히 다릅니다.

editbin /STACK:<size> yourexe.exe 

또는 GCC에 다음과 같은 옵션을 제공 : -Wl,--stack,<size in bytes>, <size in bytes> 원하는 스택 크기가

는 윈도우의 스택 크기가이 같은 명령 줄 Microsoft에서 editbin.exe를 사용할 수 있습니다 실행 늘리려면 바이트 단위. 최소한 전체 배열 (즉, 8*NUMLOOPS)과 로컬 변수 및 내용에 맞도록 스택 크기를 설정해야합니다.

2

동일한 문제가있었습니다. 내가 아는 한, -fopenmp 옵션은 기본적으로 -frecursive와 함께 온다. 이 후자는 스택에있는 큰 배열을 강제하고 그것은 우리의 문제입니다.

의사 솔루션은 다른 옵션을 사용하여 -fopenmp에 의해 암시 된 -frecursive 옵션을 덮어 쓰는 것입니다. 이를 위해 gfortran 컴파일러 옵션에 -fno-automatic 옵션을 추가합니다.