CUDA使用纹理内存

纹理内存位于设备端,global memory也位于设备端,但是texture memory的访问速度较global memory要快。

因为纹理内存有cache, 只有当cache没有命中的时候才会去访问device memory,否则访问texture cache具有很小的延迟。

另外,texture cache的2D定位已经进行了优化,对于同一线程束的线程访问位置临近的texture memory时效率非常高。

还有,texture memory的stream fetching 也进行了优化,所以即使cache没有命中,对texture memory的访问延迟也不会很高。


初始化纹理内存:

[cpp]  view plain  copy
  1. texture<uchar, 3, cudaReadModeNormalizedFloat> tex;  
  2. cudaArray *d_volumeArray = 0;  
  3.   
  4. extern "C"  
  5. void initCudaTexture(const uchar *h_volume, cudaExtent volumeSize)  
  6. {  
  7.     cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<uchar>();  
  8.   
  9.     cutilSafeCall(cudaMalloc3DArray(&d_volumeArray, &channelDesc, volumeSize));  
  10.   
  11.     cudaMemcpy3DParms copyParams = {0};  
  12.     copyParams.srcPtr = make_cudaPitchedPtr((void*)h_volume, volumeSize.width*sizeof(uchar), volumeSize.width, volumeSize.height);  
  13.     copyParams.dstArray = d_volumeArray;  
  14.     copyParams.extent   = volumeSize;  
  15.     copyParams.kind     = cudaMemcpyHostToDevice;  
  16.     cutilSafeCall(cudaMemcpy3D(©Params));  
  17.   
  18.     tex.normalized = true;  
  19.     tex.filterMode = cudaFilterModeLinear;  
  20.     tex.addressMode[0] = cudaAddressModeWrap;  
  21.     tex.addressMode[1] = cudaAddressModeWrap;  
  22.     tex.addressMode[2] = cudaAddressModeWrap;  
  23.   
  24.     cutilSafeCall(cudaBindTextureToArray(tex, d_volumeArray, channelDesc));  
  25. }  


在上述代码中已经将h_volume中的数据拷贝到设备端的d_volumeArray中,然后又将其绑定到一个纹理内存。
下面在kernel函数中,对纹理进行访问,并将数据保存到PBO中,然后绘制。PBO的使用在前面已经写过了,可以参考之。

[cpp]  view plain  copy
  1. __global__ void kernel(uint *d_output, uint imageW, uint imageH, float w)  
  2. {  
  3.     uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;  
  4.     uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;  
  5.   
  6.     float u = x / (float)imageW;  
  7.     float v = y / (float)imageH;  
  8.   
  9.     float voxel = tex3D(tex, u, v, w);  
  10.       
  11.   
  12.     if ((x < imageW) && (y < imageH))  
  13.     {  
  14.         uint i = __umul24(y, imageW) + x;  
  15.         d_output[i] = voxel * 255;  
  16.   
  17. //      CUPRINTF("%d  ", d_output[i]);  
  18.     }  
  19. }  


代码:

[cpp]  view plain  copy
  1. //main.cpp  
  2.   
  3. #include <gl/glew.h>  
  4. #include <cuda_runtime.h>  
  5. #include <cutil_inline.h>  
  6. #include <cutil_gl_inline.h>  
  7. #include <cutil_gl_error.h>  
  8. #include <rendercheck_gl.h>  
  9.   
  10. typedef unsigned int  uint;  
  11. typedef unsigned char uchar;  
  12.   
  13. unsigned int window_width = 512;  
  14. unsigned int window_height = 512;  
  15.   
  16. unsigned int timer = 0;  
  17.   
  18. bool animFlag = true;  
  19. float animTime = 0.0;  
  20. float animInc  = 0.1;  
  21.   
  22. float w = 0.5;  
  23.   
  24. GLuint pbo = NULL;  
  25. struct cudaGraphicsResource *cuda_pbo_resource;  
  26.   
  27. cudaExtent volumeSize = make_cudaExtent(32, 32, 32);  
  28.   
  29. extern "C"  
  30. void initCudaTexture(const uchar *h_volume, cudaExtent volumeSize);  
  31.   
  32. extern "C"  
  33. void launch_kernel(uint *d_output, uint imageW, uint imageH, float w);  
  34.   
  35. void createPBO(GLuint *pbo)  
  36. {  
  37.     if(pbo)  
  38.     {  
  39.         glGenBuffers(1, pbo);  
  40.         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, *pbo);  
  41.         glBufferData(GL_PIXEL_UNPACK_BUFFER, window_width*window_height*sizeof(GLubyte)*4, 0, GL_STREAM_DRAW);  
  42.         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);  
  43.   
  44.         //cudaGLRegisterBufferObject(*pbo);  
  45.         cudaGraphicsGLRegisterBuffer(&cuda_pbo_resource, *pbo, cudaGraphicsMapFlagsWriteDiscard);  
  46.     }  
  47.   
  48. }  
  49.   
  50. void deletePBO(GLuint *pbo)  
  51. {  
  52.     if (pbo)  
  53.     {  
  54.         //  cudaGLUnregisterBufferObject(*pbo);  
  55.         cudaGraphicsUnregisterResource(cuda_pbo_resource);  
  56.   
  57.         glBindBuffer(GL_ARRAY_BUFFER, *pbo);  
  58.         glDeleteBuffers(1, pbo);  
  59.   
  60.         *pbo = NULL;  
  61.     }  
  62. }  
  63.   
  64. void cleanupCuda()  
  65. {  
  66.     if(pbo) deletePBO(&pbo);  
  67. }  
  68.   
  69. void runCuda()  
  70. {  
  71.   
  72.     unsigned int *d_output = NULL;  
  73.     size_t num_bytes;  
  74.   
  75.     //  cudaGLMapBufferObject((void**)&d_output, pbo);  
  76.     cudaGraphicsMapResources(1, &cuda_pbo_resource, 0);  
  77.     cudaGraphicsResourceGetMappedPointer((void**)&d_output, &num_bytes, cuda_pbo_resource);  
  78.   
  79.     launch_kernel(d_output, window_width, window_height, w);  
  80.   
  81.     cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0);  
  82.     //  cudaGLUnmapBufferObject(pbo);  
  83.   
  84.   
  85. }  
  86.   
  87. uchar *loadVolumeData(const char *filename)  
  88. {  
  89.     size_t size = volumeSize.width * volumeSize.height * volumeSize.depth;  
  90.   
  91.     FILE *fp = fopen(filename, "rb");  
  92.     if (!fp)  
  93.     {  
  94.         fprintf(stderr, "Error openging file '%s'\n", filename);  
  95.         return 0;  
  96.     }  
  97.   
  98.     uchar *data = (uchar *)malloc(size);  
  99.     size_t read = fread(data, 1, size, fp);  
  100.     fclose(fp);  
  101.   
  102.     printf("Read '%s', %lu bytes\n", filename, read);  
  103.   
  104.     return data;  
  105.   
  106. }  
  107.   
  108.   
  109. void initCuda(int argc, char **argv)  
  110. {  
  111.     if(cutCheckCmdLineFlag(argc, (const char**)argv, "device"))  
  112.         cutilGLDeviceInit(argc, argv);  
  113.     else  
  114.         cudaGLSetGLDevice(cutGetMaxGflopsDeviceId());  
  115.   
  116.     createPBO(&pbo);  
  117.   
  118.     uchar *data = loadVolumeData("Bucky.raw");  
  119.   
  120.     initCudaTexture(data, volumeSize);  
  121.   
  122.     atexit(cleanupCuda);  
  123.   
  124.     runCuda();  
  125. }  
  126.   
  127. void computeFPS()  
  128. {  
  129.     static int fpsCount = 0;  
  130.     static int fpsLimit = 100;  
  131.   
  132.     fpsCount++;  
  133.   
  134.     if(fpsCount == fpsLimit)  
  135.     {  
  136.         char fps[256];  
  137.         float ifps = 1.0f / (cutGetAverageTimerValue(timer) / 1000.0f);  
  138.         sprintf(fps, "Cuda GL Interop Wrapper: %3.1f fps", ifps);  
  139.   
  140.         glutSetWindowTitle(fps);  
  141.         fpsCount = 0;  
  142.   
  143.         cutilCheckError(cutResetTimer(timer));    
  144.     }  
  145. }  
  146.   
  147. void display()  
  148. {  
  149.     runCuda();  
  150.   
  151.     glClear(GL_COLOR_BUFFER_BIT);  
  152.   
  153.     glDisable(GL_DEPTH_TEST);  
  154.     glRasterPos2i(0, 0);  
  155.     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);  
  156.     glDrawPixels(window_width, window_height, GL_RGBA, GL_UNSIGNED_BYTE, 0);  
  157.     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);  
  158.   
  159.     glutSwapBuffers();  
  160.     glutReportErrors();  
  161.     /*if (animFlag) 
  162.     { 
  163.          
  164.         animTime += animInc; 
  165.     }*/  
  166. //  glutPostRedisplay();  
  167. }  
  168.   
  169. void fpsDisplay()  
  170. {  
  171.     cutilCheckError(cutStartTimer(timer));  
  172.   
  173.     display();  
  174.   
  175.     cutilCheckError(cutStopTimer(timer));  
  176.   
  177.     computeFPS();  
  178. }  
  179.   
  180. void keyboard(unsigned char key, int x, int y)  
  181. {  
  182.   
  183. }  
  184.   
  185. void idle()  
  186. {  
  187.     if (animFlag)  
  188.     {  
  189. //      animTime += animInc;  
  190.         w += 0.01f;  
  191.         glutPostRedisplay();  
  192.     }  
  193. }  
  194.   
  195. void reshape(int x, int y)  
  196. {  
  197.     glViewport(0, 0, x, y);  
  198.   
  199.     glMatrixMode(GL_MODELVIEW);  
  200.     glLoadIdentity();  
  201.   
  202.     glMatrixMode(GL_PROJECTION);  
  203.     glLoadIdentity();  
  204.     glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);   
  205. }  
  206.   
  207. CUTBoolean initGL(int argc, char **argv)  
  208. {  
  209.     glutInit(&argc, argv);  
  210.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);  
  211.     glutInitWindowSize(window_width, window_height);  
  212.     glutCreateWindow("Cuda GL Interop Demo (adapted from NVDIA's simpleGL)");  
  213.   
  214.     glutDisplayFunc(fpsDisplay);  
  215.     glutKeyboardFunc(keyboard);  
  216.     glutReshapeFunc(reshape);  
  217.     glutIdleFunc(idle);  
  218.   
  219.     glewInit();  
  220.     if(!glewIsSupported("GL_VERSION_2_0"))  
  221.     {  
  222.         fprintf(stderr, "ERROR: Support for necessary OpengGL extensions missing.");  
  223.         return CUTFalse;  
  224.     }  
  225.   
  226.     glClearColor(0.0, 0.0, 0.0, 1.0);  
  227.     glDisable(GL_DEPTH_TEST);  
  228.   
  229.     glViewport(0, 0, window_width, window_height);  
  230.   
  231.     glMatrixMode(GL_PROJECTION);  
  232.     glLoadIdentity();  
  233.     gluPerspective(60.0, (GLfloat)window_width / (GLfloat)window_height, 0.1, 10.0);  
  234.   
  235.     return CUTTrue;  
  236. }  
  237.   
  238.   
  239.   
  240.   
  241. int main(int argc, char **argv)  
  242. {  
  243.   
  244.     cutilCheckError(cutCreateTimer(&timer));  
  245.   
  246.     if(CUTFalse == initGL(argc, argv))  
  247.         return CUTFalse;  
  248.   
  249.     initCuda(argc, argv);  
  250.     CUT_CHECK_ERROR_GL();  
  251.   
  252.     runCuda();  
  253.   
  254.     glutDisplayFunc(fpsDisplay);  
  255.     glutKeyboardFunc(keyboard);  
  256.     glutIdleFunc(idle);  
  257.   
  258.     glutMainLoop();  
  259.   
  260.     cudaThreadExit();           ///  
  261.     cutilExit(argc, argv);      //  
  262.   
  263. }  

[cpp]  view plain  copy
  1. //kernelTexture.cu  
  2.   
  3. #include <stdio.h>  
  4. #include <cutil_inline.h>  
  5. #include <cutil_math.h>  
  6. #include "cuPrintf.cu"  
  7.   
  8. //The macro CUPRINTF is defined for architectures  
  9. //with different compute capabilities.  
  10. #if __CUDA_ARCH__ < 200  //Compute capability 1.x architectures  
  11. #define CUPRINTF cuPrintf   
  12. #else                       //Compute capability 2.x architectures  
  13. #define CUPRINTF(fmt, ...) printf("[%d, %d]:\t" fmt, \  
  14.     blockIdx.y*gridDim.x+blockIdx.x,\  
  15.     threadIdx.z*blockDim.x*blockDim.y+threadIdx.y*blockDim.x+threadIdx.x,\  
  16.     __VA_ARGS__)  
  17. #endif  
  18.   
  19.   
  20. typedef unsigned int  uint;  
  21. typedef unsigned char uchar;  
  22.   
  23. texture<uchar, 3, cudaReadModeNormalizedFloat> tex;  
  24. cudaArray *d_volumeArray = 0;  
  25.   
  26.   
  27. __global__ void kernel(uint *d_output, uint imageW, uint imageH, float w)  
  28. {  
  29.     uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;  
  30.     uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;  
  31.   
  32.     float u = x / (float)imageW;  
  33.     float v = y / (float)imageH;  
  34.   
  35.     float voxel = tex3D(tex, u, v, w);  
  36.       
  37.   
  38.     if ((x < imageW) && (y < imageH))  
  39.     {  
  40.         uint i = __umul24(y, imageW) + x;  
  41.         d_output[i] = voxel * 255;  
  42.   
  43. //      CUPRINTF("%d  ", d_output[i]);  
  44.     }  
  45. }  
  46.   
  47.   
  48. extern "C"  
  49. void launch_kernel(uint *d_output, uint imageW, uint imageH, float w)  
  50. {  
  51.     dim3 blockSize(16, 16, 1);  
  52.     dim3 gridSize(imageW/blockSize.x, imageH/blockSize.y);  
  53.   
  54.     kernel<<<gridSize, blockSize>>>(d_output, imageW, imageH, w);  
  55.   
  56.       
  57. }  
  58.   
  59.   
  60. extern "C"  
  61. void initCudaTexture(const uchar *h_volume, cudaExtent volumeSize)  
  62. {  
  63.     cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<uchar>();  
  64.   
  65.     cutilSafeCall(cudaMalloc3DArray(&d_volumeArray, &channelDesc, volumeSize));  
  66.   
  67.     cudaMemcpy3DParms copyParams = {0};  
  68.     copyParams.srcPtr = make_cudaPitchedPtr((void*)h_volume, volumeSize.width*sizeof(uchar), volumeSize.width, volumeSize.height);  
  69.     copyParams.dstArray = d_volumeArray;  
  70.     copyParams.extent   = volumeSize;  
  71.     copyParams.kind     = cudaMemcpyHostToDevice;  
  72.     cutilSafeCall(cudaMemcpy3D(©Params));  
  73.   
  74.     tex.normalized = true;  
  75.     tex.filterMode = cudaFilterModeLinear;  
  76.     tex.addressMode[0] = cudaAddressModeWrap;  
  77.     tex.addressMode[1] = cudaAddressModeWrap;  
  78.     tex.addressMode[2] = cudaAddressModeWrap;  
  79.   
  80.     cutilSafeCall(cudaBindTextureToArray(tex, d_volumeArray, channelDesc));  
  81. }  



运行结果:



参考自CUDA SDK

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值