解释3D阵列的内存,宽度,高度,内存深度

时间:2017-01-09 00:14:38

标签: python cuda pycuda

我在python中使用CUDA和3D纹理(使用pycuda)。有一个名为Memcpy3D的函数,它与Memcpy2D具有相同的成员加上一些附加功能。在其中,它会要求您描述width_in_bytessrc_pitchsrc_heightheightcopy_depth等内容。这就是我正在努力(在3D中)及其与C或F风格索引的相关性。例如,如果我只是在下面的工作示例中将排序从F更改为C,它就会停止工作 - 我不知道为什么。

  1. 首先,我理解音调是在threadIdx.x(或x方向或列)中移动一个索引所需的内存中的字节数。因此对于C形状(3,2,4)的float32数组,要在x中移动一个值,我希望在内存中移动4个值(as the indexing goes down the z axis first?)。因此,我的音调将是4 * 32位。
  2. 我理解height是行数。 (在这个例子中,3)
  3. 我理解width是cols的数量。 (在这个例子中,2)
  4. 我理解depth是z切片的数量。 (在这个例子中,4)
  5. 我理解width_in_bytes是其后面z个元素的x 包含行的宽度,即行切片,(0,:,:)。这将是在y方向上横向一个元素所花费的内存中的地址数。
  6. 因此,当我在下面的代码中将排序从F更改为C,并调整代码以相应地更改高度/宽度值时,它仍然不起作用。它只是呈现出逻辑失败,这让我觉得我不能正确理解音高,宽度,高度和深度的概念。

    请教育我。

    下面是一个完整的工作脚本,它将数组作为纹理复制到GPU并将内容复制回来。

    import pycuda.driver as drv
    import pycuda.gpuarray as gpuarray
    import pycuda.autoinit
    from pycuda.compiler import SourceModule
    import numpy as np
    
    w = 2
    h = 3
    d = 4
    shape = (w, h, d)
    
    a = np.arange(24).reshape(*shape,order='F').astype('float32')
    print(a.shape,a.strides)
    print(a)
    
    
    descr = drv.ArrayDescriptor3D()
    descr.width = w
    descr.height = h
    descr.depth = d
    descr.format = drv.dtype_to_array_format(a.dtype)
    descr.num_channels = 1
    descr.flags = 0
    
    ary = drv.Array(descr)
    
    copy = drv.Memcpy3D()
    copy.set_src_host(a)
    copy.set_dst_array(ary)
    copy.width_in_bytes = copy.src_pitch = a.strides[1]
    copy.src_height = copy.height = h
    copy.depth = d
    
    copy()
    
    mod = SourceModule("""
        texture<float, 3, cudaReadModeElementType> mtx_tex;
    
        __global__ void copy_texture(float *dest)
        {
          int x = threadIdx.x;
          int y = threadIdx.y;
          int z = threadIdx.z;
          int dx = blockDim.x;
          int dy = blockDim.y;
          int i = (z*dy + y)*dx + x;
          dest[i] = tex3D(mtx_tex, x, y, z);
        }
    """)
    
    copy_texture = mod.get_function("copy_texture")
    mtx_tex = mod.get_texref("mtx_tex")
    
    mtx_tex.set_array(ary)
    
    dest = np.zeros(shape, dtype=np.float32, order="F")
    copy_texture(drv.Out(dest), block=shape, texrefs=[mtx_tex])
    
    print(dest)
    

1 个答案:

答案 0 :(得分:1)

我不确定我是否完全理解您的代码中的问题,但我会尝试澄清。

在CUDA中,widthx)指的是变化最快的维度,heighty)是中间维度,depthz)是变化最慢的维度。 pitch是指沿着y维度在值之间步进所需的跨度(以字节为单位)。

在Numpy中,定义为np.empty(shape=(3,2,4), dtype=np.float32, order="C")的数组有strides=(32, 16, 4),对应width=4height=2depth=3pitch=16。< / p>

在Numpy中使用"F"排序意味着维度的顺序在内存中相反。

如果我进行以下更改,您的代码似乎有效:

#shape = (w, h, d)
shape = (d, h, w)

#a = np.arange(24).reshape(*shape,order='F').astype('float32')
a = np.arange(24).reshape(*shape,order='C').astype('float32')
...
#dest = np.zeros(shape, dtype=np.float32, order="F")
dest = np.zeros(shape, dtype=np.float32, order="C")
#copy_texture(drv.Out(dest), block=shape, texrefs=[mtx_tex])
copy_texture(drv.Out(dest), block=(w,h,d), texrefs=[mtx_tex])