在我的CFD求解器中,必须在每个节点上的整个域中应用几个大量计算,具体取决于索引i,j,k和l。该域为3-D,分辨率为IMAX + 1,JMAX + 1,KMAX + 1。
我的问题是重复实施这些非常广泛的块。
以下两种方法中的哪一种效率更高,处理负荷更少?
方法1
MODULE module_of_method_1
IMPLICIT NONE
PRIVATE
INTEGER, PARAMETER, PUBLIC :: IMIN = 0 , &
IMAX = 1024, &
JMIN = 0 , &
JMAX = 1024, &
KMIN = 0 , &
KMAX = 1024, &
SITE = 32
CONTAINS
SUBROUTINE sub_1 ()
! very extentise bLock 1
END SUBROUTINE
SUBROUTINE sub_2 ()
! very extentise bLock 2
END SUBROUTINE
SUBROUTINE sub_3 ()
! very extentise bLock 3
END SUBROUTINE
END MODULE
PROGRAM driver_of_method_1
USE module_of_method_1
IMPLICIT NONE
INTEGER :: I, J, K, L
DO k = KMIN, KMAX
DO j = JMIN, JMAX
DO i = IMIN, IMAX
DO l = 0, SITE
SELECT CASE (case_expression(i, j, k, l))
CASE (case_selector_1)
CALL sub_1 ()
CASE (case_selector_2)
CALL sub_2 ()
CASE DEFAULT
CALL sub_3 ()
END SELECT
END DO
END DO
END DO
END DO
END PROGRAM
方法2
MODULE module_of_method_2
IMPLICIT NONE
PRIVATE
INTEGER, PARAMETER :: IMIN = 0 , &
IMAX = 1024, &
JMIN = 0 , &
JMAX = 1024, &
KMIN = 0 , &
KMAX = 1024, &
SITE = 32
CONTAINS
SUBROUTINE only_one_subroutine ()
INTEGER :: I, J, K, L
DO k = KMIN, KMAX
DO j = JMIN, JMAX
DO i = IMIN, IMAX
DO l = 0, SITE
SELECT CASE (case_expression(i, j, k, l))
CASE (case_selector_1)
! very extentise bLock 1
CASE (case_selector_2)
! very extentise bLock 2
CASE DEFAULT
! very extentise bLock 3
END SELECT
END DO
END DO
END DO
END DO
END SUBROUTINE
END MODULE
PROGRAM program_of_method_2
USE module_of_method_2
IMPLICIT NONE
CALL only_one_subroutine ()
END PROGRAM
我更喜欢方法1,因为它是一种自上而下的设计,具有更简单的调试,开发和维护,但我担心这种方法的处理负荷。
答案 0 :(得分:1)
如果您的子例程sub_1
,sub_2
,...与驱动程序例程在同一个文件中,则编译器(没有特定选项)具有选择内联或不内联的所有信息功能。
如果你自己内联子程序,你将让编译器做出任何选择。在最好的情况下,它是进行内联的好选择,你会看到没有区别,因为编译器也会选择它。在最坏的情况下,您会看到速度变慢,因为编译器将选择不内联。
当然,我认为你没有编译得很糟糕的可执行文件(因为你的编译器很糟糕,或者因为它有-O0
等不适应的选项。
通常最好让编译器选择最佳策略,这可能取决于您的体系结构和代码。对于Xeon或Power CPU,选择可能不同。您可以做的最好的事情是通过选项和指令向编译器提供尽可能多的信息(手册页是一个好的开始)并让它完成它的工作。