2013-08-13 1 views
4

я получаю следующее предупреждение во время выполнения:forrtl: предупреждение (402): форт: (1)

... 
forrtl: warning (402): fort: (1): In call to I/O Write routine, an array temporary was created for argument #2 

forrtl: warning (402): fort: (1): In call to I/O Write routine, an array temporary was created for argument #3 

forrtl: warning (402): fort: (1): In call to GERADHEIT_LINIAL, an array temporary was created for argument #2 

forrtl: warning (402): fort: (1): In call to GERADHEIT_LINIAL, an array temporary was created for argument #3 
... 

для каждого вызова заявления подпрограммы/записи.

Вызов подпрограммы:

integer :: l,kreise 
character(*)::setname 
real(8),diemnsion(:,:,:),allocatable::stripe 
integer,dimension(:)s(j) 

...code and allocation of arrays... 
do j=n(1) 
    call geradheit_linial (s(j),stripe(j,1:s(j),1), 
&      stripe(j,1:s(j),2),setname) 
end do 

... 

subroutine geradheit_linial (ndaten,x,r,setname) 
    implicit none 
    integer,intent(in) :: ndaten 
    real(8),dimension(ndaten),intent(in) :: x,r 
    character(*),intent(in) :: setname 

и утверждение записи:

write(91,*)'Gerade: ',gerade(maxloc(reslt(1:i)),minsumloc,1), 
&    gerade(maxloc(reslt(1:i)),minsumloc,2) 

Массив stripe выделяется с максимальным значением, ожидаемым для каждого измерения, так что большую часть времени лишь подмножество передается по вызову.

Насколько я понимаю, это не проблема с точки зрения точности, но может замедлить работу программы, поэтому большая часть записи в ОЗУ выполняется. Итак, сколько это замедляет мои вычисления (stripe может иметь размер около stripe(100,300,3) и может стать больше когда-нибудь позже)? И как я могу избежать таких дополнительных массивов ?.

+0

Я замечаю, что когда я использую дефисный размер, например. real (8), dimension (:), intent (in) :: x, r, я не вижу этого предупреждения .. – Charlie

ответ

6

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

Если я прочитал ваш код правильно компилятор понимает это заявление

stripe(j,1:s(j),1) 

означать (как это было)

stripe(j,1,1) 
stripe(j,2,1) 
stripe(j,3,1) 
... 

Поскольку, как я ожидаю, что вы знаете, Fortran массивы хранятся с первым значением индекса, которое изменяется быстрее всего, ваш массив проходит через память.

Вы можете подавить предупреждение с помощью опции компилятора noarg_temp_created. Обратите внимание, что это только подавляет предупреждение (которое может спасти smidgeon времени выполнения программы, я полагаю), это не влияет на то, что делает компилятор, временные массивы все равно будут созданы.

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

Или вы можете изменить или перенести свой первоначальный массив один раз, прежде чем приступать к вызову подпрограммы и придать ей правильную форму и расположение для нарезки в смежные блоки. А затем unpermute/unreshape в конце всех вызовов.

Единственный убедительный способ ответить на ваш вопрос об относительной производительности вашего текущего кода и любых альтернативных формулировок - это закодировать их и вывести свой секундомер.

+1

Возможно, это неявно в вашем ответе, но еще два момента ... Если массив манекена аргумент в процедуре считается формой, тогда, как правило, компилятор может генерировать код, который принимает «регулярные» шаговые, несмежные массивы, как я думаю, здесь происходит.Отчет о записи, вероятно, (на основе доступного кода), потому что MAXLOC без DIM возвращает результат массива - следовательно, индекс является векторным индексом, который может привести к временному; добавьте спецификатор DIM = 1, и индекс будет скалярным. – IanH

+0

@IanH: да, это правильно, эти точки были подкреплены моим ответом, спасибо за то, что они были явными :-) –

+0

Привет, я обновил, как подпрограмма передает свои аргументы. Я знаю, что печать предупреждения не сильно влияет на скорость, но я не закрою ее. Я могу изменить макет массива, возможно, когда-нибудь позже, но на данный момент он кажется достаточно хорошим. (и спасибо за «smidgeon времени выполнения программы», мне нравится его звук ^^). –

Смежные вопросы