测试类型的内部表示(种类)

问题描述 投票:1回答:2

当使用不同的内部表示(种类)测试计算机性能时,代码保持或多或少相同,除了测试参数的定义(kind = 1; kind = 2)。我试图建立不同的模块。

    module var_1
    implicit none
    real(8), allocatable :: x(:,:),xi(:,:),xt(:,:)
    integer(kind=1), allocatable :: z(:,:)
    end module var_1

    module var_2
    implicit none
    real(8), allocatable :: x(:,:),xi(:,:),xt(:,:)
    integer(kind=2), allocatable :: z(:,:)
    end module var_2

还有一个全局模块定义了不会改变的参数:

    module global
    integer :: i,j,n,p,nProcessors,s,v,w,infodpotrf,infodpotri,mkl_get_max_threads
    integer, dimension(3) :: ni = [100, 1000, 10000], pi = [100, 1000, 10000]
    integer, dimension(5) :: nProcessorsi = [1, 2, 4, 6, 12]
    real(8):: u,myone= 1.d0,t11,t22
    real:: t2,t1
    include 'omp_lib.h'
    end module global

比在程序部分,我们调用后面定义的子程序:

   program test
   call matrix_multi_inv_1
   call matrix_multi_inv_2
   end program test

子程序:

    subroutine matrix_multi_inv_1
    use global 
    use var_1

    open (unit=100,file="results.txt",status="unknown")

    do s=1,5
      nProcessors = nProcessorsi(s)
      CALL OMP_SET_NUM_THREADS(nProcessors)
      do v=1,3
        n=ni(v)
        do w=1,3
          p=pi(w)
          allocate(x(n,n),z(n,p),xi(n,n),xt(n,n))
            do i=1,n
               do j=1,p
                  call random_number(u)
                  z(i,j)=real(floor(u*3),8)
               enddo
            enddo

       1000 format(3(a20),2(i10),2(f15.3),i10)

            t11=omp_get_wtime()
            call cpu_time(t1)
            x=matmul(z,transpose(z))
            t22=omp_get_wtime()
            call cpu_time(t2)

            write(100,1000) 'x_integer_kind_1', 'G_real_8', 'matmul', n, p, t22-t11,t2-t1, mkl_get_max_threads() 

          deallocate(x,z,xi,xt)
        enddo
      enddo
    enddo
    end subroutine matrix_multi_inv_1

    subroutine matrix_multi_inv_2
    use global 
    use var_1

    open (unit=100,file="results.txt",status="unknown")

    do s=1,5
      nProcessors = nProcessorsi(s)
      CALL OMP_SET_NUM_THREADS(nProcessors)
      do v=1,3
        n=ni(v)
        do w=1,3
          p=pi(w)
          allocate(x(n,n),z(n,p),xi(n,n),xt(n,n))
            do i=1,n
               do j=1,p
                  call random_number(u)
                  z(i,j)=real(floor(u*3),8)
               enddo
            enddo

       1000 format(3(a20),2(i10),2(f15.3),i10)

            t11=omp_get_wtime()
            call cpu_time(t1)
            x=matmul(z,transpose(z))
            t22=omp_get_wtime()
            call cpu_time(t2)

            write(100,1000) 'x_integer_kind_2', 'G_real_8', 'matmul', n, p, t22-t11,t2-t1, mkl_get_max_threads() 

          deallocate(x,z,xi,xt)
        enddo
      enddo
    enddo
    end subroutine matrix_multi_inv_2

这就是问题所在。除了调用模块部分之外,子例程完全相同。我试图在子例程中使用包含语句,但如果调用内部子例程,则这不起作用。我也尝试使用带有属性的子程序,但我的编译器报告错误:

类型参数必须是编译时常量。

有谁知道如何优化代码的好方法。当测试10个不同的内部表示的不同变化时,这个代码变得太大了。

fortran
2个回答
0
投票

类似的问题通常由使用include`的穷人模板解决。您将公共部分移动到另一个文件,然后就可以了

subroutine matrix_multi_inv_1
    use var_1
    include "common.f90"
end subroutine

subroutine matrix_multi_inv_2
    use var_2
    include "common.f90"
end subroutine

C预处理器可用于更多功率。


0
投票

为什么不将相关代码导入文件print_huge.inc.F90以包含在模块中:

! No module ... required
interface print_huge
  module procedure print_huge
end interface

contains

subroutine print_huge(a)
  real(kind=mykind),intent(in) :: a

  print *, huge(a)
end subroutine

! no end module

然后你可以将include这个变成不同的模块print_huge_N

module print_huge_4
  integer,parameter :: mykind = 4

  include 'print_huge.inc.F90'
end module

module print_huge_8
  integer,parameter :: mykind = 8

  include 'print_huge.inc.F90'
end module

module print_huge_16
  integer,parameter :: mykind = 16

  include 'print_huge.inc.F90'
end module

注意,每个模块都有自己定义的mykind

为方便起见,您可以使用定义的接口将模块捆绑成一个“超级模块”(灵感来自Arjen Markus一书中的示例):

module print_huge_all
  use print_huge_4
  use print_huge_8
  use print_huge_16
end module

然后您的主要应用程序将看起来像:

program huge_program
  use print_huge_all
  real(kind=4)  :: a1
  real(kind=8)  :: a2
  real(kind=16) :: a3

  call print_huge(a1)
  call print_huge(a2)
  call print_huge(a3)
end program

使用以下输出:

./a.out 
   3.40282347E+38
   1.7976931348623157E+308
   1.18973149535723176508575932662800702E+4932

子例程驻留在包含文件中,不需要调整到所有kinds。当然,您可以直接访问所有模块和/或使用=>运算符“重命名”子例程。

© www.soinside.com 2019 - 2024. All rights reserved.