紋理存儲器非常適合實現圖像處理和查找表,對大量數據的隨機訪問或非隨機訪問也有良好的加速效果。第一次接觸紋理存儲器,寫了以下一個小程序。
相關閱讀:
Ubuntu 11.10 上安裝CUDA開發環境 http://www.linuxidc.com/Linux/2012-04/58913.htm
Ubuntu 11.04 安裝 NVIDIA CUDA 4.0 RC2 見 http://www.linuxidc.com/Linux/2011-10/46304.htm
- /*
- * Copyright 徐洪志(西北農林科技大學.信息工程學院). All rights reserved.
- * Data: 2012-4-20
- */
- //
- // 此程序是演示了1D和2D紋理存儲器的使用
- #include <stdio.h>
- #include <cutil_inline.h>
- #include <iostream>
- using namespace std;
-
- texture<float> texRef1D; // 1D texture
- texture<float, 2> texRef2D; // 2D texture
-
- // 1D 紋理操作函數
- __global__ void Texture1D(float *dst, int w, int h)
- {
- int x = threadIdx.x + blockIdx.x * blockDim.x;
- int y = threadIdx.y + blockIdx.y * blockDim.y;
- int offset = x + y * blockDim.x * gridDim.x;
-
- if(x<w && y<h)
- dst[offset] = tex1Dfetch(texRef1D, offset);
- }
- // 2D 紋理操作函數
- __global__ void Texture2D(float *dst, int w, int h)
- {
- int x = threadIdx.x + blockIdx.x * blockDim.x;
- int y = threadIdx.y + blockIdx.y * blockDim.y;
- int offset = x + y * blockDim.x * gridDim.x;
-
- dst[offset] = tex2D(texRef2D, x, y);
- }
- int main(int argc, char **argv)
- {
- CUT_DEVICE_INIT(argc, argv); // 啟動 CUDA
- /// 1D 紋理內存
- cout << "1D texture" << endl;
- float *host1D = (float*)calloc(10, sizeof(float)); // 內存原數據
- float *hostRet1D = (float*)calloc(10, sizeof(float));// 內存保存返回數據
-
- float *dev1D, *devRet1D; // 顯存數據
- int i;
- cout << " host1D:" << endl;
- for(i = 0; i < 10; ++i) // 初始化內存原數據
- {
- host1D[i] = i * 2;
- cout << " " << host1D[i] << " ";
- }
- cutilSafeCall( cudaMalloc((void**)&dev1D, sizeof(float)*10)); // 申請顯存空間
- cutilSafeCall( cudaMalloc((void**)&devRet1D, sizeof(float)*10));
- cutilSafeCall( cudaMemcpy(dev1D, host1D, sizeof(float)*10, cudaMemcpyHostToDevice)); // 將內存數據拷貝入顯存
- cutilSafeCall( cudaBindTexture(NULL, texRef1D, dev1D, sizeof(float)*10)); // 將顯存數據和紋理綁定
-
- Texture1D<<<10, 1>>>(devRet1D, 10, 1); // 運行1D紋理操作函數
-
- cutilSafeCall( cudaMemcpy(hostRet1D, devRet1D, sizeof(float)*10, cudaMemcpyDeviceToHost)); // 將顯存數據拷貝入內存
- // 打印內存數據
- cout << endl << " hostRet1D:" << endl;
- for(i = 0; i < 10; ++i)
- cout << " " << hostRet1D[i] << " ";
-
- cutilSafeCall( cudaUnbindTexture(texRef1D)); // 解綁定
- cutilSafeCall( cudaFree(dev1D)); // 釋放顯存空間
- cutilSafeCall( cudaFree(devRet1D));
- free(host1D); // 釋放內存空間
- free(hostRet1D);
-
- /// 2D 紋理內存
- cout << endl << "2D texture" << endl;
- int width = 5, height = 3;
- float *host2D = (float*)calloc(width*height, sizeof(float)); // 內存原數據
- float *hostRet2D = (float*)calloc(width*height, sizeof(float)); // 內存返回數據
-
- cudaArray *cuArray; // CUDA數組
- float *devRet2D; // 顯存數據
- int row, col;
- cout << " host2D:" << endl;
- for(row = 0; row < height; ++row) // 初始化內存原數據
- {
- for(col = 0; col < width; ++col)
- {
- host2D[row*width + col] = row + col;
- cout << " " << host2D[row*width + col] << " ";
- }
- cout << endl;
- }
- cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
- cutilSafeCall( cudaMallocArray(&cuArray, &channelDesc, width, height)); // 申請顯存空間
- cutilSafeCall( cudaMalloc((void**) &devRet2D, sizeof(float)*width*height));
- cutilSafeCall( cudaBindTextureToArray(texRef2D, cuArray)); // 將顯存數據和紋理綁定
- cutilSafeCall( cudaMemcpyToArray(cuArray, 0, 0, host2D, sizeof(float)*width*height, cudaMemcpyHostToDevice)); // 將內存數據拷貝入CUDA數組
-
- dim3 threads(width, height);
- Texture2D<<<1, threads>>>(devRet2D, width, height); // 運行2D紋理操作函數
-
- cutilSafeCall( cudaMemcpy(hostRet2D, devRet2D, sizeof(float)*width*height, cudaMemcpyDeviceToHost)); // 將顯存數據拷貝入內存
- // 打印內存數據
- cout << " hostRet2D:" << endl;
- for(row = 0; row < height; ++row)
- {
- for(col = 0; col < width; ++col)
- cout << " " << hostRet2D[row*width + col] << " ";
- cout << endl;
- }
-
- cutilSafeCall( cudaUnbindTexture(texRef2D)); // 解綁定
- cutilSafeCall( cudaFreeArray(cuArray)); // 釋放顯存空間
- cutilSafeCall( cudaFree(devRet2D));
- free(host2D); // 釋放內存空間
- free(hostRet2D);
-
- CUT_EXIT(argc, argv); // 退出CUDA
- }