纹理内存

与常量内存类似,纹理内存同样缓存在芯片上,因此在某些情况中,它能减少对内存的请求并提供更高效的内存带宽。纹理缓存是专门为那些在内存访问模式中存在大量空间局部性(Spatial Locality)的图形应用程序而设计的。在某个计算应用程序中,这意味着一个线程读取的位置可能与邻近线程读取的位置“非常接近”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//一维纹理
texture<float> texIn;
texture<float> texOut;
cudaBindTexture(NULL, texIn, data.inSrc, size);
cudaBindTexture(NULL, texOut, data.outSrc, size);
//不同与其它内存用方括号访问内存,纹理内存用内置函数访问
float f1 = tex1Dfetch(texIn, pos1);
float f2 = tex1Dfetch(texOut, pos2);
//核函数中无需将纹理内存作为参数传入
cudaUnbindTexture(texIn);
cudaUnbindTexture(texOut);
//二维纹理
texture<float, 2> texIn;
texture<float, 2> texOut;
//使用tex2D时,不需要担心发生溢出的问题。如果参数x,y小于0或某个值大于宽度,则会返回位于0或者宽度位置的值。(注意,在有些应用程序中需要这种行为,而有些则需要避免该行为的发生)
float t = tex2D(texIn, x, y);
//与一维纹理相同的是,都需要预先分配存储空间。但不同的是,二维纹理要求提供一个cudaChannelFormatDesc,对通道格式描述符的声明。
cudaChannelFormatDesc desc = cudaCreateChannelDesc<float>();
//这里使用默认的参数,仅仅指定浮点描述符。
cudaBindTexture2D(NULL, texIn, data.Insrc, desc, DIM, DIM, size);
//同样是使用cudaUnbindTexture(texIn)来解除绑定。

注意,无论是使用2维纹理还是1维纹理,性能基本相同,只是在有些情况下,2维纹理的代码会更简单直观一些。