2D纹理的间距对齐

时间:2012-09-23 08:49:26

标签: cuda textures

2D纹理是图像处理应用程序中CUDA的一个有用功能。要将音高线性存储器绑定到2D纹理,必须对齐存储器。 cudaMallocPitch是对齐内存分配的一个很好的选择。在我的设备上,cudaMallocPitch返回的音高是512的倍数,即内存是512字节对齐的。

设备的实际对齐要求由cudaDeviceProp::texturePitchAlignment确定,我的设备上为32字节。

我的问题是:

如果2D纹理的实际对齐要求是32字节,那么为什么cudaMallocPitch会返回512字节对齐的内存?

不浪费记忆吗?例如,如果我创建一个大小为513 x 100的8位图像,它将占用1024 x 100字节。

我在以下系统中遇到此行为:

1:华硕G53JW + Windows 8 x64 + GeForce GTX 460M + CUDA 5 +酷睿i7 740QM + 4GB内存

2:戴尔Inspiron N5110 + Windows 7 x64 + GeForce GT525M + CUDA 4.2 + Corei7 2630QM + 6GB内存

2 个答案:

答案 0 :(得分:4)

这是一个略微推测的答案,但请记住,有两个对齐属性,分配的音高必须满足纹理,一个用于纹理指针,一个用于纹理行。我怀疑cudaMallocPitch尊重前者,由cudaDeviceProp::textureAlignment定义。例如:

#include <cstdio>

int main(void)
{
    const int ncases = 12;
    const size_t widths[ncases] = { 5, 10, 20, 50, 70, 90, 100,
        200, 500, 700, 900, 1000 };
    const size_t height = 10;

    float *vals[ncases];
    size_t pitches[ncases];

    struct cudaDeviceProp p;
    cudaGetDeviceProperties(&p, 0);
    fprintf(stdout, "Texture alignment = %zd bytes\n",
            p.textureAlignment);
    cudaSetDevice(0);
    cudaFree(0); // establish context

    for(int i=0; i<ncases; i++) {
        cudaMallocPitch((void **)&vals[i], &pitches[i], 
            widths[i], height);
        fprintf(stdout, "width = %zd <=> pitch = %zd \n",
                widths[i], pitches[i]);
    }

    return 0;
}

在GT320M上给出以下内容:

Texture alignment = 256 bytes
width = 5 <=> pitch = 256 
width = 10 <=> pitch = 256 
width = 20 <=> pitch = 256 
width = 50 <=> pitch = 256 
width = 70 <=> pitch = 256 
width = 90 <=> pitch = 256 
width = 100 <=> pitch = 256 
width = 200 <=> pitch = 256 
width = 500 <=> pitch = 512 
width = 700 <=> pitch = 768 
width = 900 <=> pitch = 1024 
width = 1000 <=> pitch = 1024 

我猜测cudaDeviceProp::texturePitchAlignment适用于CUDA数组。

答案 1 :(得分:3)

在对内存分配进行了一些实验后,我终于找到了一个可以节省内存的工作解决方案。如果我强行对齐由cudaMalloc分配的内存,cudaBindTexture2D可以正常工作。

cudaError_t alignedMalloc2D(void** ptr, int width, int height, int* pitch, int alignment = 32)
{       
   if((width% alignment) != 0)
      width+= (alignment - (width % alignment));

   (*pitch) = width;

   return cudaMalloc(ptr,width* height);
}

此函数分配的内存为32字节对齐,这是cudaBindTexture2D的要求。我的内存使用量现在减少了16倍,所有使用2D纹理的CUDA函数也正常工作。

这是一个小实用程序功能,用于获取当前所选的CUDA设备音调对齐要求。

int getCurrentDeviceTexturePitchAlignment()
{
   cudaDeviceProp prop;
   int currentDevice = 0;

   cudaGetDevice(&currentDevice);

   cudaGetDeviceProperties(&prop,currentDevice);

   return prop.texturePitchAlignment;
}