Cuda & Fortran简单的例子

一、 简单小程序

module simpleOps_m
contains
 attributes(global)subroutine increment(a,b)
  implicit none
  integer,intent(inout)::a(:)
  integer,value::b
  integer::i
  i = threadIdx%x
  a(i)=a(i)+b
 end subroutine increment
end module simpleOps_m

program incrementTestGPU
  use cudafor
  use simpleOps_m
  implicit none
  integer ,parameter :: n =256
  integer :: a(n),b
  integer, device :: ad(n)

  a=1
  b=3
  ad=a
  call increment<<<1,n>>>(ad,b)
  a=ad
  if(any(a /=4)) then
    write(*,*) "Failed"
  else
    write(*,*)  "Passed"
  endif
end program incrementTestGPU

fortran是用module进行包装的。implicit none这句表示变量必须定义之后才可以使用,subroutine是用来包装子程序的标签,(global)这个相当于cuda的_global_。Fortran的参数申明是在里面的,不需要在increment(a,b)这个里面做申明。Increment是子程序名。Fortran默认是按地址传递,所以如果要使用按值传递的话,需要加上value这个形容词,就比如上面的integer,value::b一样。Program是程序的入口,就像main一样,incrementTestGPU这个是程序名称可以修改成其他,use cudafor这个是需要添加的因为我们会使用到cudaFortran。simpleOps_m这个模块我也也会使用到,我们会调用到里面的子程序。然后就定义各种变量,大家注意格式就好了。调用内核函数的使用,和cuda一样,只是多了一个call这个东西。
如果我们把上面的代码存在a.f90
编译命令:pgf90 a.f90 -Mcuda
-Mcuda这个参数是需要添加的,它是为了告诉编译器我要使用到cudaFortran了。


二、 调用另外一个文件的内核函数

假如我们把内核函数写在b.f90这个文件里面

module simpleOps_m
contains
 attributes(global)subroutine increment(a,b)
  implicit none
  integer,intent(inout)::a(:)
  integer,value::b
  integer::i
  i = threadIdx%x
  a(i)=a(i)+b
 end subroutine increment
end module simpleOps_m

我们把主函数写在a.f90这个文件里面

program incrementTestGPU
  use cudafor
  use simpleOps_m
  implicit none
  integer ,parameter :: n =256
  integer :: a(n),b
  integer, device :: ad(n)

  a=1
  b=3
  ad=a
  call increment<<<1,n>>>(ad,b)
  a=ad
  if(any(a /=4)) then
    write(*,*) "Failed"
  else
    write(*,*)  "Passed"
  endif
end program incrementTestGPU

这个时候我们就涉及到调用另外一个文件里的函数的问题,其实很简单。我们先把b.f90这个文件编译成.o的中间文件即可,只是注意需要加个参数
编译命令:pgf90 -Mcuda=rdc -c b.f90
这个时候就生成了b.o这个文件
pgf90 -Mcuda b.o a.f90
这个时候我们就可以看到可执行文件了。


你可能感兴趣的:(cuda,并行计算)