Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cuda 用Fortran&;库达_Cuda_Fortran_Pgi - Fatal编程技术网

Cuda 用Fortran&;库达

Cuda 用Fortran&;库达,cuda,fortran,pgi,Cuda,Fortran,Pgi,我试图在PGI的fortran编译器中制作一个简单的程序。这个简单的程序将使用图形卡,使用“镖靶”算法计算pi。在与这个程序斗争了很长一段时间之后,现在我终于让它在很大程度上正常工作了。然而,我目前仍然无法正确地传递结果。我必须说,这是一个相当棘手的程序调试,因为我不能再推任何打印语句到子程序。此程序当前返回所有零。我不确定到底发生了什么,但我有两个想法。我不知道如何解决这两个问题: CUDA内核没有运行吗 我没有正确地转换值pi_零件=pi_零件 这就是我目前项目的状态。CUDA准备好的设备内

我试图在PGI的fortran编译器中制作一个简单的程序。这个简单的程序将使用图形卡,使用“镖靶”算法计算pi。在与这个程序斗争了很长一段时间之后,现在我终于让它在很大程度上正常工作了。然而,我目前仍然无法正确地传递结果。我必须说,这是一个相当棘手的程序调试,因为我不能再推任何打印语句到子程序。此程序当前返回所有零。我不确定到底发生了什么,但我有两个想法。我不知道如何解决这两个问题:

  • CUDA内核没有运行吗
  • 我没有正确地转换值<代码>pi_零件=pi_零件
  • 这就是我目前项目的状态。CUDA准备好的设备内存的端部支架上带有
    \u d
    的所有变量,其中所有其他变量(CUDA内核除外)都是典型的Fortran CPU准备变量。现在有一些我已经注释掉的打印语句,我已经在CPU Fortran land上试用过了。这些命令是为了检查我是否真的正确生成了随机数。至于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
    
    模块calcPi
    包含
    属性(全局)子例程pi_省道(x,y,结果,N)
    使用cudafor
    隐式无
    整数::id
    整数,值::N
    实数,维数(N)::x,y,结果
    real::z
    id=(块IDX%x-1)*块DIM%x+线程IDX%x
    如果(id.lt.N)那么
    ! 不需要SQRT,SQRT(1)==1
    ! 任何高于或低于1的值都将保持不变,即使应用了
    ! sqrt函数。因此,使用sqrt函数会浪费GPU时间。
    z=1.0
    !z=x(id)*x(id)+y(id)*y(id)
    !如果(z.lt.1.0),则
    !   z=1.0
    !其他的
    !   z=0.0
    !恩迪夫
    结果(id)=z
    恩迪夫
    结束子例程pi_省道
    端模块calcPi
    计划最终项目
    使用calcPi
    使用cudafor
    隐式无
    整数,参数::N=400
    整数::i
    实数,尺寸(N):x、y、pi\U零件
    实数,维数(N),设备::x\u d,y\u d,pi\u parts\u d
    类型(dim3):网格,tBlock
    ! 初始化随机数生成器种子
    调用随机_seed()
    ! 确保我们使用0初始化部件
    pi_部分=0
    ! 准备随机数(这些随机数不能从内部生成)
    !cuda内核)
    随机呼叫号码(x)
    呼叫随机号码(y)
    !写(*,*)x,y
    ! 将随机数转换为图形卡存储空间!
    x_d=x
    y_d=y
    pi_零件d=pi_零件
    ! 对于cuda内核
    tBlock=dim3(256,1,1)
    网格=dim3((N/t块%x)+1,1,1)
    ! 启动cuda内核
    调用pi_省道(x_d,y_d,pi_d,N)
    ! 将结果转换为CPU内存
    圆周率=圆周率
    编写(*,*)pi_零件
    写入(*,*)“PI:”,4.0*和(PI_部分)/N
    最终项目
    
    编辑到代码: 更改了不同的行以反映所提到的修复:
    Robert Crovella
    。当前状态:cuda memcheck捕获的错误显示:
    在我的机器上调用cuda API时程序命中错误8

    如果有任何方法我可以用来测试这个程序,请让我知道。我正在投掷飞镖,看看它们落在哪里,以适应我目前使用CUDA进行调试的风格。这不是最理想的,但在我找到另一种方法之前,它将不得不这样做


    在这个黑暗的时刻,愿福特兰神怜悯我的灵魂。

    当我编译并运行你的程序时,我得到了一个错误。这是由于您要传递给内核的最后一个参数(
    N\u d
    ):

    当我对您发布的代码进行更改时,我会得到实际的打印输出(而不是seg故障),这是一个由1和0组成的数组(256个1,后跟144个0,总共
    N
    =400个值),然后是计算出的PI值(在本例中正好是2.56)(4*256/400),因为您已经使内核基本上是一个虚拟内核)

    这一行代码也可能不是您想要的:

    grid = dim3(N/tBlock%x,1,1)
    
    N
    =400和
    tBlock%x
    =256(来自前面的代码行)时,计算结果为1(即
    grid
    最终位于
    (1,1,1)
    ,相当于一个螺纹块)。但是您确实希望启动2个ThreadBlock,以便覆盖整个数据集范围(
    N
    =400个元素)。有很多方法可以解决这个问题,但为了简单起见,我们总是在计算中加1:

    grid = dim3((N/tBlock%x)+1,1,1)
    
    在这种情况下,当我们启动的网格(总线程数)大于我们的数据集大小(在本例中为512个线程,但只有400个数据元素)时,通常会在内核的开头附近进行线程检查(在本例中,在初始化
    id
    之后),以防止越界访问,像这样:

    if (id .lt. N) then
    
    (在内核代码的最末端有一个对应的
    endif
    )这样,只有对应于实际有效数据的线程才允许执行任何工作

    通过上述更改,您的代码应该基本上是功能性的,并且您应该能够将内核代码还原为正确的语句,并开始获得PI的估计值


    请注意,您可以检查CUDA API中的错误返回代码,也可以使用
    CUDA memcheck
    运行代码,了解内核是否正在进行越界访问。但是,其中的Niether将有助于解决这个特殊的seg故障。

    您是否有机会在GPU的帮助下查看这个用于π的蒙特卡罗计算的Fortran示例:非常感谢您回复我的问题
    grid = dim3((N/tBlock%x)+1,1,1)
    
    if (id .lt. N) then