Cuda纹理缓存在每次内核启动时不刷新

时间:2020-11-10 12:48:49

标签: c++ cuda textures texture2d

我正在尝试在CUDA中使用纹理内存。我编写了一个简单的代码来使用2D纹理添加数字。有一个for循环,可多次重复内核。但是奇怪的是,似乎纹理缓存仅每两个内核启动就被刷新一次。

核心就是

_global__ void add(float *f, float *fn){
int y = threadIdx.x;
int x = blockIdx.x;

float a = tex2D(text,x,y);
if (x==1 && y==0){
    printf("The location is : %d %d %d\n", x,y,x+nx*y);
    printf("The first element read through texture is : %f\n", a );
    printf("The first element read through global is : %f\n", f[x+nx*y]);
    printf("Printing to :%p\n", f);
}
a+=a;

fn[x+nx*y] = a; }

纹理变量的全局定义为

texture<float,2> text;

一旦定义了变量并将其复制到设备1D数组cudamemcpy,纹理将使用绑定

cudaChannelFormatDesc desc = cudaCreateChannelDesc<float>();
gpuErrchk(cudaBindTexture2D(NULL, text, f, desc, nx, ny, sizeof(float)*nx));
checkerr();
text.addressMode[0] = cudaAddressModeWrap;
text.addressMode[1] = cudaAddressModeWrap;

主循环如下所示

or (int t=0; t<10; t++){
    cout<<"Iteration : "<<t<<endl;
        add<<<nx,ny>>>(f,fn);
    cudaDeviceSynchronize();
    checkerr();

    cudaMemcpy(h_f,fn,sizeof(float)*nx*ny,cudaMemcpyDeviceToHost);
//checkerr();
    cout<<"In iteration "<<t<<" the texture is pointing to "<<f<<endl;
    swap(f,fn);
for (int i=0; i<nx*ny; i++)
    cout<<h_f[i]<<' ';
cout<<endl;

}

此处,内核从f读取,并将输出保存到fn。然后,在内核完成后,交换功能仅交换指针。我得到的输出是

Iteration : 0
The location is : 1 0 1
The first element read through texture is : 1.000000
The first element read through global is : 1.000000
Printing to :0x500a20000
In iteration 0 the texture is pointing to 0x500a20000
Iteration : 1
The location is : 1 0 1
The first element read through texture is : 1.000000
The first element read through global is : 2.000000
Printing to :0x500a20200
In iteration 1 the texture is pointing to 0x500a20200
Iteration : 2
The location is : 1 0 1
The first element read through texture is : 2.000000
The first element read through global is : 2.000000
Printing to :0x500a20000
In iteration 2 the texture is pointing to 0x500a20000
Iteration : 3
The location is : 1 0 1
The first element read through texture is : 2.000000
The first element read through global is : 4.000000
Printing to :0x500a20200
In iteration 3 the texture is pointing to 0x500a20200

指针在交换时没有任何问题,并且通过全局内存进行的访问始终会给出正确的答案。但在我看来,纹理缓存未刷新,导致它获取了旧值。

有人遇到过这个问题吗?我很确定我做错了什么。任何帮助都将非常有帮助

1 个答案:

答案 0 :(得分:1)

这里的问题是,当绑定指针时,纹理一旦绑定就不会在两个指针之间交替。

由于纹理是通过值而不是通过引用绑定到f的,因此指针交换对纹理绑定到的对象没有影响。第一次运行内核时,对fn的更新对纹理没有影响。当您第二次运行内核时,尽管交换了指针,但纹理仍指向先前的f数组,该数组未被先前的内核调用修改。因此,在第二次内核迭代中,纹理值看起来是相同的,因为它是相同的。如果您希望每次迭代中的纹理都发生变化,那么您就有逻辑上的代码设计缺陷。

一个可能的“解决方案”是在每一步重新绑定纹理。

但是,我不会建议这种“修复”。从内核写入与纹理关联的绑定线性内存可能会导致未定义的行为。纹理只是具有插入缓存的存储区域。预期纹理存储器对于内核代码是只读的,因此缓存始终是一致的。如果您写入基础内存,则缓存可能不再一致。

对于希望从内核代码“写入纹理”的情况,建议的方法是使用表面。有CUDA sample codes证明了这一点。

此外,一般的建议是如this blog中所述,从使用绑定的纹理(或表面)引用切换到无绑定的纹理(或表面)对象。