#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 с помощью macportsudo 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?