【问题标题】:Cuda Create 3d texture and cudaArray(3d) from device memoryCuda 从设备内存创建 3d 纹理和 cudaArray(3d)
【发布时间】:2014-09-18 19:38:09
【问题描述】:

我正在尝试从设备阵列的一部分创建纹理 3d。

为此,我的步骤如下:

  1. malloc 设备阵列
  2. 写入设备数组
  3. 创建 CudaArray (3D)
  4. 将纹理绑定到 CudaArray

我这样做的方式不会产生编译器错误,但是当我运行 cuda-memcheck 时,当我尝试从纹理中获取数据时它失败了。

无效的全局读取大小为 8 .. 地址 0x10dfaf3a0 超出范围

这就是我猜测我声明纹理数组错误的原因。 这是我访问纹理的方式:

tex3D(NoiseTextures[i],x,y,z)

我执行上述步骤的方式:

1.Malloc 设备阵列

cudaMalloc((void **)&d_Noise, sqrSizeNoise*nNoise*sizeof(float));

2.写入设备数组

curandCreateGenerator(&gen,CURAND_RNG_PSEUDO_DEFAULT);
curandSetPseudoRandomGeneratorSeed(gen,Seed);
curandGenerateUniform(gen, d_Noise, sqrSizeNoise*nNoise);
curandDestroyGenerator(gen);

3+4.创建 Cuda Array 并将其绑定到纹理(我猜是这里的错误)

cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();//cudaCreateChannelDesc(32, 0, 0, 0, cudaChannelFormatKindFloat);
cudaArray *d_cuArr;
cudaMalloc3DArray(&d_cuArr, &channelDesc, make_cudaExtent(SizeNoise,SizeNoise,SizeNoise), 0);
cudaMemcpy3DParms copyParams = {0};

//Loop for every separated Noise Texture (nNoise = 4)
for(int i = 0; i < nNoise; i++){

    //initialize the textures
    NoiseTextures[i] = texture<float, 3, cudaReadModeElementType>(1,cudaFilterModeLinear,cudaAddressModeWrap,channelDesc);

    //Array creation
    //+(sqrSizeNoise*i) is to separate the created Noise Array into smaller parts with the size of SizeNoise^3
    copyParams.srcPtr   = make_cudaPitchedPtr(d_Noise+(sqrSizeNoise*i), SizeNoise*sizeof(float), SizeNoise, SizeNoise);
    copyParams.dstArray = d_cuArr;
    copyParams.extent   = make_cudaExtent(SizeNoise,SizeNoise,SizeNoise);
    copyParams.kind     = cudaMemcpyDeviceToDevice;
    checkCudaErrors(cudaMemcpy3D(&copyParams));
    //Array creation End

    //new Bind
    // set texture parameters
    NoiseTextures[i].normalized = true;                      // access with normalized texture coordinates
    NoiseTextures[i].filterMode = cudaFilterModeLinear;      // linear interpolation
    NoiseTextures[i].addressMode[0] = cudaAddressModeWrap;   // wrap texture coordinates
    NoiseTextures[i].addressMode[1] = cudaAddressModeWrap;
    NoiseTextures[i].addressMode[2] = cudaAddressModeWrap;

    // bind array to 3D texture
    checkCudaErrors(cudaBindTextureToArray(NoiseTextures[i], d_cuArr, channelDesc));
    //end Bind
}
cudaFreeArray(d_cuArr);

我已将此代码 sn-p 粘贴到 Pastebin,以便使用颜色等更容易查看。 http://pastebin.com/SM3dYd38

我希望我清楚地描述了我的问题。如果不是请评论!

你能帮我解决这个问题吗? 感谢阅读,

赛瑞

编辑: 这是一个完整的代码,您可以在自己的机器上试用:

#include <helper_cuda.h>  
#include <helper_functions.h>
#include <helper_cuda_gl.h>
#include <texture_types.h>
#include <cuda_runtime.h>
#include <curand.h>

static texture<float, 3, cudaReadModeElementType> NoiseTextures[4];//texture Array
float *d_NoiseTest;//Device Array with random floats
int SizeNoiseTest = 32;
int sqrSizeNoiseTest = 32768;

void CreateTexture();

__global__ void AccesTexture(texture<float, 3, cudaReadModeElementType>* NoiseTextures)
{
        int test = tex3D(NoiseTextures[0],threadIdx.x,threadIdx.y,threadIdx.z);//by using this the error occurs
}

int
main(int argc, char **argv)
{
        CreateTexture();
}
void CreateTexture()
{
        //curand Random Generator (needs compiler link -lcurand)
        curandGenerator_t gen;
        cudaMalloc((void **)&d_NoiseTest, sqrSizeNoiseTest*4*sizeof(float));//Allocation of device Array
        curandCreateGenerator(&gen,CURAND_RNG_PSEUDO_DEFAULT);
        curandSetPseudoRandomGeneratorSeed(gen,1234ULL);
        curandGenerateUniform(gen, d_NoiseTest, sqrSizeNoiseTest*4);//writing data to d_NoiseTest
        curandDestroyGenerator(gen);

        //cudaArray Descriptor
        cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
        //cuda Array
        cudaArray *d_cuArr;
        cudaMalloc3DArray(&d_cuArr, &channelDesc, make_cudaExtent(SizeNoiseTest*sizeof(float),SizeNoiseTest,SizeNoiseTest), 0);
        cudaMemcpy3DParms copyParams = {0};

        //Loop for every separated Noise Texture (4 = 4)
        for(int i = 0; i < 4; i++){

                //initialize the textures
                NoiseTextures[i] = texture<float, 3, cudaReadModeElementType>(1,cudaFilterModeLinear,cudaAddressModeWrap,channelDesc);

                //Array creation
                //+(sqrSizeNoise*i) is to separate the created Noise Array into smaller parts with the size of SizeNoise^3
                copyParams.srcPtr   = make_cudaPitchedPtr(d_NoiseTest+(sqrSizeNoiseTest*i), SizeNoiseTest*sizeof(float), SizeNoiseTest, SizeNoiseTest);
                copyParams.dstArray = d_cuArr;
                copyParams.extent   = make_cudaExtent(SizeNoiseTest*sizeof(float),SizeNoiseTest,SizeNoiseTest);
                copyParams.kind     = cudaMemcpyDeviceToDevice;
                checkCudaErrors(cudaMemcpy3D(&copyParams));
                //Array creation End

                //new Bind
                // set texture parameters
                NoiseTextures[i].normalized = true;                      // access with normalized texture coordinates
                NoiseTextures[i].filterMode = cudaFilterModeLinear;      // linear interpolation
                NoiseTextures[i].addressMode[0] = cudaAddressModeWrap;   // wrap texture coordinates
                NoiseTextures[i].addressMode[1] = cudaAddressModeWrap;
                NoiseTextures[i].addressMode[2] = cudaAddressModeWrap;

                // bind array to 3D texture
                checkCudaErrors(cudaBindTextureToArray(NoiseTextures[i], d_cuArr, channelDesc));
                //end Bind
        }
        cudaFreeArray(d_cuArr);

        AccesTexture<<<1,dim3(4,4,4)>>>(NoiseTextures);
}

您需要链接 -lcurand。并包括 CUDA-6.0/samples/common/inc

我现在在这段代码中遇到了另一个错误

code=11(cudaErrorInvalidValue) "cudaMemcpy3D(&copyParams)"

即使它与我的原始代码完全相同。 - 我开始完全糊涂了。 谢谢你的帮助

【问题讨论】:

  • 1.提供一个简短的完整代码,有人可以复制、粘贴、编译和运行以查看错误。所以expects this。 2. 为什么要使用纹理数组?是否可以为每个子纹理使用带有偏移到该纹理的单个纹理?或者,你看过分层纹理吗? 3. 你打算使用什么 GPU?我问是因为纹理 objects 数组(cc3.0 和更高版本)可能可行,但存在问题/限制。
  • make_cudaExtent() 的第一个参数是以字节为单位的宽度,所以据我所知应该是make_cudaExtent(SizeNoise*sizeof(float),SizeNoise,SizeNoise);
  • 感谢您处理我的问题! Robert Crovella:我创建了一个简短的完整代码 sn-p,因此您可以尝试一下。 FindError.cu : pastebin.com/viQYFGA7 我还编辑了原始帖子。 2.也许可以使用大纹理并偏移值,但我认为创建多个纹理会更容易,因为我想定期多次映射纹理。我认为 adressModeWrap 将是做到这一点的好方法。分层纹理不能是 3d 的,对吗?我的目标是 cc3.0,所以纹理对象可能是可能的。 Kamil Czerski:我试过了,但错误仍然出现。
  • 您最好先让您的 3D 纹理代码为 single 普通(非数组)纹理工作。 dim3(32,32,32) 不是任何当前 CUDA GPU 的有效线程块配置。无论前面的代码如何,您都不可能运行该内核。而且我们不会将纹理引用作为参数传递给内核。它是一个静态实体。你只是使用它。如果您先学习基本纹理,这可能是最好的。
  • @KamilCzerski 如果 cudaArray 参与cudaMemcpy3D 操作,则用于 3D 复制参数的范围不是以字节为单位,而是以元素为单位。参考documentation

标签: c++ c arrays cuda textures


【解决方案1】:

这是一个工作示例,展示了如何创建纹理对象数组,大致遵循您提供的代码路径。通过与我放置here 的纹理参考代码进行比较,您可以看到,从第一个纹理对象(即第一个内核调用)读取的第一组纹理与从纹理参考读取的一组数值相同示例(您可能需要调整两个示例代码的网格大小以匹配)。

使用纹理对象需要 3.0 或更高的计算能力。

示例:

$ cat t507.cu
#include <helper_cuda.h>
#include <curand.h>
#define NUM_TEX 4

const int SizeNoiseTest = 32;
const int cubeSizeNoiseTest = SizeNoiseTest*SizeNoiseTest*SizeNoiseTest;
static cudaTextureObject_t texNoise[NUM_TEX];

__global__ void AccesTexture(cudaTextureObject_t my_tex)
{
        float test = tex3D<float>(my_tex,(float)threadIdx.x,(float)threadIdx.y,(float)threadIdx.z);//by using this the error occurs
        printf("thread: %d,%d,%d, value: %f\n", threadIdx.x, threadIdx.y, threadIdx.z, test);
}

void CreateTexture()
{

    float *d_NoiseTest;//Device Array with random floats
    cudaMalloc((void **)&d_NoiseTest, cubeSizeNoiseTest*sizeof(float));//Allocation of device Array
    for (int i = 0; i < NUM_TEX; i++){
        //curand Random Generator (needs compiler link -lcurand)
        curandGenerator_t gen;
        curandCreateGenerator(&gen,CURAND_RNG_PSEUDO_DEFAULT);
        curandSetPseudoRandomGeneratorSeed(gen,1235ULL+i);
        curandGenerateUniform(gen, d_NoiseTest, cubeSizeNoiseTest);//writing data to d_NoiseTest
        curandDestroyGenerator(gen);

        //cudaArray Descriptor
        cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
        //cuda Array
        cudaArray *d_cuArr;
        checkCudaErrors(cudaMalloc3DArray(&d_cuArr, &channelDesc, make_cudaExtent(SizeNoiseTest*sizeof(float),SizeNoiseTest,SizeNoiseTest), 0));
        cudaMemcpy3DParms copyParams = {0};


        //Array creation
        copyParams.srcPtr   = make_cudaPitchedPtr(d_NoiseTest, SizeNoiseTest*sizeof(float), SizeNoiseTest, SizeNoiseTest);
        copyParams.dstArray = d_cuArr;
        copyParams.extent   = make_cudaExtent(SizeNoiseTest,SizeNoiseTest,SizeNoiseTest);
        copyParams.kind     = cudaMemcpyDeviceToDevice;
        checkCudaErrors(cudaMemcpy3D(&copyParams));
        //Array creation End

        cudaResourceDesc    texRes;
        memset(&texRes, 0, sizeof(cudaResourceDesc));
        texRes.resType = cudaResourceTypeArray;
        texRes.res.array.array  = d_cuArr;
        cudaTextureDesc     texDescr;
        memset(&texDescr, 0, sizeof(cudaTextureDesc));
        texDescr.normalizedCoords = false;
        texDescr.filterMode = cudaFilterModeLinear;
        texDescr.addressMode[0] = cudaAddressModeClamp;   // clamp
        texDescr.addressMode[1] = cudaAddressModeClamp;
        texDescr.addressMode[2] = cudaAddressModeClamp;
        texDescr.readMode = cudaReadModeElementType;
        checkCudaErrors(cudaCreateTextureObject(&texNoise[i], &texRes, &texDescr, NULL));}
}

int main(int argc, char **argv)
{
        CreateTexture();
        AccesTexture<<<1,dim3(2,2,2)>>>(texNoise[0]);
        AccesTexture<<<1,dim3(2,2,2)>>>(texNoise[1]);
        AccesTexture<<<1,dim3(2,2,2)>>>(texNoise[2]);
        checkCudaErrors(cudaPeekAtLastError());
        checkCudaErrors(cudaDeviceSynchronize());
        return 0;
}

编译:

$ nvcc -arch=sm_30 -I/shared/apps/cuda/CUDA-v6.0.37/samples/common/inc -lcurand -o t507 t507.cu

输出:

$ cuda-memcheck ./t507
========= CUDA-MEMCHECK
thread: 0,0,0, value: 0.310691
thread: 1,0,0, value: 0.627906
thread: 0,1,0, value: 0.638900
thread: 1,1,0, value: 0.665186
thread: 0,0,1, value: 0.167465
thread: 1,0,1, value: 0.565227
thread: 0,1,1, value: 0.397606
thread: 1,1,1, value: 0.503013
thread: 0,0,0, value: 0.809163
thread: 1,0,0, value: 0.795669
thread: 0,1,0, value: 0.808565
thread: 1,1,0, value: 0.847564
thread: 0,0,1, value: 0.853998
thread: 1,0,1, value: 0.688446
thread: 0,1,1, value: 0.733255
thread: 1,1,1, value: 0.649379
thread: 0,0,0, value: 0.040824
thread: 1,0,0, value: 0.087417
thread: 0,1,0, value: 0.301392
thread: 1,1,0, value: 0.298669
thread: 0,0,1, value: 0.161962
thread: 1,0,1, value: 0.316443
thread: 0,1,1, value: 0.452077
thread: 1,1,1, value: 0.477722
========= ERROR SUMMARY: 0 errors

在这种情况下,我使用同一个内核,多次调用,从各个纹理对象中读取。应该可以将多个对象传递给同一个内核,但是不建议从多个纹理读取单个 warp,如果可以在您的代码中避免这种情况。实际问题存在于四级,我不想进入。如果您可以安排您的代码,以便在任何给定的循环中从同一个纹理对象读取扭曲,那将是最好的。

请注意,为简单起见,此CreateTexture() 函数会在循环处理期间覆盖先前分配的设备指针,例如d_cuArr。这不是非法的或功能性问题,但它增加了内存泄漏的可能性。

如果这是一个问题,我假设您可以修改代码以处理这些的释放。这段代码的目的是演示让事情正常工作的方法。

【讨论】:

    【解决方案2】:

    在 cudaMalloc3DArray 中,应该是这样 make_cudaExtent(SizeNoiseTest,SizeNoiseTest,SizeNoiseTest) 不是 make_cudaExtent(SizeNoiseTest*sizeof(float),SizeNoiseTest,SizeNoiseTest)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-04
      • 2012-11-04
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多