gpt4 book ai didi

performance - 通过重构 if 语句/do 循环来避免重复代码

转载 作者:行者123 更新时间:2023-12-04 19:58:27 27 4
gpt4 key购买 nike

嗨,我正在尝试在网格中的许多不同空间点对我的函数施加特定条件。但是,我正在复制大量代码,而且效率越来越低。

我怎样才能通过简单地使用 do 循环来做我需要做的事情?我试图对我的函数施加的具体条件在所有不同的空间点上都是相同的,所以我认为有一种方法可以在一个循环中完成所有这些。或者如何将所有这些 If/else if 语句组合成一个语句?必须有比我正在做的更有效的方法。

我在下面提供了一个示例代码。

FUNCTION grad(psi)
IMPLICIT NONE
INTEGER :: i,j,kk,ll
INTEGER, PARAMETER :: nx = 24, ny = 24
COMPLEX,DIMENSION(3,3,-nx:nx, -ny:ny) :: psi, grad
REAL :: pi
REAL :: f0
INTEGER :: nxx, nyy

nxx = nx/2
nyy = ny/2

pi = 4*atan(1.0)
f0 = pi**2*1.3

DO i=-nx+1,nx-1 !spatial points
DO j=-ny+1,ny-1 !spatial points

IF ( i == 0 .AND. j == 0 .AND. i == j) THEN ! I have lots of statements like this

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == nxx .AND. j == nyy .AND. i == j) THEN ! I have lots of statements like this

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == -nxx .AND. j == -nyy .AND. i == j) THEN ! I have lots of statements like this

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == nxx .AND. j == -nyy) THEN ! I have lots of statements like this

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == -nxx .AND. j == nyy) THEN

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == nxx .AND. j == ny) THEN

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == -nxx .AND. j == ny) THEN

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == nx .AND. j == -nyy) THEN

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE IF ( i == nx .AND. j == nyy) THEN

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)

END DO

ELSE

DO kk=1,3

grad(kk,1,i,j) = psi(kk,1,i+1,j)

grad(kk,2,i,j) = psi(kk,2,i+1,j)

grad(kk,3,i,j) = psi(kk,3,i+1,j)

END DO

END IF

END DO
END DO

END FUNCTION grad

最佳答案

如果你正在寻找简洁,我会说你可以比你更简洁。您提供的整个函数可以像这样重写:

function grad(psi)
implicit none
integer, parameter :: nx = 24, ny = 24, nxx = nx / 2, nyy = ny / 2
real, parameter :: pi = 4 * atan(1.0), f0 = pi ** 2 * 1.3
complex, dimension(3,3,-nx:nx,-ny:ny) :: psi, grad

grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1)
grad(:,:,0,0) = psi(:,:,1,0)
grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]) = psi(:,:,[-nxx+1,nxx+1],[-nyy,nyy,ny]) - f0 * psi(:,:,[-nxx,nxx],[-nyy,nyy,ny])
!grad(:,:,nx,[-nyy,nyy]) = psi(:,:,nx+1,[-nyy,nyy]) - f0 * psi(:,:,nx,[-nyy,nyy])
end

正如@IanBush 所说,分配默认值然后修改特殊情况似乎是一个不错的方法。另外, array sections notation是 Fortran 语言独特而强大的功能之一,可用于在不影响清晰度的情况下增加表达力。

纯冒号表示该维度中的所有值,值之间的冒号表示该维度中该范围内的值。

所以,当我写 grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1)我的意思是:我正在从数组 psi 中分配值至 grad ;我包括来自第一个维度的所有值,但只包括最后两个维度的子集(我不包括每个维度中的第一个和最后一个);此外,它们直接映射,除了第三维,它映射到 psi 中等效位置的下一个。 .

当我写 grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]) ,我指定索引列表而不是第三和第四维度的范围。这将包括两个列表的总组合: -nxx,-nyy , -nxx,nyy , -nxx,ny , nxx,-nyy ...

这种符号的一个优点是,由于它更明显且更接近数学符号,因此更容易发现不一致之处。这就是最后一行被注释掉的原因:索引 nx+1 ,正如您在您编写的代码中的第 8 个和第 9 个条件中所具有的那样,将超出范围。不知道你提供的示例代码是不是官方的;如果是的话,你应该更正你的算法(好吧,因为你只是从第二个到倒数第二个索引循环,你实际上永远不会触及这些条件......)。

作为附加建议,您可以将自定义函数放在模块中,这样您就可以将所有这些参数声明传递给模块范围。此外,您可以考虑假定形状的数组参数。

关于performance - 通过重构 if 语句/do 循环来避免重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53289143/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com