tex1Dfetch意外返回0

时间:2015-07-20 03:36:57

标签: c++ cuda textures gpu

我不相信这与此处报道的问题相同:

Bound CUDA texture reads zero

CUDA 1D texture fetch always return 0

在我的CUDA应用程序中,我注意到tex1Dfetch没有返回预期值,超过缓冲区中的某个索引。在应用程序中的初步观察是索引0处的值可以正确读取,但在12705625处,读取的值为0.我做了一个小的测试程序来研究这个,如下所示。结果对我来说有点莫名其妙。我试图探究哪些索引不再正确读取值。但是随着值arraySize的改变," firstBadIndex"也是如此。即使使用arraySize = 2,第二个值也会被错误地读取!随着arraySize变大,firstBadIndex变大。绑定到float,float2或float4的数组时会发生这种情况。如果从设备缓冲区中读取数据(切换FetchTextureData中的注释行),那么一切都很好。这是在Tesla c2075上使用CUDA 6.5。 感谢您提供的任何见解或建议。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>

#define FLOATTYPE float4
texture<FLOATTYPE,cudaTextureType1D,cudaReadModeElementType> texture1D;

const unsigned int arraySize = 1000;
FLOATTYPE* host;
FLOATTYPE* device;
FLOATTYPE* dTemp;
FLOATTYPE hTemp[1];

__global__ void FetchTextureData(FLOATTYPE* data,FLOATTYPE* arr,int idx)
{
    data[0] = tex1Dfetch(texture1D, idx);
    //data[0] = arr[idx];
}

bool GetTextureValues(int idx){

    FetchTextureData<<<1,1>>>(dTemp,device,idx);

    // copy to the host
    cudaError_t err = cudaMemcpy(hTemp,dTemp,sizeof(FLOATTYPE),cudaMemcpyDeviceToHost);
    if (err != cudaSuccess) {
        throw "cudaMemcpy failed!";
    }

    if (cudaDeviceSynchronize() != cudaSuccess) {
        throw "cudaDeviceSynchronize failed!";
    }

    return hTemp[0].x == 1.0f;
}

int main()
{

    try{

        host = new FLOATTYPE[arraySize];
        cudaError_t err = cudaMalloc((void**)&device,sizeof(FLOATTYPE) * arraySize);
        cudaError_t err1 = cudaMalloc((void**)&dTemp,sizeof(FLOATTYPE));
        if (err != cudaSuccess || err1 != cudaSuccess) {
            throw "cudaMalloc failed!";
        }

        // make some host data
        for(unsigned int i=0; i<arraySize; i++){
            FLOATTYPE data = {1.0f, 0.0f, 0.0f, 0.0f};
            host[i] = data;
        }

        // and copy it to the device
        err = cudaMemcpy(device,host,sizeof(FLOATTYPE) * arraySize,cudaMemcpyHostToDevice);
        if (err != cudaSuccess){
            throw "cudaMemcpy failed!";
        }

        // set up the textures
        cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<FLOATTYPE>();
        texture1D.addressMode[0] = cudaAddressModeClamp;
        texture1D.filterMode = cudaFilterModePoint;
        texture1D.normalized = false;
        cudaBindTexture(NULL, texture1D, device, channelDesc, arraySize);

        // do a texture fetch and find where the fetches stop working
        int lastGoodValue = -1, firstBadValue = -1;
        float4 badValue = {-1.0f,0.0f,0.0f,0.0f};

        for(unsigned int i=0; i<arraySize; i++){

            if(i % 100000 == 0) printf("%d\n",i);
            bool isGood = GetTextureValues(i);

            if(firstBadValue == -1 && !isGood)
                firstBadValue = i;

            if(isGood)
                lastGoodValue = i;
            else
                badValue = hTemp[0];
        }

        printf("lastGoodValue %d, firstBadValue %d\n",lastGoodValue,firstBadValue);
        printf("Bad value is (%.2f)\n",badValue.x);

    }catch(const char* err){
        printf("\nCaught an error : %s\n",err);
    }
    return 0;
}

1 个答案:

答案 0 :(得分:3)

问题在于纹理设置。这样:

cudaBindTexture(NULL, texture1D, device, channelDesc, arraySize);

应该是:

    cudaBindTexture(NULL, texture1D, device, channelDesc, 
                                   arraySize * sizeof(FLOATTYPE));

根据documentation,size参数是以字节为单位的内存区域的大小,而不是元素的数量。我原以为使用钳位寻址模式,代码仍然可以按预期工作。使用边框模式,您应该获得零值,看起来它会触发您的错误值检测。我实际上没有运行你的代码,所以也许有一个微妙的我在某处丢失。对于这样一个简单的repro案例,你的代码结构相当复杂,难以理解(至少在我正在阅读的手机屏幕上)。

编辑在我开始写这篇文章和完成之间添加,@ njuffa在评论中指出同样的错误