当 OMP_NUM_THREADS 大于 1 时,fortran 分段错误

问题描述 投票:0回答:1

所以我正在使用以下

a.out
文件执行
runaout.sh
(编译的fortran代码)

#!/bin/bash
#SBATCH --time=00:15:00
#SBATCH --job-name=mhsw9
#SBATCH --nodes=1
#SBATCH --nodelist=komputasi09
whoami
hostname
ulimit -s unlimited
export OMP_NUM_THREADS=128
echo "9"
ulimit -s unlimited
/a.out      

我尝试将 OMP_NUM_THREADS 更改为任何大于 1 的值。我尝试了 2、64、128,但都是分段错误。在代码中我已经设置了 ulimit -s unlimited,但仍然存在分段错误。我用

gfortran -fopenmp assignment1.f90    

编译fortran代码。下面是赋值1.f90代码,该代码正在运行matmul计算

program sample3
use omp_lib
implicit real(8)(a-h,o-z)
parameter (n=8192)
real(8) a(n,n),b(n,n),c(n,n)
real*8 t1,t2
a=0.0d0
call random_number(b)
call random_number(c)
write(6,50) ' Matrix Size =',n
50 format(1x,a,i5)
t1=omp_get_wtime()
!$OMP parallel do reduction(+:a)
do j=1,n
do k=1,n
do i=1,n
    a(i,j)=a(i,j)+b(i,k)*c(k,j)
enddo
enddo
enddo
!$OMP end parallel do
t2=omp_get_wtime()
write(6,60)'Execution Time = ',t2-t1,' sec','A(n,n) = ',a(n,n)
60 format(1x,a,f10.3,a,1x,a,d24.15)
stop
end       

更让我困惑的是,我的朋友运行相同的代码并没有遇到分段错误。有人可以帮我吗?我哪里做错了?

我使用 slurm 执行文件

sbatch runaout.sh
segmentation-fault fortran openmp slurm
1个回答
0
投票

我不确定问题到底出在哪里,但是这段代码有很多不好的做法(其中一些已经由@IanBush指出):

    应使用
  • implicit none
    并显式声明所有变量
  • real*8
    是非标准的,
    real(8)
    不便于携带。使用
    double precision
    代替,或者:
integer, parameter :: dp=kind(1d0)
real(dp) :: ...
  • 您的每个阵列大约有 800 MB。尽管可以按照您的方式声明如此大的数组 (*),但通常最好将它们声明为可分配的:
real(dp) :: a(:,:)
...
allocate( a(n,n) )
  • 减少如此大的数组是一个坏主意:在幕后,每个线程都将创建数组的完整副本。不仅性能会很糟糕,而且需要大量内存(128 个线程 -> 大约需要 100GB)
  • 这里的要点是,您根本不需要任何减少,因为并行代码中的
    a(:,:)
    上没有竞争条件。
  • 你的编译命令行既不适合调试(它应该类似于
    gfortran -Wall -fcheck=all -O -g -fopenmp
    ),也不适合性能(至少
    gfortran -O3 -fopenmp

(*) 我已经用 gfortran 测试了您的代码,只要代码是在没有 OpenMP 的情况下编译的,您的代码的静态声明就可以。一旦涉及 OpenMP,即使没有减少和单个线程,它也会导致段错误。制作数组

allocatable
解决了问题,但我无法真正解释原因。

© www.soinside.com 2019 - 2024. All rights reserved.