【发布时间】:2018-02-03 18:59:49
【问题描述】:
问题是编写允许使用相同名称的变量的代码,这些变量可以根据条件引用数组或函数。
更详细地说:我有 real*8 函数,它需要 4 个整数索引。这种函数的计算是相当昂贵的。返回此函数的值被使用了数百万次。最明显的解决方案 - 计算一次并使用 4 维数组而不是函数。它可以节省大量时间。
但是当任务的大小增加时,不可能将这样的数组存储在内存中。所以要独立于硬件,需要关闭存储在内存中,改为使用函数。
我想到的唯一一种解决方案是将abstract interface 与“虚拟函数”一起使用,该函数除了按四个索引返回数组的值之外什么都不做。
首先,需要定义抽象接口:
abstract interface
real(kind=rglu) function integral(a,b,c,d)
use glob, only: iglu,rglu
integer(kind=iglu), intent(in) :: a,b,c,d
end function integral
end interface
procedure (integral), pointer :: R=>null()
接下来,编写函数:
real(kind=rglu) function stored_int(a,b,c,d) result(ret)
implicit none
integer(kind=iglu), intent(in) :: a,b,c,d
ret=hR(a,b,c,d); return
end function stored_int
然后我们会以如下方式使用它:
if (storeIntegrals) then
do i = 1,N
do j = 1,N
do a = 1,N
do b = 1,N
hR(i,j,a,b)=my_integral(i,j,a,b)
enddo
enddo
enddo
enddo
R=>stored_int
else
R=>my_integral
endif
函数my_integral是我们需要用数组替换。
不幸的是,这种方法表现出非常糟糕的性能。
编译ifort -O3 -fpp -openmp
在四个内核上,它给出的结果比相同的代码差两倍,但有一个数组(没有虚函数)。
还有其他变体可以解决这个问题吗?
【问题讨论】:
-
顺便说一句,将
return放入 Fortran 中的每个函数是没有意义的。 -
我以前放
return,如果不影响性能我会继续写。
标签: fortran intel-fortran