如何将CUDA tex1DFetch与CUDateTextureObject_t一起使用?

如何将CUDA tex1DFetch与CUDateTextureObject_t一起使用?,cuda,textures,Cuda,Textures,当我注意到纹理引用被弃用时,我正在使用纹理引用,我尝试更新我的测试函数以使用tex1Dfetch的“新”无绑定纹理对象,但无法产生相同的结果 我目前正在探索使用纹理内存来加速我的aho corasick实现;我能够让tex1D处理纹理引用,但是,我注意到它们已被弃用,并决定使用纹理对象 当我试图以任何方式使用结果时,我得到了一些非常奇怪的内核行为;我可以做结果[tidx]=tidx;没有任何问题,但结果[tidx]=temp+1;仅返回temp not temp*3的值或任何其他涉及temp的数

当我注意到纹理引用被弃用时,我正在使用纹理引用,我尝试更新我的测试函数以使用tex1Dfetch的“新”无绑定纹理对象,但无法产生相同的结果

我目前正在探索使用纹理内存来加速我的aho corasick实现;我能够让tex1D处理纹理引用,但是,我注意到它们已被弃用,并决定使用纹理对象

当我试图以任何方式使用结果时,我得到了一些非常奇怪的内核行为;我可以做结果[tidx]=tidx;没有任何问题,但结果[tidx]=temp+1;仅返回temp not temp*3的值或任何其他涉及temp的数值测试

我看不出这种行为的逻辑原因,文档示例看起来非常相似,我看不出哪里出了问题

我已经读过CUDA tex1Dfetch错误的行为和新的CUDA纹理对象-在2D情况下获取错误的数据,但两者似乎都与我遇到的问题无关

以防万一,这会产生影响;我正在使用CUDA版本10.0,V10.0.130和Nvidia GTX 980ti

#include <iostream>

__global__ void test(cudaTextureObject_t tex ,int* results){
    int tidx = threadIdx.y * blockDim.x + threadIdx.x;
    unsigned temp = tex1Dfetch<unsigned>(tex, threadIdx.x);
    results[tidx] = temp * 3;
}

int main(){
    int *host_arr;
    const int host_arr_size = 8;

    // Create and populate host array
    std::cout << "Host:" << std::endl;
    cudaMallocHost(&host_arr, host_arr_size*sizeof(int));
    for (int i = 0; i < host_arr_size; ++i){
        host_arr[i] = i * 2;
        std::cout << host_arr[i] << std::endl;
    }

    // Create resource description
    struct cudaResourceDesc resDesc;
    resDesc.resType = cudaResourceTypeLinear;
    resDesc.res.linear.devPtr = &host_arr;
    resDesc.res.linear.sizeInBytes = host_arr_size*sizeof(unsigned);
    resDesc.res.linear.desc = cudaCreateChannelDesc<unsigned>();
    // Create texture description
    struct cudaTextureDesc texDesc;
    texDesc.readMode = cudaReadModeElementType;
    // Create texture
    cudaTextureObject_t tex;
    cudaCreateTextureObject(&tex, &resDesc, &texDesc, NULL);

    // Allocate results array
    int * result_arr;
    cudaMalloc(&result_arr, host_arr_size*sizeof(unsigned));

    // launch test kernel
    test<<<1, host_arr_size>>>(tex, result_arr);

    // fetch results
    std::cout << "Device:" << std::endl;
    cudaMemcpy(host_arr, result_arr, host_arr_size*sizeof(unsigned), cudaMemcpyDeviceToHost);
    // print results
    for (int i = 0; i < host_arr_size; ++i){
        std::cout << host_arr[i] << std::endl;
    }

    // Tidy Up
    cudaDestroyTextureObject(tex);
    cudaFreeHost(host_arr);
    cudaFree(result_arr);
}
实际结果:

Host:
0
2
4
6
8
10
12
14
Device:
0
2
4
6
8
10
12
14

有人知道到底出了什么问题吗?

CUDA API函数调用返回错误代码。您想检查这些错误代码。特别是当某处明显出了问题

您可以使用相同的数组来存储初始数组数据以及从设备接收结果。内核启动失败,出现非法地址错误,因为您没有有效的纹理对象。您没有有效的纹理对象,因为创建纹理对象失败。内核启动后的第一个API调用是cudaMemcpy,用于返回结果。由于内核启动期间出错,将失败,返回最新的错误而不是执行复制。因此,host_arr缓冲区的内容保持不变,您只需再次显示原始输入数据即可

创建纹理对象失败的原因在“重点”中解释:

如果cudaResourceDesc::resType设置为cudaResourceTypeLinear,则必须将cudaResourceDesc::res::linear::devPtr设置为与cudaDeviceProp::textureAlignment对齐的有效设备指针。[……]

纹理对象无法引用主体内存。代码中的问题在于:

resDesc.res.linear.devPtr = &host_arr;
您需要在decive内存中分配一个缓冲区,例如,使用cudaMalloc,将数据复制到那里,并创建一个引用该设备缓冲区的纹理对象

此外,您的texDesc没有正确初始化。在您的情况下,仅将其初始化为零就足够了:

struct cudaTextureDesc texDesc = {};

CUDA API函数调用返回错误代码。您想检查这些错误代码。特别是当某处明显出了问题

您可以使用相同的数组来存储初始数组数据以及从设备接收结果。内核启动失败,出现非法地址错误,因为您没有有效的纹理对象。您没有有效的纹理对象,因为创建纹理对象失败。内核启动后的第一个API调用是cudaMemcpy,用于返回结果。由于内核启动期间出错,将失败,返回最新的错误而不是执行复制。因此,host_arr缓冲区的内容保持不变,您只需再次显示原始输入数据即可

创建纹理对象失败的原因在“重点”中解释:

如果cudaResourceDesc::resType设置为cudaResourceTypeLinear,则必须将cudaResourceDesc::res::linear::devPtr设置为与cudaDeviceProp::textureAlignment对齐的有效设备指针。[……]

纹理对象无法引用主体内存。代码中的问题在于:

resDesc.res.linear.devPtr = &host_arr;
您需要在decive内存中分配一个缓冲区,例如,使用cudaMalloc,将数据复制到那里,并创建一个引用该设备缓冲区的纹理对象

此外,您的texDesc没有正确初始化。在您的情况下,仅将其初始化为零就足够了:

struct cudaTextureDesc texDesc = {};

我不敢相信我错过了,谢谢你的提示!我在CUDA Pro提示中看到了memset初始化:开普勒纹理对象提高了性能和灵活性示例,因此认为这是必要的。我不敢相信我错过了,谢谢提示!我在CUDA Pro提示中看到了memset初始化:开普勒纹理对象提高了性能和灵活性示例,因此认为这是必需的。