我在运行时收到以下警告:
...
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
被分配了每个维度所期望的最大值,因此大多数时候只有一个子集通过该调用。
据我所知,它在准确性方面并不是真正的问题,但可能会减慢程序速度,因此很多写入RAM的工作都已完成。那么它减慢了我的计算量(stripe
可能有一个大约stripe(100,300,3)
的维度,并且可能会在以后的某个时间变大)?我怎样才能避免这种额外的阵列?
答案 0 :(得分:7)
我认为您收到此警告是因为子例程正在传递非连续的数组部分,并且编译器已决定子例程应该获得包含必要值的连续临时数组。我希望子程序代码是用数组编写的,并且隐含地假设,就像我们在Fortran中编程时一样,它是连续的。
如果我正确阅读了你的代码,编译器就会理解这个陈述
stripe(j,1:s(j),1)
表示(原样)
stripe(j,1,1)
stripe(j,2,1)
stripe(j,3,1)
...
因为我希望你知道,Fortran数组存储的第一个索引值变化最快,你的数组部分会通过内存。
您可以使用编译器选项noarg_temp_created
来禁止警告。请注意,这只会抑制警告(这可能会节省程序运行时间的微笑),它不会影响编译器的作用,仍然会创建临时数组。
您可以编写代码来创建包含要传递给子例程的部分的临时数组。我没有看到这样做的好处;我希望编译器发出的代码优于你为这种直接操作编写的代码。
或者你可以在开始调用子程序之前对原始数组进行一次整形/置换,并为其提供正确的形状和排列,以便切割成连续的块。然后在所有通话结束时取消/取消。
回答关于当前代码和任何替代配方的相对性能的问题的唯一结论性方法是对它们进行编码并拿出秒表。