CUDA

您所在的位置:网站首页 cuda例程 CUDA

CUDA

2024-04-29 06:41| 来源: 网络整理| 查看: 265

struct   textureReference{ int normalized; //是否归一化 true or false enum cudaTextureFilterMode    filterMode;    //滤波模式:cudaFilterModepoint和cudaFilterModeLinear enum cudaTextureAddressMode    addressMode[3];    //寻址模式:cudaAddressModeClump和cudaAddressModeWarp struct cudaChannelFormatDesc    channelDesc; }

例如:

2、纹理缓存的作用

1)纹理内存中的数据可以被重复利用,当需要的数据存在于纹理缓存中,就不用再去显存读取了

2)纹理拾取可以读取纹理坐标附近的几个象元,提高局部性的访问效率,实现滤波模式。换言之,对于图像滤波具有很好的性能。

3、一维纹理存储器的使用方法

1)在host端声明线性内存空间

分配线性内存空间的方法常见有cudaMalloc(), 由cudaMallocPitch()或者cudaMalloc3D()分配的线性空间是经过填充对齐的线性内存。

2)声明纹理参考系

texture texRef; //Type指定数据类型,特别注意:不支持3元组 //Dim指定纹理参考系的维度,默认为1 //ReadMode可以是cudaReadModelNormalizedFloat或cudaReadModelElementType(默认)

注意:type仅限于基本整型、单精度浮点类型和CUDA运行时提供的1元组、2元组和四元祖。

texture texRef;这样就声明了一个一维整数的纹理。

3)绑定数据到纹理

通过cudaBindTexture()函数将纹理参考连接到内存。将1维线性内存绑定到1维纹理。

cudaError_t cudaBindTexture(    size_t *offset, const struct textureReference *texref, const void *devPtr,const struct cudaChannelFormatDesc * desc,size_t  size = UINT_MAX )  例如:cudaBindTexture(0, texRef, d_data);

4)设备端的纹理拾取

在kernel中对纹理存储器进行访问,要通过tex1Dfetch()函数,通过纹理参考和给出的坐标位置就可以取得数据了。

type tex1Dfetch(texture texRef, int x);

通过以上四步,我们就可以在程序中利用纹理内存进行数据处理了。例子如下:

#include "cuda_runtime.h" #include "device_launch_parameters.h" #include #define N 256 //声明纹理参考系 texture texRef; //CPU串行向量复制 void copyCPU(int* source, int* target, int size) { for (int i = 0; i < size; i++) { target[i] = source[i]; } } //GPU使用全局内存实现向量复制 __global__ void kernel(int* source, int* target, int size) { int index = threadIdx.x + blockDim.x * blockIdx.x; if (index (d_data, d_Result, size); //拷贝数据回主机端 cudaMemcpy(target, d_Result, Size, cudaMemcpyDeviceToHost); cudaFree(d_data); cudaFree(d_Result); } //GPU使用纹理内存实现向量复制 __global__ void kernelTexture(int* target, int size) { int index = threadIdx.x + blockDim.x * blockIdx.x; if (index (d_Result, N); cudaMemcpy(target, d_Result, Size, cudaMemcpyDeviceToHost); //解除纹理绑定 cudaUnbindTexture(texRef); cudaFree(d_data); cudaFree(d_Result); } int main() { int *source, *target; source = (int *)malloc(sizeof(int) * N); target = (int *)malloc(sizeof(int) * N); for (int i = 0; i < N; i++) { source[i] = i + 1; target[i] = 0; } cudaEvent_t t1, t2; cudaEventCreate(&t1); cudaEventCreate(&t2); cudaEventRecord(t1, 0); int number = 2; switch (number) { case 0: copyCPU(source, target, N); break; case 1: copyGPU(source, target, N); break; case 2: copyGPUTexture(source, target, N); break; } cudaEventRecord(t2, 0); cudaEventSynchronize(t2); printf("\nSource data:\n"); for (int i = 0; i < N; i++) { printf("%5d", source[i]); } printf("\nTarget data:\n"); for (int i = 0; i < N; i++) { printf("%5d", target[i]); } printf("\n"); float gpuTime = 0; cudaEventElapsedTime(&gpuTime, t1, t2); printf("GPU Time is:%f\n", gpuTime); return 0; } 4、二维纹理存储器的使用方法

1)声明CUDA数组

使用CUDA数组主要通过三个函数使用:cudaMallocArray(), cudaMemcpyToArray(),cudaFreeArray(). 在声明CUDA数组之前,必须先描述结构体cudaChannelFormatDes()的组件数量和数据类型。

结构体定义:

struct cudaChannelFormatDesc { int x, y, z, w; enumcudaChannelFormatKind f; };

x, y, z和w分别是每个返回值成员的位数,而f是一个枚举变量,可以取一下几个值:

cudaChannelFormatKindSigned,如果这些成员是有符号整型 cudaChannelFormatKindUnsigned,如果这些成员是无符号整型 cudaChannelFormatKindFloat,如果这些成员是浮点型

CUDA数组的创建方法:

cudaChannelFormatDesc  channelDesc = cudaCreateChannelDesc();//声明数据类型 cudaArray *cuArray; //分配大小为W*H的CUDA数组 cudaMallocArray(&cuArray, &channelDesc, Width, Height);

CUDA 数组的复制:

cudaMemcpyToArray(struct cuArray* dstArray, size_t dstX, size_t dstY,  const void *src, size_t  count, enum cudaMemcpyKind kind);   //函数功能是:把数据src复制到CUDA 数组dstArray中,复制的数据字节大小为count,从src的左上角(dstX,dstY)开始复制。 //cudaMemcpyKind 复制方向有:hostTohost, hostTodevice, deviceTohost,device todevice(简写方式).

2)声明纹理参考系

//声明一个float 类型的2维的纹理,读取模式为cudaReadModeElementType,也可以声明其他的读取模式 texture texRef;

3)绑定CUDA数组到纹理

调用cudaBindTextureToArray()函数把CUDA数组和纹理连接起来。

4)设备端的纹理拾取

和一维纹理内存的tex1Dfetch()不同,需要使用tex1D()、tex2D()、tex3D()这三个函数,分别是用在1D/2D/3D的纹理。

 

二维纹理内存使步骤和一维区别不大,主要是利用CUDA数组来进行绑定。具体实例如下:

 

#include "cuda_runtime.h" #include "device_launch_parameters.h" #include #define W 16 #define H 16 //声明一个float 类型的2维的纹理,读取模式为cudaReadModeElementType texture texRef; __global__ void addKernel(float *array, const int w, const int h) { int idx = threadIdx.x + blockDim.x * blockIdx.x; int idy = threadIdx.y + blockDim.y * blockIdx.y; if (idx < w && idy (d_data, W ,H); cudaMemcpy(h_result, d_data, W*H * sizeof(float), cudaMemcpyDeviceToHost); //解除绑定 cudaUnbindTexture(texRef); //释放CDUA数组 cudaFreeArray(cuArray); //释放显存 cudaFree(d_data); printf("Origin data:\n"); for (int i = 0; i < W*H; i++) { printf("%8.1f", h_data[i]); } printf("\nResult:\n"); for (int i = 0; i < W*H; i++) { printf("%8.1f", h_result[i]); } return 0; }

参考:http://blog.csdn.net/augusdi/article/details/12187159

         《基于CUDA的并行程序设计》刘金硕



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3