Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/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_Gpu_Shared Memory_Gpgpu - Fatal编程技术网

cuda fortran中的共享内存未按预期工作

cuda fortran中的共享内存未按预期工作,cuda,gpu,shared-memory,gpgpu,Cuda,Gpu,Shared Memory,Gpgpu,我正在构建一个cuda fortran,出现了一个奇怪的行为。我真的不明白为什么我的代码会这样运行,我将非常感谢您的帮助 似乎从未分配值0,甚至循环也是如此 不受限制地执行 我试图将if条件放在循环之后,但也没有帮助。 谢谢你的帮助 real, shared :: s_d_aaa_adk(0:15,0:15) real, shared :: s_d_bbb_adk(0:15,0:15) real, shared :: s_d_ccc_adk(0:15,0:15)

我正在构建一个cuda fortran,出现了一个奇怪的行为。我真的不明白为什么我的代码会这样运行,我将非常感谢您的帮助

似乎从未分配值0,甚至循环也是如此 不受限制地执行

我试图将if条件放在循环之后,但也没有帮助。 谢谢你的帮助

    real, shared :: s_d_aaa_adk(0:15,0:15)
    real, shared :: s_d_bbb_adk(0:15,0:15)
    real, shared :: s_d_ccc_adk(0:15,0:15)

    d_k = (blockIdx%x-1)
    s_d_j = threadIdx%x-1
    s_d_l = threadIdx%y-1   

    if(d_k == kmax-1)then
        s_d_aaa_adk(s_d_j,s_d_l)  = 0 
        s_d_bbb_adk(s_d_j,s_d_l) = 0
        s_d_ccc_adk(s_d_j,s_d_l)  = 0       
    endif

    do d_k = 0, kmax-2              
        s_d_bbb_adk(s_d_j,s_d_l) = d_bbb(s_d_j,d_l,d_k+1)
        s_d_ccc_adk(s_d_j,s_d_l)  = d_ccc(d_j,s_d_l,d_k+1) 
        s_d_aaa_adk(s_d_j,s_d_l) = d_aaa(d_j,s_d_l,d_k+1)               
    end do  `
我将所有全局内存数组大小设置为(16,16,kmax), 网格为(128,1,1)、块(16,16,1)和
内核作为
testkernell()

启动,因为您在
d_k
上调节if语句,该语句来自块索引:

d_k = (blockIdx%x-1)
if(d_k == kmax-1)then
这意味着网格中128个块中只有一个块将实际执行if语句,将这些特定的共享内存值设置为零。大多数块不会执行if语句中的内容

如果
kmax
恰好大于128,则所有块都不会执行if语句

如果希望在每个threadblock中执行If语句,则需要在块索引以外的其他条件下执行它

我想就如何重新构造代码提出一个建议,但我不清楚在将数据加载到共享内存方面您想要实现什么。例如,您的do循环对我来说没有多大意义:

do d_k = 0, kmax-2              
    s_d_bbb_adk(s_d_j,s_d_l) = d_bbb(s_d_j,d_l,d_k+1)
    s_d_ccc_adk(s_d_j,s_d_l)  = d_ccc(d_j,s_d_l,d_k+1) 
    s_d_aaa_adk(s_d_j,s_d_l) = d_aaa(d_j,s_d_l,d_k+1)               
end do            ^     ^
                  |     |
         a given thread has specific values for these indices
您的
s_d_j
s_d_l
变量是线程索引。因此,给定的线程将看到这个do循环,它将迭代地执行循环,从各种全局内存数组(
d_bbb
d_ccc
,等等)将连续的值加载到每个共享内存数组中完全相同的位置

在我看来,您似乎并不真正理解线程执行是如何工作的。假设您是一个给定的线程,为
s_d_j
s_d_l
(和
d_k
,尽管重复使用该变量作为循环索引时会覆盖块索引,这对我来说也很奇怪),然后看看代码执行是否有意义

编辑:根据其他评论:

您已经声明了您的总体数据集大小(x,y,z)是(64,64,32)。 您已声明“我正在切片…数组通过z…我想将每个切片放在一个块中”

这对我来说意味着你应该每片发射一个区块。或者,您可能有一个算法,将多个块分配给单个切片。无论如何,我将假设您希望所有切片数据(64,64)都可用于指定给该切片的给定块。我现在假设你将发射32个区块。扩展到多个块在单个切片上工作的情况应该不难。我还将假设一个32x32线程块,而不是您指出的16x16。如果您想使用16x16,将其扩展为使用16x16应该不难

你可以这样做:

real, shared :: s_d_aaa_adk(0:63,0:63)
real, shared :: s_d_bbb_adk(0:63,0:63)
real, shared :: s_d_ccc_adk(0:63,0:63)

c above uses 48KB of shared mem, so assuming cc 2.0+ and cache config set accordingly

d_k = (blockIdx%x-1)
s_d_j = threadIdx%x-1
s_d_l = threadIdx%y-1   

c fill first quadrant
s_d_bbb_adk(s_d_j,s_d_l) = d_bbb(s_d_j,s_d_l,d_k+1)
s_d_ccc_adk(s_d_j,s_d_l) = d_ccc(s_d_j,s_d_l,d_k+1) 
s_d_aaa_adk(s_d_j,s_d_l) = d_aaa(s_d_j,s_d_l,d_k+1)
c fill second quadrant
s_d_bbb_adk(s_d_j+blockDim%x,s_d_l) = d_bbb(s_d_j+blockDim%x,s_d_l,d_k+1)
s_d_ccc_adk(s_d_j+blockDim%x,s_d_l) = d_ccc(s_d_j+blockDim%x,s_d_l,d_k+1) 
s_d_aaa_adk(s_d_j+blockDim%x,s_d_l) = d_aaa(s_d_j+blockDim%x,s_d_l,d_k+1)
c fill third quadrant
s_d_bbb_adk(s_d_j,s_d_l+blockDim%y) = d_bbb(s_d_j,s_d_l+blockDim%y,d_k+1)
s_d_ccc_adk(s_d_j,s_d_l+blockDim%y) = d_ccc(s_d_j,s_d_l+blockDim%y,d_k+1) 
s_d_aaa_adk(s_d_j,s_d_l+blockDim%y) = d_aaa(s_d_j,s_d_l+blockDim%y,d_k+1)
c fill fourth quadrant
s_d_bbb_adk(s_d_j+blockDim%x,s_d_l+blockDim%y) = d_bbb(s_d_j+blockDim%x,s_d_l+blockDim%y,d_k+1)
s_d_ccc_adk(s_d_j+blockDim%x,s_d_l+blockDim%y) = d_ccc(s_d_j+blockDim%x,s_d_l+blockDim%y,d_k+1) 
s_d_aaa_adk(s_d_j+blockDim%x,s_d_l+blockDim%y) = d_aaa(s_d_j+blockDim%x,s_d_l+blockDim%y,d_k+1)


c just guessing about what your intent was on filling with zeroes
c this just makes sure that one of the slices at the end gets zeroes
c instead of the values from the global arrays

if(d_k == kmax-1)then
c fill first quadrant
    s_d_bbb_adk(s_d_j,s_d_l) = 0
    s_d_ccc_adk(s_d_j,s_d_l) = 0
    s_d_aaa_adk(s_d_j,s_d_l) = 0
c fill second quadrant
    s_d_bbb_adk(s_d_j+blockDim%x,s_d_l) = 0
    s_d_ccc_adk(s_d_j+blockDim%x,s_d_l) = 0
    s_d_aaa_adk(s_d_j+blockDim%x,s_d_l) = 0
c fill third quadrant
    s_d_bbb_adk(s_d_j,s_d_l+blockDim%y) = 0
    s_d_ccc_adk(s_d_j,s_d_l+blockDim%y) = 0
    s_d_aaa_adk(s_d_j,s_d_l+blockDim%y) = 0
c fill fourth quadrant
    s_d_bbb_adk(s_d_j+blockDim%x,s_d_l+blockDim%y) = 0
    s_d_ccc_adk(s_d_j+blockDim%x,s_d_l+blockDim%y) = 0
    s_d_aaa_adk(s_d_j+blockDim%x,s_d_l+blockDim%y) = 0     
endif

kmax
的值是多少?我正在通过z将一个3d到2d阵列切片。kmax是z的最大值。我想把每个片放在一个块中,在这种情况下可能不需要使用do循环。三维数组在x,y,z中的大小是多少?大小是(64,64,32)。我发布的示例不是完整大小,因为我想先看看它在小数组中的行为。这就是我发布(16,16,4)的原因。所有3个阵列的大小都相同。谢谢你,罗伯特。我正试图在CUDA上以新手的身份工作。我明白我现在不应该循环其他blockId。我有一个3D数组(x,y,z),我想为每个z提取平面(x,y),并把这些值放在共享内存中。罗伯特,你真是太好了。感谢您花时间详细解释这一点。现在已经很清楚了。我将实现我的代码并让您知道。你是对的,我有一个算法,它将在每个片上显示许多线程块。最后一个目标是将其移植到多gpu环境。事实上,我突然想到,您可能无法使用所有48KB的共享内存,因为系统使用了其中的一小部分(通常是几个字节)用于管理。因此,我编写的代码仍然无法工作。你没有足够的共享内存来使一个片的所有数据都能对每个块可用,所以你必须考虑你的算法,如果你可以在共享内存中使用一个简化的集合,或者从全局内存中操作它的一部分。谢谢罗伯特。但是48KB是每个SM的,对吗?在这种情况下,多次使用内核应该有助于解决内存问题。我也在考虑将流与发送和处理重叠。是的,它是每个SM 48KB。使用流将数据副本与计算重叠是一个好主意。