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
Fortran 已在另一个单元程序中打开的文件被中止。_Fortran_Openmp_Gfortran - Fatal编程技术网

Fortran 已在另一个单元程序中打开的文件被中止。

Fortran 已在另一个单元程序中打开的文件被中止。,fortran,openmp,gfortran,Fortran,Openmp,Gfortran,以下是我编写的用于测试多线程独立读取文件的程序: program he use omp_lib implicit none integer :: i, a(20), funit open(unit=2, file='dat/he', status='replace') write(2, '(i2/, i2/, i2/, i2)') 1, 3, 5, 7 close(2) !$omp parallel do num_threads(20

以下是我编写的用于测试多线程独立读取文件的程序:

program he
    use omp_lib

    implicit none
    integer :: i, a(20), funit

    open(unit=2, file='dat/he', status='replace')
    write(2, '(i2/, i2/, i2/, i2)') 1, 3, 5, 7
    close(2)

    !$omp parallel do num_threads(20) private(funit)
    do i = 1, 20
        funit=100+omp_get_thread_num()
        open(funit, file='dat/he', status='old')
        read(funit,'(i2)') a(i)
    end do
    !$omp end parallel do

    print *, a
end program he
我用gfortran编译器编译了它,没有得到任何错误:
gfortran-fopenmp-o exe a.f90
,并运行
/exe
,但每次运行
/exe
时都会得到不同的错误。但是,我也使用ifort编译了它:
ifort-qopenmp-oexe a.f90
,并成功地运行了它,
/exe

gfortran在运行时出现的错误之一是

At line 15 of file fortran_learning_book.f90 (unit = 102)
Fortran runtime error: File already opened in another unit

Program aborted. Backtrace:

Program aborted. Backtrace:
#0  0x10c30aff2
#0  0x10c30aff2

Program aborted.

我怀疑问题的根源是您没有为
open
语句提供任何
action
参数。实际上,允许对新打开的文件执行的默认操作(无论是
read
write
还是
readwrite
)都是实现定义的。因此,您可能会在例如
readwrite
模式下并行打开同一文件数次,特别是允许来自多个独立单元的
write
模式,从而导致潜在的文件不一致。然后编译器和/或运行时库可能会也可能不会检查这种一致性,并将其报告为错误。。。从外观上看,gfrotran和ifort在两个部分(默认操作和/或RTL检查)中至少有一个部分采用了不同的方法

唯一的情况是,这种并行打开同一个文件的方式是“合法的”,并且安全的,前提是您限制对读取模式的访问。因此,将
action='read'
添加到
open
语句可能会解决这个问题。事实上,它在gfortran 5.4.0版中为我做到了这一点


现在,我们处于一个灰色地带(至少对我来说),我真的不知道这一切有多便携/符合标准。因此,尽管我认为这解决了您当前的问题,但我无法评论代码在不同编译器之间的整体可移植性。

您的代码不是有效的标准Fortran,因此在不同的编译器中表现出未定义的行为。Fortran标准非常清楚:

如果一个文件已连接到一个单元,则不应使用不同单元对该文件执行OPEN语句

(ISO/IEC 1539-1-2010第9.5.6.1节)

与其他一些语言不同,标准Fortran不允许多次打开同一文件

编辑:正如IanH所指出的,即将发布的Fortran标准(非正式称为Fortran 2015)将正式取消该限制,但仍将由实施部门决定是否允许多个连接到同一文件


GNU Fortran和“英特尔Fortran”都能够编译带有OpenMP扩展名的正确的Fortran代码。

一个文件在给定时间不能连接到多个单元,无论指定了什么操作。编译器在违反该规则时所做的是自己的选择。Fortran 2008规范中的9.5.6.1:“8.如果一个文件已经连接到一个单元,则不应在该文件上执行具有不同单元的OPEN语句。”@Gilles My gfortran版本为5.3.0,添加
action='read'
并不能解决问题。我试图通过macport
sudo port install gcc5@5.4.0安装5.4.0版,但出现了一个错误:@Gilles-->gcc5的计算依赖项--->清理gcc5--->扫描二进制文件以查找链接错误警告:错误解析文件/Applications/MacPorts/Python 2.7/Python Launcher.app/Contents/MacOS/Python Launcher:错误打开或读取文件警告:错误解析文件/Applications/MacPorts/AquaTerm.app/Contents/MacOS/AquaTerm:打开或读取文件时出错--->未找到损坏的文件。@Gilles您是如何安装5.4.0版的?\n如果代码中有问题,请询问如何解决。不要问哪个编译器更好,这完全是离题的。只是修复你的错误代码,不要责怪编译器。顺便说一句,我仍然不知道你为什么想要这个。我读了你的最后一个问题,但我还是不知道。我只能向您保证,像这样将单个文件的
open
语句放在并行循环中是个坏主意。这种方法是将疯狂转化为代码!请原谅我的直言不讳(或者不直言不讳,如果你愿意的话,请生气),但看起来OP还没有足够的OpenMP经验来了解这种方法有多错误。OpenMP是关于共享内存计算的。让一个线程将
a
的值读取到内存中,使其成为一个共享对象,并让各个线程对元素执行它们希望的操作。这在F2015中发生了变化—“一个文件是否可以同时连接到多个单元取决于处理器。”(12.5.4p4)。但ifort似乎没有对此抱怨。ifort中有这样的限制吗?大多数编译器在某种程度上偏离了标准。我不确定是否有一个Fortran编译器从第一个字母到最后一个字母都遵循这个标准。