我正在尝试在 PGI 的 fortran 编译器中制作一个简单的程序。这个简单的程序将使用显卡使用“飞镖板”算法计算 pi。在与这个程序斗争了相当长一段时间之后,我终于让它在大多数情况下都能正常工作。但是,我目前坚持正确传回结果。我必须说,这是一个相当棘手的调试程序,因为我不能再将任何打印语句推入子程序。该程序当前返回全零。我不确定发生了什么,但我有两个想法。我不知道如何解决这两个问题:
- CUDA 内核没有以某种方式运行?
- 我没有正确转换值?
pi_parts = pi_parts_d
嗯,这就是我当前程序的状态。末尾带有的所有变量_d
都代表 CUDA 准备的设备内存,其中所有其他变量(CUDA 内核除外)都是典型的 Fortran CPU 准备变量。现在有一些我已经注释掉的打印语句,我已经从 CPU Fortran 领域尝试过。这些命令是为了检查我是否真的正确地生成了随机数。至于 CUDA 方法,我目前已将计算注释掉并替换z
为静态等于,1
只是为了看看发生了什么。
module calcPi
contains
attributes(global) subroutine pi_darts(x, y, results, N)
use cudafor
implicit none
integer :: id
integer, value :: N
real, dimension(N) :: x, y, results
real :: z
id = (blockIdx%x-1)*blockDim%x + threadIdx%x
if (id .lt. N) then
! SQRT NOT NEEDED, SQRT(1) === 1
! Anything above and below 1 would stay the same even with the applied
! sqrt function. Therefore using the sqrt function wastes GPU time.
z = 1.0
!z = x(id)*x(id)+y(id)*y(id)
!if (z .lt. 1.0) then
! z = 1.0
!else
! z = 0.0
!endif
results(id) = z
endif
end subroutine pi_darts
end module calcPi
program final_project
use calcPi
use cudafor
implicit none
integer, parameter :: N = 400
integer :: i
real, dimension(N) :: x, y, pi_parts
real, dimension(N), device :: x_d, y_d, pi_parts_d
type(dim3) :: grid, tBlock
! Initialize the random number generaters seed
call random_seed()
! Make sure we initialize the parts with 0
pi_parts = 0
! Prepare the random numbers (These cannot be generated from inside the
! cuda kernel)
call random_number(x)
call random_number(y)
!write(*,*) x, y
! Convert the random numbers into graphics card memory land!
x_d = x
y_d = y
pi_parts_d = pi_parts
! For the cuda kernel
tBlock = dim3(256,1,1)
grid = dim3((N/tBlock%x)+1,1,1)
! Start the cuda kernel
call pi_darts<<<grid, tblock>>>(x_d, y_d, pi_parts_d, N)
! Transform the results into CPU Memory
pi_parts = pi_parts_d
write(*,*) pi_parts
write(*,*) 'PI: ', 4.0*sum(pi_parts)/N
end program final_project
编辑代码:
更改了各个行以反映以下提到的修复:Robert Crovella
。当前状态:通过cuda-memcheck
显示发现错误:Program hit error 8 on CUDA API call to cudaLaunch
在我的机器上。
如果有什么方法可以用来测试这个程序,请告诉我。我正在投掷飞镖,看看它们在我目前使用 CUDA 的调试方式中落在哪里。不是最理想的,但在我找到另一种方法之前必须这样做。
愿 Fortran 诸神在这黑暗的时刻怜悯我的灵魂。