▶ 本章介绍了纹理内存的使用,并给出了热传导的两个个例子。分别使用了一维和二维纹理单元。

● 热传导(使用一维纹理)

  1. #include <stdio.h>
  2. #include "cuda_runtime.h"
  3. #include "device_launch_parameters.h"
  4. #include "D:\Code\CUDA\book\common\book.h"
  5. #include "D:\Code\CUDA\book\common\cpu_anim.h"
  6.  
  7. #define DIM 1024
  8. #define PI 3.1415926535897932f
  9. #define MAX_TEMP 1.0f
  10. #define MIN_TEMP 0.0001f
  11. #define SPEED 0.25f
  12.  
  13. //在全局位置上声明纹理引用,存在于GPU中
  14. texture<float> texConstSrc;
  15. texture<float> texIn;
  16. texture<float> texOut;
  17.  
  18. struct DataBlock
  19. {
  20. unsigned char *output_bitmap;
  21. float *dev_inSrc;
  22. float *dev_outSrc;
  23. float *dev_constSrc;
  24. CPUAnimBitmap *bitmap;
  25. cudaEvent_t start, stop;
  26. float totalTime;
  27. float frames;
  28. };
  29.  
  30. __global__ void blend_kernel(float *dst, bool dstOut)
  31. {
  32. int x = threadIdx.x + blockIdx.x * blockDim.x;
  33. int y = threadIdx.y + blockIdx.y * blockDim.y;
  34. int offset = x + y * blockDim.x * gridDim.x;
  35.  
  36. int left = offset - ;//找到上下左右的块
  37. int right = offset + ;
  38. int top = offset - DIM;
  39. int bottom = offset + DIM;
  40. if (x == )
  41. left++;
  42. if (x == DIM - )
  43. right--;
  44. if (y == )
  45. top += DIM;
  46. if (y == DIM - )
  47. bottom -= DIM;
  48. float t, l, c, r, b;
  49. if (dstOut)
  50. {
  51. t = tex1Dfetch(texIn, top);
  52. l = tex1Dfetch(texIn, left);
  53. c = tex1Dfetch(texIn, offset);
  54. r = tex1Dfetch(texIn, right);
  55. b = tex1Dfetch(texIn, bottom);
  56. }
  57. else
  58. {
  59. t = tex1Dfetch(texOut, top);
  60. l = tex1Dfetch(texOut, left);
  61. c = tex1Dfetch(texOut, offset);
  62. r = tex1Dfetch(texOut, right);
  63. b = tex1Dfetch(texOut, bottom);
  64. }
  65.  
  66. dst[offset] = c + SPEED * (t + b + r + l - * c);
  67.  
  68. return;
  69. }
  70.  
  71. __global__ void copy_const_kernel(float *iptr)// 将恒温常量矩阵覆盖输入矩阵
  72. {
  73. int x = threadIdx.x + blockIdx.x * blockDim.x;
  74. int y = threadIdx.y + blockIdx.y * blockDim.y;
  75. int offset = x + y * blockDim.x * gridDim.x;
  76.  
  77. float c = tex1Dfetch(texConstSrc, offset);
  78. if (c != )
  79. iptr[offset] = c;
  80.  
  81. return;
  82. }
  83.  
  84. void anim_gpu(DataBlock *d, int ticks)
  85. {
  86. cudaEventRecord(d->start, );
  87. dim3 blocks(DIM / , DIM / );
  88. dim3 threads(, );
  89. CPUAnimBitmap *bitmap = d->bitmap;
  90.  
  91. volatile bool dstOut = true;//确定输入矩阵是哪一个,true代表dev_inSrc,false代表ev_outSrc
  92. for (int i = ; i < ; i++)
  93. {
  94. float *in, *out;
  95. if (dstOut)
  96. {
  97. in = d->dev_inSrc;
  98. out = d->dev_outSrc;
  99. }
  100. else
  101. {
  102. in = d->dev_outSrc;
  103. out = d->dev_inSrc;
  104. }
  105.  
  106. copy_const_kernel << < blocks, threads >> > (in);
  107. blend_kernel << < blocks, threads >> > (out, dstOut);
  108. dstOut = !dstOut;
  109. }
  110. float_to_color << < blocks, threads >> > (d->output_bitmap, d->dev_inSrc);
  111.  
  112. cudaMemcpy(bitmap->get_ptr(), d->output_bitmap, bitmap->image_size(), cudaMemcpyDeviceToHost);
  113.  
  114. cudaEventRecord(d->stop, );
  115. cudaEventSynchronize(d->stop);
  116. float elapsedTime;
  117. cudaEventElapsedTime(&elapsedTime, d->start, d->stop);
  118. d->totalTime += elapsedTime;
  119. ++d->frames;
  120. printf("Average Time per frame: %3.1f ms\n", d->totalTime / d->frames);
  121. }
  122.  
  123. void anim_exit(DataBlock *d)// 收拾申请的内存
  124. {
  125. cudaUnbindTexture(texIn);
  126. cudaUnbindTexture(texOut);
  127. cudaUnbindTexture(texConstSrc);
  128. cudaFree(d->dev_inSrc);
  129. cudaFree(d->dev_outSrc);
  130. cudaFree(d->dev_constSrc);
  131.  
  132. cudaEventDestroy(d->start);
  133. cudaEventDestroy(d->stop);
  134. return;
  135. }
  136.  
  137. int main(void)
  138. {
  139. DataBlock data;
  140. CPUAnimBitmap bitmap(DIM, DIM, &data);
  141. data.bitmap = &bitmap;
  142. data.totalTime = ;
  143. data.frames = ;
  144. cudaEventCreate(&data.start);
  145. cudaEventCreate(&data.stop);
  146.  
  147. int imageSize = bitmap.image_size();
  148.  
  149. cudaMalloc((void**)&data.output_bitmap, imageSize);
  150.  
  151. cudaMalloc((void**)&data.dev_inSrc, imageSize);
  152. cudaMalloc((void**)&data.dev_outSrc, imageSize);
  153. cudaMalloc((void**)&data.dev_constSrc, imageSize);
  154. cudaBindTexture(NULL, texConstSrc, data.dev_constSrc, imageSize);//将内存绑定到之前声明的纹理引用中去
  155. cudaBindTexture(NULL, texIn, data.dev_inSrc, imageSize);
  156. cudaBindTexture(NULL, texOut, data.dev_outSrc, imageSize);
  157.  
  158. float *temp = (float*)malloc(imageSize);
  159. for (int i = ; i < DIM*DIM; i++)// 恒温格点数据
  160. {
  161. temp[i] = ;
  162. int x = i % DIM;
  163. int y = i / DIM;
  164. if ((x >= ) && (x < ) && (y >= ) && (y < ))
  165. temp[i] = MAX_TEMP;
  166. if ((x >= ) && (x < ) && (y >= ) && (y < ))
  167. temp[i] = MIN_TEMP;
  168. }
  169. cudaMemcpy(data.dev_constSrc, temp, imageSize, cudaMemcpyHostToDevice);
  170.  
  171. for (int i = ; i < DIM*DIM; i++)// 初始温度场数据
  172. {
  173. temp[i] = 0.5;
  174. int x = i % DIM;
  175. int y = i / DIM;
  176. if ((x >= ) && (x < ) && (y >= ) && (y < ))
  177. temp[i] = MAX_TEMP;
  178. }
  179. cudaMemcpy(data.dev_inSrc, temp, imageSize, cudaMemcpyHostToDevice);
  180.  
  181. free(temp);
  182.  
  183. bitmap.anim_and_exit((void(*)(void*, int))anim_gpu, (void(*)(void*))anim_exit);
  184.  
  185. getchar();
  186. return;
  187. }

● 输出结果(左侧为恒高温,中间为恒低温,右侧为初始高温点)

● 使用一维纹理内存的过程浓缩一下就变成了以下过程

  1. texture<float> texSrc;// 在全局位置上声明纹理引用
  2.  
  3. float *dev_Src;
  4. cudaMalloc((void**)&dev_Src, sizeof(float)*DIM);// 申请和绑定纹理内存
  5. cudaBindTexture(NULL, texSrc, dev_Src, NULL);
  6.  
  7. float *temp = (float *)malloc(sizeof(float)*DIM);// 初始化该内存中的内容
  8. //Initalize data in temp and then free(temp)
  9.  
  10. cudaMemcpy(dev_Src, temp, sizeof(float)*DIM, cudaMemcpyHostToDevice);
  11.  
  12. //Do something
  13.  
  14. cudaUnbindTexture(texSrc);// 解绑和释放内存
  15. cudaFree(dev_Src);

● 访问纹理内存不用中括号下标,而是

  1. int x = threadIdx.x + blockIdx.x * blockDim.x;
  2. int y = threadIdx.y + blockIdx.y * blockDim.y;
  3. int offset = x + y * blockDim.x * gridDim.x;
  4. float c = tex1Dfetch(texSrc, offset);

● 热传导(使用二维纹理),输出结果同一维纹理的的情况,速度上没有明显差别

  1. #include <stdio.h>
  2. #include "cuda_runtime.h"
  3. #include "device_launch_parameters.h"
  4. #include "D:\Code\CUDA\book\common\book.h"
  5. #include "D:\Code\CUDA\book\common\cpu_anim.h"
  6.  
  7. #define DIM 1024
  8. #define PI 3.1415926535897932f
  9. #define MAX_TEMP 1.0f
  10. #define MIN_TEMP 0.0001f
  11. #define SPEED 0.25f
  12.  
  13. texture<float, > texConstSrc;
  14. texture<float, > texIn;
  15. texture<float, > texOut;
  16.  
  17. struct DataBlock
  18. {
  19. unsigned char *output_bitmap;
  20. float *dev_inSrc;
  21. float *dev_outSrc;
  22. float *dev_constSrc;
  23. CPUAnimBitmap *bitmap;
  24. cudaEvent_t start, stop;
  25. float totalTime;
  26. float frames;
  27. };
  28.  
  29. __global__ void blend_kernel(float *dst,bool dstOut)
  30. {
  31. int x = threadIdx.x + blockIdx.x * blockDim.x;
  32. int y = threadIdx.y + blockIdx.y * blockDim.y;
  33. int offset = x + y * blockDim.x * gridDim.x;
  34.  
  35. float t, l, c, r, b;
  36. if (dstOut)//不需要自己处理边界情况
  37. {
  38. t = tex2D(texIn, x, y - );
  39. l = tex2D(texIn, x - , y);
  40. c = tex2D(texIn, x, y);
  41. r = tex2D(texIn, x + , y);
  42. b = tex2D(texIn, x, y + );
  43. }
  44. else
  45. {
  46. t = tex2D(texOut, x, y - );
  47. l = tex2D(texOut, x - , y);
  48. c = tex2D(texOut, x, y);
  49. r = tex2D(texOut, x + , y);
  50. b = tex2D(texOut, x, y + );
  51. }
  52. dst[offset] = c + SPEED * (t + b + r + l - * c);
  53.  
  54. return;
  55. }
  56.  
  57. __global__ void copy_const_kernel(float *iptr)
  58. {
  59. // map from threadIdx/BlockIdx to pixel position
  60. int x = threadIdx.x + blockIdx.x * blockDim.x;
  61. int y = threadIdx.y + blockIdx.y * blockDim.y;
  62. int offset = x + y * blockDim.x * gridDim.x;
  63.  
  64. float c = tex2D(texConstSrc, x, y);
  65. if (c != )
  66. iptr[offset] = c;
  67.  
  68. return;
  69. }
  70.  
  71. void anim_gpu(DataBlock *d, int ticks)
  72. {
  73. cudaEventRecord(d->start, );
  74. dim3 blocks(DIM / , DIM / );
  75. dim3 threads(, );
  76. CPUAnimBitmap *bitmap = d->bitmap;
  77.  
  78. volatile bool dstOut = true;
  79. for (int i = ; i < ; i++)
  80. {
  81. float *in, *out;
  82. if (dstOut) {
  83. in = d->dev_inSrc;
  84. out = d->dev_outSrc;
  85. }
  86. else
  87. {
  88. out = d->dev_inSrc;
  89. in = d->dev_outSrc;
  90. }
  91. copy_const_kernel << <blocks, threads >> > (in);
  92. blend_kernel << <blocks, threads >> > (out, dstOut);
  93. dstOut = !dstOut;
  94. }
  95. float_to_color << <blocks, threads >> > (d->output_bitmap, d->dev_inSrc);
  96.  
  97. cudaMemcpy(bitmap->get_ptr(), d->output_bitmap, bitmap->image_size(), cudaMemcpyDeviceToHost);
  98.  
  99. cudaEventRecord(d->stop, );
  100. cudaEventSynchronize(d->stop);
  101.  
  102. float elapsedTime;
  103. cudaEventElapsedTime(&elapsedTime, d->start, d->stop);
  104. d->totalTime += elapsedTime;
  105. ++d->frames;
  106. printf("Average Time per frame: %3.1f ms\n", d->totalTime / d->frames);
  107.  
  108. return;
  109. }
  110.  
  111. void anim_exit(DataBlock *d)
  112. {
  113. cudaUnbindTexture(texIn);
  114. cudaUnbindTexture(texOut);
  115. cudaUnbindTexture(texConstSrc);
  116. cudaFree(d->dev_inSrc);
  117. cudaFree(d->dev_outSrc);
  118. cudaFree(d->dev_constSrc);
  119.  
  120. cudaEventDestroy(d->start);
  121. cudaEventDestroy(d->stop);
  122. return;
  123. }
  124.  
  125. int main(void)
  126. {
  127. DataBlock data;
  128. CPUAnimBitmap bitmap(DIM, DIM, &data);
  129. data.bitmap = &bitmap;
  130. data.totalTime = ;
  131. data.frames = ;
  132. cudaEventCreate(&data.start);
  133. cudaEventCreate(&data.stop);
  134.  
  135. int imageSize = bitmap.image_size();
  136.  
  137. cudaMalloc((void**)&data.output_bitmap, imageSize);
  138.  
  139. cudaMalloc((void**)&data.dev_inSrc, imageSize);
  140. cudaMalloc((void**)&data.dev_outSrc, imageSize);
  141. cudaMalloc((void**)&data.dev_constSrc, imageSize);
  142.  
  143. cudaChannelFormatDesc desc = cudaCreateChannelDesc<float>();
  144. cudaBindTexture2D(NULL, texConstSrc, data.dev_constSrc, desc, DIM, DIM, sizeof(float) * DIM);
  145. cudaBindTexture2D(NULL, texIn, data.dev_inSrc, desc, DIM, DIM, sizeof(float) * DIM);
  146. cudaBindTexture2D(NULL, texOut, data.dev_outSrc, desc, DIM, DIM, sizeof(float) * DIM);
  147.  
  148. float *temp = (float*)malloc(imageSize);
  149. for (int i = ; i<DIM*DIM; i++) {
  150. temp[i] = ;
  151. int x = i % DIM;
  152. int y = i / DIM;
  153. if ((x >= ) && (x < ) && (y >= ) && (y < ))
  154. temp[i] = MAX_TEMP;
  155. if ((x >= ) && (x < ) && (y >= ) && (y < ))
  156. temp[i] = MIN_TEMP;
  157. }
  158. cudaMemcpy(data.dev_constSrc, temp, imageSize, cudaMemcpyHostToDevice);
  159.  
  160. for (int i = ; i < DIM*DIM; i++)// 初始温度场数据
  161. {
  162. temp[i] = 0.5;
  163. int x = i % DIM;
  164. int y = i / DIM;
  165. if ((x >= ) && (x < ) && (y >= ) && (y < ))
  166. temp[i] = MAX_TEMP;
  167. }
  168. cudaMemcpy(data.dev_inSrc, temp, imageSize, cudaMemcpyHostToDevice);
  169. free(temp);
  170.  
  171. bitmap.anim_and_exit((void(*)(void*, int))anim_gpu, (void(*)(void*))anim_exit);
  172.  
  173. getchar();
  174. return ;
  175. }

● 使用纹理内存的过程浓缩一下就变成了以下过程

  1. texture<float, > texSrc;// 在全局位置上声明纹理引用
  2.  
  3. float *dev_Src;
  4. cudaMalloc((void**)&dev_Src, DIM*DIM);// 申请和绑定纹理内存
  5. cudaChannelFormatDesc desc = cudaCreateChannelDesc<float>();
  6. cudaBindTexture2D(NULL, texSrc, dev_Src, desc, DIM, DIM, sizeof(float) * DIM*DIM);
  7.  
  8. float *temp = (float*)malloc(sizeof(float)*DIM*DIM);// 初始化该内存中的内容
  9. //Initalize data in temp and then free(temp)
  10.  
  11. cudaMemcpy(dev_Src, temp, sizeof(float)*DIM*DIM, cudaMemcpyHostToDevice);
  12.  
  13. //Do something
  14.  
  15. cudaUnbindTexture(texSrc);// 解绑和释放内存
  16. cudaFree(dev_Src);

● 访问纹理内存不用中括号下标,而是

  1. int x = threadIdx.x + blockIdx.x * blockDim.x;
  2. int y = threadIdx.y + blockIdx.y * blockDim.y;
  3. float c = tex2D(texSrc, x, y);

《GPU高性能编程CUDA实战》第七章 纹理内存的更多相关文章

  1. 《GPU高性能编程CUDA实战》第九章 原子性

    ▶ 本章介绍了原子操作,给出了基于原子操作的直方图计算的例子. ● 章节代码 #include <stdio.h> #include "cuda_runtime.h" ...

  2. [问题解决]《GPU高性能编程CUDA实战》中第4章Julia实例“显示器驱动已停止响应,并且已恢复”问题的解决方法

    以下问题的出现及解决都基于"WIN7+CUDA7.5". 问题描述:当我编译运行<GPU高性能编程CUDA实战>中第4章所给Julia实例代码时,出现了显示器闪动的现象 ...

  3. 《GPU高性能编程CUDA实战》第十一章 多GPU系统的CUDA C

    ▶ 本章介绍了多设备胸膛下的 CUDA 编程,以及一些特殊存储类型对计算速度的影响 ● 显存和零拷贝内存的拷贝与计算对比 #include <stdio.h> #include " ...

  4. 《GPU高性能编程CUDA实战》第五章 线程并行

    ▶ 本章介绍了线程并行,并给出四个例子.长向量加法.波纹效果.点积和显示位图. ● 长向量加法(线程块并行 + 线程并行) #include <stdio.h> #include &quo ...

  5. 《GPU高性能编程CUDA实战》第四章 简单的线程块并行

    ▶ 本章介绍了线程块并行,并给出两个例子:长向量加法和绘制julia集. ● 长向量加法,中规中矩的GPU加法,包含申请内存和显存,赋值,显存传入,计算,显存传出,处理结果,清理内存和显存.用到了 t ...

  6. 《GPU高性能编程CUDA实战》第六章 常量内存

    ▶ 本章介绍了常量内存的使用,并给光线追踪的一个例子.介绍了结构cudaEvent_t及其在计时方面的使用. ● 章节代码,大意是有SPHERES个球分布在原点附近,其球心坐标在每个坐标轴方向上分量绝 ...

  7. 《GPU高性能编程CUDA实战》第三章 CUDA设备相关

    ▶ 这章介绍了与CUDA设备相关的参数,并给出了了若干用于查询参数的函数. ● 代码(已合并) #include <stdio.h> #include "cuda_runtime ...

  8. 《GPU高性能编程CUDA实战中文》中第四章的julia实验

    在整个过程中出现了各种问题,我先将我调试好的真个项目打包,提供下载. /* * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. ...

  9. 《GPU高性能编程CUDA实战》附录二 散列表

    ▶ 使用CPU和GPU分别实现散列表 ● CPU方法 #include <stdio.h> #include <time.h> #include "cuda_runt ...

随机推荐

  1. 使用 WPF 开发一个 Windows 屏幕保护程序

    最近有小伙伴问我如何可以让 Windows 静置一段时间不操作之后,显示一个特殊的界面.我想了想,屏幕保护程序可以做到这一点,而且,屏幕保护程序的开发也是非常简单的. 本文将介绍如何为 Windows ...

  2. 实习第一周第一天:接口 extends是继承类,implement是实现接口,原接口里面的方法填充,方法名也是不变,重写override是父类的方法名不变,把方法体给改了

    一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...

  3. web开发的一些总结

    现在我们是在互联网的时代,到处可以使用internet 这些年的发展,让we 成为了当前开发的主流,包括现在好多的移动端开发, 很多也是使用web 页面进行呈现,因为web 拉近了你我之间的距离.对于 ...

  4. tomcat下安装jenkins

    参考网址:http://www.cnblogs.com/edward2013/p/5269465.html 5.安装Jenkins 方法1: jenkins.war下载地址:   http://mir ...

  5. SQL SERVER 2008 彻底卸载干净方法 (转)

    最近安装SQL SERVER 2008失败后,再重新安装时老是报错,东搞西搞的很难卸干净.但又不方便重装系统,经按下面方法终于搞定并成功安装上2008 1.停掉SQL SERVER 2008所有相关服 ...

  6. POJ2127 LICS模板

    题目:http://poj.org/problem?id=2127 十分费劲地终于记录好了路径……用一个前驱. 这是 n^2 的LICS方法.其实就是 n ^ 2 log n 把“找之前的d [ j ...

  7. WPF中控制窗口显示位置的三种方式

    首先新建一个WPF工程,在主界面添加一个按钮,并给按钮添加点击事件button1_Click,然后新建一个用于测试弹出位置的窗口TestWindow.1.在屏幕中间显示,设置window.Window ...

  8. JMeter和JMeterPlugin的下载安装

    JMeter和JMeterPlugin的下载安装 Apache Jmeter是一个100%的纯Java桌面应用,主要是针对web的压力和性能测试,但后来扩展到其他测试领域.Jmeter可以用于测试FT ...

  9. hadoop技术入门学习之发行版选择

    经常会看到这样的问题:零基础学习hadoop难不难?有的人回答说:零基础学习hadoop,没有想象的那么难,也没有想象的那么容易.看到这样的答案不免觉得有些尴尬,这个问题算是白问了,因为这个回答似乎什 ...

  10. 【jmeter】jmeter之-聚合点

    集合点:简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念,我们可以在需要压力的地方设置集合点, 还拿那个用户和密码的地方,每到输入用户 ...