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

Fortran 测试类型(种类)的内部表示形式,fortran,Fortran,当使用不同的内部表示(种类)测试计算机性能时,代码或多或少保持不变,但测试参数的定义除外(种类=1;种类=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 no

当使用不同的内部表示(种类)测试计算机性能时,代码或多或少保持不变,但测试参数的定义除外(种类=1;种类=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
问题来了。除调用模块部分外,子例程完全相同。我曾尝试在子例程中使用contain语句,但如果调用内部子例程,则该语句无效。我还尝试使用带有属性的子例程,但我的编译器报告了一个错误:

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


有人知道如何优化代码的好方法吗。当测试10种不同内部表示形式的不同变体时,此代码变得太大。

为什么不将相关代码导出到一个文件
print\u hug.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
然后您可以
将其包含到不同的模块中
打印

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书中的示例启发):

然后,您的主应用程序看起来就像:

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

子例程驻留在include文件中,不需要调整为all
kind
s。当然,您可以直接访问所有模块和/或使用
=>
操作符“重命名”子例程

穷人模板通常使用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预处理器可以用于更强大的功能

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