Fortran 测试类型(种类)的内部表示形式
当使用不同的内部表示(种类)测试计算机性能时,代码或多或少保持不变,但测试参数的定义除外(种类=1;种类=2)。我尝试构建不同的模块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
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文件中,不需要调整为allkind
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