{>> 44}}重复调用多个子程序或简单地调用一个扩展子程序

时间:2016-09-17 18:07:34

标签: time fortran procedure subroutine

在我的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,因为它是一种自上而下的设计,具有更简单的调试,开发和维护,但我担心这种方法的处理负荷。

1 个答案:

答案 0 :(得分:1)

如果您的子例程sub_1sub_2,...与驱动程序例程在同一个文件中,则编译器(没有特定选项)具有选择内联或不内联的所有信息功能。 如果你自己内联子程序,你将让编译器做出任何选择。在最好的情况下,它是进行内联的好选择,你会看到没有区别,因为编译器也会选择它。在最坏的情况下,您会看到速度变慢,因为编译器将选择不内联。

当然,我认为你没有编译得很糟糕的可执行文件(因为你的编译器很糟糕,或者因为它有-O0等不适应的选项。

通常最好让编译器选择最佳策略,这可能取决于您的体系结构和代码。对于Xeon或Power CPU,选择可能不同。您可以做的最好的事情是通过选项和指令向编译器提供尽可能多的信息(手册页是一个好的开始)并让它完成它的工作。