Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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
Arrays openmp fortran精简版和critical不适用于阵列_Arrays_Fortran_Openmp - Fatal编程技术网

Arrays openmp fortran精简版和critical不适用于阵列

Arrays openmp fortran精简版和critical不适用于阵列,arrays,fortran,openmp,Arrays,Fortran,Openmp,我目前正在尝试使用fortran FE有限元代码与openmp一起工作。我在所有元素上都有一个循环(我想并行工作)。下面是代码中不起作用的简化部分 !$omp parallel do default(none) shared(nelm,A,res,enod) private(ie,Fe,B,edof) do ie=1,nelm call calcB(B,A(:,ie)) call calcFe(Fe,B) write(*,*

我目前正在尝试使用fortran FE有限元代码与openmp一起工作。我在所有元素上都有一个循环(我想并行工作)。下面是代码中不起作用的简化部分

     !$omp parallel do default(none) shared(nelm,A,res,enod) private(ie,Fe,B,edof)     
    do ie=1,nelm 
       call calcB(B,A(:,ie))
       call calcFe(Fe,B)
       write(*,*) Fe !writes Fe=40d0, this is correct

        call getEdof(edof,enod(:,ie))
        !$OMP CRITICAL      
        res(edof)=res(edof)+fe
        !$OMP END CRITICAL 
        enddo 
!$omp end parallel do
代码的目的是计算力Fe,然后将其添加到edof处的res。使用calcFe计算力,计算的力是正确的,但循环后得到的res不正确

如果我用简单的Fe=40d0替换calcFe,然后将其添加到res,则循环后的结果是正确的

     !$omp parallel do default(none) shared(nelm,A,res,enod) private(ie,Fe,B,edof)


    do ie=1,nelm 
       call calcB(B,A(:,ie))

       Fe=40d0

        call getEdof(edof,enod(:,ie))
        !$OMP CRITICAL      
        res(edof)=res(edof)+fe
        !$OMP END CRITICAL 
        enddo 
!$omp end parallel do
是什么导致了这个错误?在这两种情况下,Fe=40d0都声明为私有,但其中只有一个给出了正确的结果。而不是使用!$关键我可以使用减少,但它会给出相同的错误。在程序中,还使用了几个大的稀疏矩阵,但在循环过程中使用被动/不使用。我的主管以前在使用openmp和稀疏矩阵时遇到过问题,并怀疑它们使用的是相同的内存。如果错误不明显,最好使用哪个调试器?我是fortran、openmp和编程的新手。 我使用iPort进行编译,我的操作系统是ubuntu

编辑:添加了可以运行的简化代码,尽管此代码有效 在代码中有两个循环,并行循环和串行循环,它们应该给出相同的结果res和res2

还有制作文件

    FF = ifort -O3 -openmp
OBJ1  = main.f90
ls: $(FORT_OBJS)
    $(FF) -o exec $(OBJ1)
不幸的是,这段代码可以工作,所以我无法复制错误。res2和res以串行和并行方式计算。在我的实际程序中,我将所有值都设置为1d0,以获得常数fe。计算的fe是正确的,如果我在计算之后添加write*,*fe,我会看到值是正确的。然后,我将这些值添加到res2中,并将它们与串行res进行比较。然后,它们会有很大的差异,因此没有数值舍入误差。如果我在主程序中简单地声明fe=2304,即使使用write时fe已经是2304,我也会得到正确的答案

在我的真实程序中,所有的子程序都在不同的模块中,我需要为此特别小心吗?
此外,在其中一个模块中使用了一些全局变量,它们是只读的,但由于它们没有在子例程中声明,所以它们不会自动变为私有的?这应该没有问题,因为我将用于计算fe的所有变量设置为常数,全局变量不直接用于计算fe

解决了它,它在我为模块的makefile添加-openmp时开始工作。显然,模块需要使用-openmp进行编译,而不仅仅是主文件。

在这里使用reduce,在这种情况下,critical是个坏主意。尝试创建一个完全可编译的自包含示例,我们可以编译并运行它。解释一下哪个值是错误的结果,你希望得到哪个结果。如果没有一段代码来重现错误,恐怕我们什么都做不了。通常,当您试图孤立一个小的工作示例时,您自己会发现问题。由于它们未在子例程中声明,因此它们不会自动变为私有。。。不,但如果不改变它们,它们可以保持共享,这不是问题。
    FF = ifort -O3 -openmp
OBJ1  = main.f90
ls: $(FORT_OBJS)
    $(FF) -o exec $(OBJ1)