我正在使用cuda fortran,我在一个简单的内核中一直在努力解决这个问题而我找不到解决方案。 是不是可以使用存储在数组中的整数值作为另一个数组的索引?
这是一个简单的例子(编辑后也包括主程序):
program test
use cudafor
integer:: ncell, i
integer, allocatable:: values(:)
integer, allocatable, device :: values_d(:)
ncell = 10
allocate(values(ncell), values_d(ncell))
do i=1,ncell
values(i) = i
enddo
values_d = values
call multipleindices_kernel<<< ncell/1024+1,1024 >>> (values_d,
+ ncell)
values = values_d
write (*,*) values
end program test
!////////////////////////////////////////////////////
attributes(global) subroutine multipleindices_kernel(valu, ncell)
use cudafor
implicit none
integer, value:: ncell ! ncell = 10
integer :: valu(ncell)
integer :: tempind(10)
integer:: i
tempind(1)=10
tempind(2)=3
tempind(3)=5
tempind(4)=7
tempind(5)=9
tempind(6)=2
tempind(7)=4
tempind(8)=6
tempind(9)=8
tempind(10)=1
i = (blockidx%x - 1 ) * blockdim%x + threadidx%x
if (i .LE. ncell) then
valu(tempind(i))= 1
endif
end subroutine
据我所知,如果tempind数组中有重复的值,则不同的线程可能会访问相同的内存位置进行读取或写入,但事实并非如此。 即使这样,也会出现错误“0:copyout Memcpy(host = 0x303610,dev = 0x3e20000,size = 40)FAILED:77(遇到非法内存访问)。
有没有人知道是否可以使用来自cuda中另一个数组的索引?
经过一些额外的测试后,我注意到问题不是在运行内核本身时发生,而是在将数据传输回CPU时(如果我删除“values = values_d”则不会显示错误)。此外,如果我用值(i)替换内核值(tempind(i))它工作正常,但我想让索引来自一个数组,因为这个测试的目的是进行CFD代码的并行化索引存储的位置。
答案 0 :(得分:1)
问题似乎是生成的可执行文件没有正确地将变量ncell
传递给内核。通过cuda-memcheck
运行应用程序表明,1-10之外的线程正在通过分支语句,并且在内核中添加print语句以打印ncell
也会给出奇怪的答案。
以前要求所有attributes(global)
子例程都必须驻留在模块中。在最近的CUDA Fortran版本中,这个要求似乎已经放宽了(我在编程指南中找不到对它的引用)。我相信模块外部的代码会导致错误。通过在模块中放置multipleindices_kernel
并在test
中使用该模块,我可以毫无错误地获得正确的答案。代码如下:
module testmod
contains
attributes(global) subroutine multipleindices_kernel(valu, ncell)
use cudafor
implicit none
integer, value:: ncell ! ncell = 10
integer :: valu(ncell)
integer :: tempind(10)
integer:: i
tempind(1)=10
tempind(2)=3
tempind(3)=5
tempind(4)=7
tempind(5)=9
tempind(6)=2
tempind(7)=4
tempind(8)=6
tempind(9)=8
tempind(10)=1
i = (blockidx%x - 1 ) * blockdim%x + threadidx%x
if (i .LE. ncell) then
valu(tempind(i))= 1
endif
end subroutine
end module testmod
program test
use cudafor
use testmod
integer:: ncell, i
integer, allocatable:: values(:)
integer, allocatable, device :: values_d(:)
ncell = 10
allocate(values(ncell), values_d(ncell))
do i=1,ncell
values(i) = i
enddo
values_d = values
call multipleindices_kernel<<< ncell/1024+1,1024 >>> (values_d, ncell)
values = values_d
write (*,*) values
end program test
!////////////////////////////////////////////////////