Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran OpenMP代码中的伸缩性差和分段错误_Fortran_Segmentation Fault_Openmp - Fatal编程技术网

Fortran OpenMP代码中的伸缩性差和分段错误

Fortran OpenMP代码中的伸缩性差和分段错误,fortran,segmentation-fault,openmp,Fortran,Segmentation Fault,Openmp,我在用并行do执行程序时遇到了一些问题。下面是一个测试代码 module test use, intrinsic :: iso_fortran_env, only: dp => real64 implicit none contains subroutine Addition(x,y,s) real(dp),intent(in) :: x,y real(dp), intent(out) :: s s = x+y end subroutine Addition f

我在用并行do执行程序时遇到了一些问题。下面是一个测试代码

module test
use, intrinsic :: iso_fortran_env, only: dp => real64
implicit none
contains

subroutine Addition(x,y,s)
    real(dp),intent(in) :: x,y
    real(dp), intent(out) :: s
    s = x+y
end subroutine Addition

function linspace(length,xi,xf) result (vec)
! function to create an equally spaced vector given a begin and end point
    real(dp),intent(in) :: xi,xf
    integer, intent(in) :: length
    real(dp),dimension(1:length) :: vec
    integer ::i
    real(dp) :: increment

    increment = (xf-xi)/(real(length)-1)
    vec(1) = xi
    do i = 2,length
        vec(i) = vec(i-1) + increment
    end do
end function linspace
end module test

program paralleltest
use, intrinsic :: iso_fortran_env, only: dp => real64
use test
use :: omp_lib
implicit none
integer, parameter :: length = 1000
real(dp),dimension(length) :: x,y
real(dp) :: s
integer:: i,j
integer :: num_threads = 8
real(dp),dimension(length,length) :: SMatrix

 x = linspace(length,.0d0,1.0d0)
 y = linspace(length,2.0d0,3.0d0)

!$ call omp_set_num_threads(num_threads)
!$OMP PARALLEL DO
do i=1,size(x)
    do j = 1,size(y)
    call Addition(x(i),y(j),s)
    SMatrix(i,j) = s
    end do
end do
!$OMP END PARALLEL DO

open(unit=1,file ='Add6.dat')
do i= 1,size(x)
    do j= 1,size(y)
        write(1,*) x(i),";",y(j),";",SMatrix(i,j)
    end do
end do
close(unit=1)
end program paralleltest
我以以下方式运行程序
gfortran-8-fopenmp paralleltest.f03-o pt.out-mcmodel=medium
,然后
export OMP\u NUM\u THREADS=8

这个简单的代码给我带来了至少两个关于并行do的大问题。第一个是,如果使用
length=1100
或更大的值运行,则会出现
分段错误(核心转储)
错误消息,但使用较小的值运行时不会出现问题。第二个是关于所需的时间。当我使用
length=1000
运行它时(使用
time./pt.out
运行),它所花费的时间是
1732s
,但是如果我以顺序方式运行它(不调用
-fopenmp
库和
任务集-c4 time./pt.out
),它需要
1714s
。我猜这两种方法之间的差异出现在一个更长更复杂的代码中,在这个代码中并行更有用。事实上,当我用更复杂的计算与八个线程并行运行时,时间减少了一半,而不是我预期的八分之一。鉴于此,我的问题是,任何优化是否总是可用,还是依赖于代码?第二,有没有一种友好的方法来控制哪个线程运行哪个迭代?这是第一次运行第一个
length/8
迭代,以此类推,就像用不同的代码执行几个
任务集
,其中每个任务集都是我想要的迭代。

正如我所评论的,分段错误已经在别处处理过,我将使用可分配数组,但是您也可以使用
ulimit-s
设置堆栈大小

关于时间,几乎所有的运行时都用于将数组写入外部文件

但是,即使你删除了它,并且只使用
omp\u get\u wtime()
测量并行部分花费的时间,并增加问题的大小,它仍然不能很好地扩展。这是因为CPU要做的计算非常少,而且要向内存写入大量数组(访问主内存的速度很慢-缓存未命中)

正如Jean-Claude Arbaut指出的,您的循环顺序是错误的,这使得访问内存的速度更加缓慢。一些编译器可以通过更高的优化级别(
-O2
-O3
)来为您更改这一点,但只有一些编译器可以

更糟糕的是,正如吉姆·考尼所指出的,你有一个。多个线程尝试使用相同的
s
进行读写,程序无效。您需要使用
private(s)
s
设为private


通过上述修复,我得到了一个大约快两倍的并行部分,有四个内核和四个线程。不要尝试使用超线程,它会减慢程序的速度

如果你让CPU做更多的计算工作,比如
s=Bessel_J0(x)/Bessel_J1(y)
它的伸缩性对我来说相当好,四个线程的速度几乎是四倍,而超线程确实让它加快了一点



最后,我建议删除线程数的手动设置,这对于测试来说是一件痛苦的事情。如果删除该选项,可以轻松使用
OMP\u NUM\u THREADS=4./a.out

对于SEGFULT,这是一个众所周知的问题,我们有许多重复项使用可分配数组。只要在这里搜索,您就会发现许多类似的错误。我建议从你的问题中删除这一部分。在我看来,你需要“私人”。这不会影响SEGV,但会影响结果!旁注:Fortran是,而您的内部循环在SMatrix行上工作。不支持缓存。@JimCownie私有属性应该在模块或程序的主要部分中给出?@Daniel在omp并行程序中。您希望每个线程都有自己的s副本。您的代码现在只有一个共享副本,因此当多个线程执行循环时,它们都分配给相同的“s”,并在存储结果之前覆盖彼此的结果。另一种方法是完全消除“s”,并将Smatrix(i,j)作为加法的最终参数传递…@King好吧,我并没有真正禁用它,它必须在内核或BIOS中完成。我只是在4核8超线程CPU上使用了4个线程或8个线程。