массив времени выходит за пределы в моделировании?

Сейчас я пытаюсь запустить свою климатическую модель с новыми метеорологическими данными (которые предоставляются в формате netcdf вместо старого формата cray). Модель компилируется плавно, однако, когда приходит время для моделирования, модель работает хорошо в первый день, но останавливается на второй день моделирования, всегда на одном и том же временном шаге, независимо от того, какую дату начала я использую. Ошибка:

forrtl: серьезный (408): fort: (2): Нижний индекс № 1 массива TIMEVALS имеет значение 141, что больше верхней границы 140.

Итак, я провел небольшое исследование и просмотрел свой исходный код, чтобы увидеть, к какому типу относится массив timevals, и я обнаружил, что он относится к этим новым метеорологическим данным, которые имеют измерение времени, и такой массив времени состоит из 140 элементов. Каждый элемент представляет собой определенную дату и время метеоданных, которые модель должна использовать для моделирования... поэтому я начал думать, что это проблема моего кода, но мой коллега смог запустить модель без проблемы, что было странно для меня. Он скомпилировал модель с некоторыми другими настройками в Makefile, я не знаю, имеет ли это значение, я все еще не очень хорошо знаком с фортраном и т. д. Однако ниже приведена часть кода, которая использует этот массив TIMEVALS:

           CASE(2)        ! nudging data is in netcdf-format

           cfile = str_filter(ndg_file_nc,yr,mo,dy,hr,mi,se,ndgblock)
           CALL message('   Adjust date using file: ',TRIM(cfile))

           IF (p_parallel_io) THEN
             INQUIRE(file=cfile,exist=found)
             IF (.NOT.found) &
                CALL finish('NudgingInit','Nudging data file not found.')
             ndgfile%format = NETCDF
             CALL IO_open (cfile, ndgfile, IO_READ)
             CALL IO_INQ_DIMID(ndgfile%file_id, 'time', ndimid)
             CALL IO_INQ_DIMLEN(ndgfile%file_id, ndimid, nts)
             CALL IO_INQ_VARID(ndgfile%file_id, 'time', nvarid)
             ALLOCATE (timevals(nts))
             CALL IO_GET_VAR_DOUBLE (ndgfile%file_id, nvarid, timevals)
             ihead_nc(1) = FLOOR(timevals(1))                          ! ihead_nc(1) is YYYYMMDD
             ihead_nc(2) = INT((timevals(1)-ihead_nc(1))*24._dp)       ! ihead_nc(2) is HH
             DEALLOCATE (timevals)
           ENDIF

           IF (p_parallel) CALL p_bcast(ihead_nc, p_io)
           CALL inp_convert_date(ihead_nc(1),ihead_nc(2)*10000, ndg_date0)

             IF (p_parallel_io) THEN
             ! skip first record and read second header
             ALLOCATE (timevals(nts))
             CALL IO_GET_VAR_DOUBLE (ndgfile%file_id, nvarid, timevals)
             ihead_nc(1) = FLOOR(timevals(2))                          ! ihead_nc(1) is YYYYMMDD
             ihead_nc(2) = INT((timevals(2)-ihead_nc(1))*24._dp)       ! ihead_nc(2) is HH
             DEALLOCATE (timevals)
             CALL IO_close(ndgfile)
           ENDIF

           IF (p_parallel) CALL p_bcast(ihead_nc, p_io)
           CALL inp_convert_date(ihead_nc(1),ihead_nc(2)*10000, ndg_date1)

ndg_file и ndg_date относятся к подталкиванию (метеоданные). У вас есть идеи, что может вызвать эту ошибку?


person Fil X    schedule 03.06.2015    source источник
comment
Вы пытаетесь получить доступ к timevals(141), хотя timevals содержит только 140 элементов. Это то, что компилятор говорит вам. Однако это не может произойти в предоставленном вами фрагменте кода. Здесь вы получаете доступ только к timevals(1) и timevals(2). Пожалуйста, опубликуйте соответствующую (строку) кода, то есть строку, на которую жалуется компилятор!   -  person Alexander Vogt    schedule 03.06.2015
comment
Я не получаю никаких ошибок при компиляции кода. Я вижу ошибку только в файле журнала ошибок, который создает моя модель во время работы. Сообщение об ошибке, которое я написал вверху в первом посте, - единственная подсказка, которая у меня есть по этой проблеме.   -  person Fil X    schedule 04.06.2015
comment
Если вы скомпилируете свою модель с -traceback (и, возможно, -g), вы должны получить трассировку стека, которая покажет вам, где происходит сбой программы.   -  person RussF    schedule 04.06.2015
comment
Вы также не можете сейчас доверять результатам модели, даже если вам удастся запустить ее без сбоя. Вы должны сначала исправить ошибку.   -  person Vladimir F    schedule 04.06.2015
comment
@RussF: эта перекомпиляция, которую вы советуете, совершенно не нужна. OP уже получил абсолютно четкое представление о том, что это за ошибка и где она возникает в коде.   -  person High Performance Mark    schedule 04.06.2015
comment
Просто дикая догадка, убедитесь, что значение nts соответствует количеству данных, которые IO_GET_VAR_DOUBLE считывает из ваших файлов.   -  person Vladimir F    schedule 04.06.2015
comment
Извините за вопрос новичка, как я могу это проверить?   -  person Fil X    schedule 04.06.2015
comment
@ХПМ. Я не уверен. Этот код, по-видимому, является частью набора моделей атмосферы/океана/льда Института Макса Планка. Вполне может быть, что ОП неправильно определил местоположение в таком огромном коде. Нет ничего плохого в перекомпиляции.   -  person RussF    schedule 05.06.2015
comment
Каков тип временных значений? Если данные передаются процедуре netcdf nf_get_var_double через IO_GET_VAR_DOUBLE, это должна быть двойная точность. Если только 32 бита, то будет переполнение. Эти коды часто основаны на компиляции/связывании с автопродвижением реальных чисел на 64-битные. Возможно, это то, что сделал ваш коллега.   -  person RussF    schedule 05.06.2015
comment
@RussF точно, это модель echam, произведенная этим институтом!! Я много раз перекомпилировал его с разными настройками в коде, но у меня была одна и та же проблема. Однако эта проблема с переполнением 32-64 бит звучит знакомо, так как у меня были похожие проблемы при постобработке моих выходных данных. Вы предлагаете перекомпилировать код, используя -64-битную точность? Должен ли я внести это изменение в Makefile или в модули кода? Кстати, да, код огромен, но когда я использую временные значения grep, этот термин появляется только в нескольких модулях, связанных с этими входными данными netcdf.   -  person Fil X    schedule 06.06.2015
comment
хм, я только что проверил, значения времени удваиваются.   -  person Fil X    schedule 06.06.2015


Ответы (1)


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

Ошибка, о которой вы сообщаете, является ошибкой времени выполнения, а не той, которую компилятор может увидеть во время компиляции. Если вы не понимаете разницы между временем выполнения (т.е. когда код выполняется) и временем компиляции (т.е. когда компилятор превращает ваши исходники в исполняемый код), сделайте некоторые исследования. Кроме того, очевидно, что вы (или кто-то другой) поручили компилятору создать версию кода, которая проверяет, что доступ к элементам массива находится в пределах границ массива. Это очень важная функция безопасности при тестировании нового программного обеспечения, но она приводит к снижению производительности, когда выполняется так много кодов, которые после прохождения тестов компилируются без этой проверки.

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

Сообщение об ошибке довольно явное — в какой-то момент вашего кода он пытался получить доступ к элементу 141 массива, состоящего всего из 140 элементов. Мы не можем сказать вам, как это произошло, возможно, даже если бы мы видели весь ваш код. Такое часто случается, когда загружаются данные, не соответствующие ожиданиям программиста. Это также часто случается, когда программисты допускают ошибки на единицу при написании циклов. Мы могли бы заметить это, взглянув на весь ваш код, но у вас гораздо больше возможностей для этого, чем у нас.

Ты пишешь

но мой коллега смог запустить модель без проблем, что было для меня странно. Он скомпилировал модель с некоторыми другими настройками в Makefile, я не знаю, имеет ли это значение,

Ну да, это важно, это очень важно. Если вы пишете код, который обращается к элементу 141 массива из 140 элементов, Fortran, как и многие другие компилируемые языки, с радостью получит доступ к следующему месту в памяти после элемента 140. В общем, вы понятия не имеете, с какими данными вмешивается программа. Если вам повезет, следующая ячейка памяти окажется за пределами адресного пространства, выделенного операционной системой для программы, и операционная система немедленно остановит программу и сообщит об ошибке сегментации.

Если вам не повезло, программа продолжает беспечно читать и записывать элемент 141, что бы это ни было.

Я предполагаю, что ваш коллега не внедрил проверку границ массива для своей версии кода. Вам решать, скажите ли вы ему, что его код (весьма вероятно) сломан.

Итак, что вы делаете по этому поводу? Вы отлаживаете программу. Вы можете сделать это различными способами, самый простой из которых (на мой взгляд) — вставить несколько операторов write для вывода значений переменных в критических точках кода, чтобы проверить ваши предположения о том, какие значения они могут, могут или на самом деле бери. Более сложным, но стоящим первоначальных усилий с точки зрения решения проблем в будущем будет запуск кода под управлением отладчика. Для программ на Фортране на всех основных платформах доступно несколько хороших отладчиков.

person High Performance Mark    schedule 04.06.2015