forrtl: серьезный (104): неверное значение спецификатора STATUS = для подключенного файла, блок -1, файл CONOUT $

У меня есть процедура Fortran, которая открывает много текстовых файлов, записывает данные из цикла времени. Эта подпрограмма использует open с опцией newunit, эта единица сохраняется в объекте, чтобы потом записывать вещи в файлы. В большинстве случаев это работает нормально, но когда программе необходимо одновременно открыть большое количество N файлов, я получаю следующую ошибку:

**forrtl: severe (104): incorrect STATUS= specifier value for connected file, unit -1, file CONOUT$**

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

Я включил минимальный образец кода с классом timeSeries, включая процедуру, которая создает два файла:

  • первый файл fileName1 открывается и закрывается сразу после записи внутри
  • второй файл fileName2 остается открытым для записи вычислений, вычисленных во временном цикле позже, и закрывается в конце временного цикла.

Пример состоит из двух следующих файлов. Он прерывается для i = 32639.

main.f90:

program writeFiles

use TS

logical :: stat
integer :: i, istep, N, NtimeSteps
character(len=16) :: fileName1, fileName2
character(len=300) :: path
type(timeSeries), dimension(:), allocatable :: myTS

call getcwd( path )

path = trim(path) // '\Output_files'
inquire(directory = trim(path), exist = stat )
if (.not. stat) call system("mkdir " // '"' // trim(path) // '"' )

N = 50000
NtimeSteps = 100
allocate(myTS(N))

do i = 1, N
    write(fileName1,'(a6,i6.6,a4)') 'file1_', i, '.txt'
    write(fileName2,'(a6,i6.6,a4)') 'file2_', i, '.txt'
    call myTS(i)%createFiles(trim(path),fileName1,fileName2)
end do

do istep = 1, NtimeSteps
    #
    #compute stuff
    #
    do i = 1, N 
         write(myTS(i)%fileUnit,*) 'stuff'
    end do
end do

do i = 1, N
    close(myTS(i)%fileUnit)
end do

end program writeFiles

module.f90:

module TS

    type timeSeries
    integer :: fileUnit

    contains

    procedure :: createFiles       => timeSeries_createFiles

    end type timeSeries

    contains

    subroutine timeSeries_createFiles(this,dir,fileName1,fileName2)
        class(timeSeries) :: this
        character(*) :: dir, fileName1, fileName2 

        open(newunit = this%fileUnit , file = dir // '\' // fileName1, status = 'replace') !error occurs here after multiple function calls
        write(this%fileUnit,*) 'Write stuff'
        close(this%fileUnit)
        open(newunit = this%fileUnit , file = dir // '\' // fileName2, status = 'replace') 
    end subroutine timeSeries_createFiles

end module

Есть идеи о причине этой ошибки? Есть ли ограничение на количество одновременно открытых файлов? Может быть, это связано с проблемой памяти?

Я использую Intel (R) Visual Fortran Compiler 17.0.4.210


person abenhamou    schedule 02.03.2018    source источник
comment
Пожалуйста, добавьте детали вашего компилятора (включая версию) и попытайтесь сделать полный пример для нас. Если у вас -1 выходит из newunit, значит, у вас проблема.   -  person francescalus    schedule 02.03.2018
comment
Спасибо, я добавил минимальный образец кода и свою версию компилятора   -  person abenhamou    schedule 02.03.2018
comment
50000 открытых файлов - это немного для большинства систем.   -  person albert    schedule 02.03.2018
comment
@HighPerformanceMark ОК, я над этим работаю. Извините, я еще не привык к привычкам Stackoverflow   -  person abenhamou    schedule 02.03.2018
comment
Операционные системы обычно имеют некоторое ограничение на количество файлов, которые они могут открывать одновременно - открытый файл потребляет некоторое количество ресурсов (небольшой объем данных для каждого из них). Для меня не удивительно, что попытка открыть 50 000 файлов исчерпывает пределы вашей конфигурации. Вы можете поднять лимит с помощью какого-либо параметра конфигурации o / s. Но на мой взгляд (старый, горький и извращенный) дизайн программного обеспечения, который зависит от открытия 50 000 файлов, не работает, и вам лучше изменить свой подход.   -  person High Performance Mark    schedule 02.03.2018


Ответы (1)


У Windows есть эта интересная привычка не освобождать все ресурсы для закрытого файла в течение короткого времени после того, как вы закрыли его. Я видел, как возникают и исчезают подобные проблемы на протяжении десятилетий. Моя обычная рекомендация - вызвать SLEEPQQ с продолжительностью полсекунды после ЗАКРЫТИЯ, если вы собираетесь сделать еще одно ОТКРЫТИЕ вскоре после этого для того же файла. Но здесь вы этого не делаете.

Здесь есть еще кое-что, что вызывает недоумение. Сообщение об ошибке, относящееся к модулю -1 и CONOUT $, не должно появляться при открытии явного файла и использовании NEWUNIT. В реализации Intel числа NEWUNIT начинаются с -129 и оттуда становятся более отрицательными. Единица -1 используется для PRINT или WRITE (*), а CONOUT $ - это консоль. STATUS = 'REPLACE' не действителен для устройства, подключенного к консоли. То, что номер нового блока будет -32768, говорит о внутреннем ограничении NEWUNIT в библиотеках Intel.

Я провел собственный тест и увидел, что если вы используете NEWUNIT и закроете устройство, номера устройств упадут до -16384, а затем снова вернутся к -129. Это нормально, если вы действительно закрываете модули, но никогда не закрываете второй открытый файл, поэтому вы, по крайней мере, открываете максимальное количество файлов NEWUNIT. Я бы порекомендовал найти другой способ решения проблемы, который не требовал бы открытия тысяч файлов.

person Steve Lionel    schedule 02.03.2018