Файл, уже открытый в другой модульной программе, прерван.

#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) 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 -o exe 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.
  

Комментарии:

1. У вас есть проблема в вашем коде, спросите, как ее исправить. Не спрашивайте, какой компилятор лучше, это полностью оффтопично . Просто исправьте свой глючный код, не вините компилятор.

2. Кстати, я до сих пор не знаю, зачем вам это нужно. Я прочитал ваш последний вопрос, но я все еще не знаю. Я могу только заверить вас, что размещение open инструкции для одного файла в параллельном цикле, подобном этому, является плохой идеей.

3. Этот подход — безумие, превращенное в код! Простите мою прямоту (или нет, обижайтесь, если хотите), но, похоже, у OP еще недостаточно опыта работы с OpenMP, чтобы понять, насколько ошибочен этот подход. OpenMP предназначен для вычислений с общей памятью. Попросите один поток прочитать значения a в память, сделать его общим объектом и позволить отдельным потокам делать с элементами все, что они пожелают.

Ответ №1:

Ваш код не является допустимым стандартным Fortran и поэтому демонстрирует неопределенное поведение с различными компиляторами. Стандарт Fortran довольно ясен, что:

Если файл уже подключен к модулю, оператор OPEN для этого файла с другим модулем не должен выполняться.

(Раздел 9.5.6.1 из ISO / IEC 1539-1: 2010)

В отличие от некоторых других языков, стандартный Fortran не позволяет открывать один и тот же файл несколько раз.

Редактировать: Как отметил IanH, предстоящий стандарт Fortran (неофициально известный как Fortran 2015) официально снимет ограничение, но все равно оставит на усмотрение реализации решение о том, разрешено ли несколько подключений к одному и тому же файлу или нет.

Как GNU Fortran, так и Intel Fortran способны компилировать правильный код Fortran с расширениями OpenMP.

Комментарии:

1. Это изменяется с помощью F2015 — «Это зависит от процессора, может ли файл быть подключен к нескольким устройствам одновременно». (12.5.4p4).

2. Но ifort, похоже, не жалуется на это. Есть ли такое ограничение в ifort?

3. Большинство компиляторов так или иначе отклоняются от стандартов. Я не уверен, был ли вообще компилятор Fortran, который следует стандарту от первой до последней буквы.

Ответ №2:

Я подозреваю, что причина вашей проблемы заключается в том, что вы не указали никаких action параметров в своем open заявлении. Действительно, действие по умолчанию для разрешения (или read , write или readwrite ) для вновь открытого файла определяется реализацией. Таким образом, вы потенциально открываете несколько раз параллельно один и тот же файл в readwrite режиме, например, позволяя, в частности write , режим из нескольких независимых модулей, что приводит к потенциальным несоответствиям файлов. Тогда компилятор и / или библиотека времени выполнения могут проверять (или не проверять) согласованность такого рода и сообщать об этом как об ошибке… Судя по тому, как это выглядит, gfrotran и ifort имеют разный подход по крайней мере в одной из двух частей (действие по умолчанию и / или проверка RTL).

Единственный случай, когда такое параллельное открытие одного и того же файла является «законным» и безопасным, — это если вы ограничиваете свой доступ режимом чтения. Поэтому добавление action='read' в ваш open оператор может просто устранить проблему. Действительно, он делает это для меня с помощью gfortran версии 5.4.0.

Теперь мы находимся в серой области (по крайней мере, для меня), и я действительно не знаю, насколько все это совместимо с переносимым / стандартным. Поэтому, хотя я считаю, что это решает вашу непосредственную проблему, я не могу прокомментировать общую переносимость кода между разными компиляторами.

Комментарии:

1. Файл не может быть подключен более чем к одному модулю в данный момент времени, независимо от того, какие действия указаны. То, что делает компилятор, когда кто-то нарушает это правило, является его выбором.

2. 9.5.6.1 из спецификации Fortran 2008: «8. Если файл уже подключен к модулю, оператор OPEN для этого файла с другим модулем не должен выполняться. »

3. @Gilles Моя версия gfortran — 5.3.0, и добавление action='read' не решает проблему. Я попытался установить версию 5.4.0 с помощью macport sudo port install gcc5 @5.4.0 , но получил сообщение об ошибке :

4. @Gilles —> Вычислительные зависимости для gcc5 —> Очистка gcc5 —> Проверка двоичных файлов на наличие ошибок связывания Предупреждение: Ошибка синтаксического анализа файла / Applications/ MacPorts/ Python 2.7/ Python Launcher.app/ Contents/ macOS / Python Launcher: Ошибка открытия или чтения файла Предупреждение: ошибка синтаксического анализа файла / Applications/MacPorts/AquaTerm.app/Contents/macOS / AquaTerm: Ошибка открытия или чтения файла —> Поврежденных файлов не найдено.

5. @Gilles Как вы установили версию 5.4.0?