2

Fortran と OpenMP を使用していますが、大きな配列がある場合に 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

この Makefile を使用してコンパイル:

.SUFFIXES: .f90

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

main: $(OBJ90)
    $(F90) $(FFLAGS_PFM) -o $@ $(LIB) $(OBJ90)

${OBJ90}: %.o: %.f90
    $(F90) $(FFLAGS_PFM) $(LIB) -c -o $@ $<

gfortran を使用してコンパイルされた Windows マシンでクラッシュします。ただし、NUMLOOPS 値を約 260000 未満に変更すると、プログラムは正常に実行されます。同様に、約 1000x1000 のマトリックスはクラッシュします (実際、約 500x500 を超えるものは機能しません)。したがって、OpenMP を使用する場合に許容される最大配列サイズがあるように見えますか? 私はこの種のものに出くわしたことはありません。複数のWindowsマシンで試してみましたが、同じ結果になりましたが、すべて同じ構成を使用しています.gfortranコンパイラを使用したWindows 7などです。コードは常に問題なくコンパイルされますが、実行するとクラッシュします。

4

4 に答える 4

4

-fopenmpGNU Fortran での指定-frecursiveは、すべてのローカル変数 (大きな配列も含む) が自動 (つまり、スタックに割り当てられる) であることを意味します。Windows では、スタック サイズは PE 実行可能ヘッダー ファイルで固定されており、制限メカニズムによって動的に制御できる Unix システムとは異なり、リンク フェーズで指定する必要があります。

Windows 実行可能ファイルのスタック サイズを増やすにはeditbin.exe、次のようなコマンド ラインで Microsoft から使用できます。

editbin /STACK:<size> yourexe.exe

-Wl,--stack,<size in bytes>または、GCC に次のオプションを指定<size in bytes>します。スタック サイズは、少なくとも配列全体 (つまり8*NUMLOOPS) とローカル変数などを収めるのに十分な大きさに設定する必要があります。

于 2012-05-04T12:15:17.883 に答える
3

OpenMP では、インスタンス化できる配列のサイズに制限はありません。Fortran コンパイラーは次のようになるかもしれません。そのためのドキュメントを確認してください。

使用しているハードウェアには制限があります。マシンで HUGE(int) より大きいインデックス値を持つ配列を宣言することはできません。HUGE(int) は (2^31)-1 または (2^63)-1 のいずれかである可能性が高いため (Fortran には符号なし整数がありません)、現時点ではおそらく影響はありません。

あなたに影響を与える可能性のあるもう1つの制限は、コンパイラが宣言できる変数のサイズに制限がある可能性が高いことです。私は gfortran に詳しくありませんが、Google で検索するか、ドキュメントを参照することをお勧めします。gfortran が処理できるスタックのサイズに制限がある可能性があります。多くのプラットフォームでは、静的に宣言された (つまり、ALLOCATABLE ではない) Fortran 変数がスタックに配置されます。これがあなたの問題の根源であると思います。

コンパイル時により大きな配列を宣言できるようにコンパイラを説得できない場合は、配列を ALLOCATABLE にして実行時に割り当ててみてください。

于 2012-04-22T17:40:00.617 に答える
0

コードを実行する前に、次の cmd: を挿入することで構成される以前のソリューションと比較して、より良いソリューションがありますulimit -s unlimited。これは、スタック サイズのデフォルトの制限を取り除くためです。

于 2019-08-08T12:56:54.610 に答える