▶ 本章介绍了常量内存的使用,并给光线追踪的一个例子。介绍了结构cudaEvent_t及其在计时方面的使用。

● 章节代码,大意是有SPHERES个球分布在原点附近,其球心坐标在每个坐标轴方向上分量绝对值不大于500,其半径介于20到120;观察者(画面平面)位于z正半轴充分远处(z>500),现将所有的球体平行投影到画面平面上,考虑遮挡关系,并考虑球面与画面平面的夹角给球体绘制阴影。使用常量内存时球数组定义在所有函数外部,核函数只需图形参数就够了;不使用常量内存时球数组定义在结构DataBlock内部,核函数需要球数组和图形参数。

  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_bitmap.h"
  6.  
  7. #define DIM 1024
  8. #define rnd( x ) (x * rand() / RAND_MAX)
  9. #define INF 2e10f
  10. #define SPHERES 40
  11. #define USE_CONSTANT_MEMORY false
  12.  
  13. struct Sphere
  14. {
  15. float r, b, g;
  16. float radius;
  17. float x, y, z;
  18. __device__ float hit(float ox, float oy, float *n)//计算球体上一点处的法向量n并返回该点到画面平面的距离
  19. {
  20. float dx = ox - x;
  21. float dy = oy - y;
  22. if (dx*dx + dy*dy < radius*radius)
  23. {
  24. float dz = sqrtf(radius*radius - dx*dx - dy*dy);
  25. *n = dz / sqrtf(radius * radius);//球上该点法向量与画面法向量夹角的余弦值
  26. return dz + z;
  27. }
  28. return -INF;
  29. }
  30. };
  31.  
  32. #if USE_CONSTANT_MEMORY
  33. __constant__ Sphere s[SPHERES];
  34. struct DataBlock
  35. {
  36. unsigned char *dev_bitmap;
  37. };
  38. #else
  39. struct DataBlock
  40. {
  41. unsigned char *dev_bitmap;
  42. Sphere *s;
  43. };
  44. #endif
  45.  
  46. #if USE_CONSTANT_MEMORY
  47. __global__ void kernel(unsigned char *ptr)
  48. #else
  49. __global__ void kernel(Sphere *s, unsigned char *ptr)
  50. #endif
  51. {
  52. int x = threadIdx.x + blockIdx.x * blockDim.x;
  53. int y = threadIdx.y + blockIdx.y * blockDim.y;
  54. int offset = x + y * blockDim.x * gridDim.x;
  55. float ox = (x - DIM / );
  56. float oy = (y - DIM / );
  57.  
  58. float r = , g = , b = ;//计算该像素应该显示什么颜色
  59. float maxz = -INF;
  60. for (int i = ; i<SPHERES; i++)
  61. {
  62. float n;
  63. float t = s[i].hit(ox, oy, &n);//o理解成"observation",即当前线程代表的坐标
  64. if (t > maxz)//距离画面最近,更新该像素的显示
  65. {
  66. float fscale = n;
  67. r = s[i].r * fscale;
  68. g = s[i].g * fscale;
  69. b = s[i].b * fscale;
  70. maxz = t;
  71. }
  72. }
  73.  
  74. ptr[offset * + ] = (int)(r * );
  75. ptr[offset * + ] = (int)(g * );
  76. ptr[offset * + ] = (int)(b * );
  77. ptr[offset * + ] = ;
  78.  
  79. return;
  80. }
  81.  
  82. int main(void)
  83. {
  84. DataBlock data;
  85. cudaEvent_t start, stop;// 计时器
  86. cudaEventCreate(&start);
  87. cudaEventCreate(&stop);
  88. cudaEventRecord(start, );
  89.  
  90. CPUBitmap bitmap(DIM, DIM, &data);
  91. unsigned char *dev_bitmap;
  92. #if !USE_CONSTANT_MEMORY
  93. Sphere *s;
  94. #endif
  95. cudaMalloc((void**)&dev_bitmap,bitmap.image_size());
  96. cudaMalloc((void**)&s,sizeof(Sphere) * SPHERES);
  97. Sphere *temp_s = (Sphere*)malloc(sizeof(Sphere) * SPHERES);
  98.  
  99. for (int i = ; i<SPHERES; i++)
  100. {
  101. temp_s[i].r = rnd(1.0f);
  102. temp_s[i].g = rnd(1.0f);
  103. temp_s[i].b = rnd(1.0f);
  104. temp_s[i].x = rnd(1000.0f) - ;
  105. temp_s[i].y = rnd(1000.0f) - ;
  106. temp_s[i].z = rnd(1000.0f) - ;
  107. temp_s[i].radius = rnd(100.0f) + ;
  108. }
  109.  
  110. #if USE_CONSTANT_MEMORY
  111. cudaMemcpyToSymbol(s, temp_s, sizeof(Sphere) * SPHERES);
  112. kernel << < dim3(DIM / , DIM / ), dim3(, ) >> > (dev_bitmap);
  113. #else
  114. cudaMemcpy(s, temp_s, sizeof(Sphere) * SPHERES, cudaMemcpyHostToDevice);
  115. kernel << < dim3(DIM / , DIM / ), dim3(, ) >> > (s, dev_bitmap);
  116. #endif
  117.  
  118. cudaMemcpy(bitmap.get_ptr(), dev_bitmap,bitmap.image_size(),cudaMemcpyDeviceToHost);
  119.  
  120. cudaEventRecord(stop, );//测量计算耗时
  121. cudaEventSynchronize(stop);
  122. float elapsedTime;
  123. cudaEventElapsedTime(&elapsedTime,start, stop);
  124. printf("Time to generate: %3.1f ms\n", elapsedTime);
  125. cudaEventDestroy(start);
  126. cudaEventDestroy(stop);
  127.  
  128. free(temp_s);
  129. cudaFree(dev_bitmap);
  130. cudaFree(s);
  131.  
  132. bitmap.display_and_exit();
  133.  
  134. getchar();
  135. return;
  136. }

● 使用了结构cudaEvent_t用于计时,并介绍了与此相关的时间控制函数,按顺序使用如下。

  1. cudaEvent_t start, stop;
  2. cudaEventCreate(&start);
  3. cudaEventCreate(&stop);
  4.  
  5. cudaEventRecord(start, );
  6.  
  7. //Do something
  8.  
  9. cudaEventRecord(stop, );
  10. cudaEventSynchronize(stop);
  11.  
  12. float elapsedTime;
  13. cudaEventElapsedTime(&elapsedTime, start, stop);
  14. cudaEventDestroy(start);
  15. cudaEventDestroy(stop);

● 使用cudaMemcpyToSymbol()函数复制内存到到常量内存中(可以反向从显存复制到内存中,但由于只读一般没有情况会这样做)。其定义于cuda_runtime.h中

  1. template<class T>
  2. static __inline__ __host__ cudaError_t cudaMemcpyToSymbol(
  3. const T &symbol,
  4. const void *src,
  5. size_t count,
  6. size_t offset = ,
  7. enum cudaMemcpyKind kind = cudaMemcpyHostToDevice)
  8. {
  9. return ::cudaMemcpyToSymbol((const void*)&symbol, src, count, offset, kind);
  10. }

《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实战》第七章 纹理内存

    ▶ 本章介绍了纹理内存的使用,并给出了热传导的两个个例子.分别使用了一维和二维纹理单元. ● 热传导(使用一维纹理) #include <stdio.h> #include "c ...

  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. 1.linux6 x86-64 RPM包安装mysql5.7.20

    注意版本和此次更新时间 2017-12-03  版本:mysql-5.7.20-1.el6.x86_64  环境:linux6.x ​官方下载地址: wget https://dev.mysql.co ...

  2. 什么是词性标注(POS tagging)

    词性标注也叫词类标注,POS tagging是part-of-speech tagging的缩写. 维基百科对POS Tagging的定义: In corpus linguistics, part-o ...

  3. Android 如何让EditText不自动获取焦点 (转)

    在项目中,一进入一个页面, EditText默认就会自动获取焦点. 那么如何取消这个默认行为呢? 在网上找了好久,有点 监听软键盘事件,有点 调用 clearFouse()方法,但是测试了都没有! x ...

  4. ThinkPHP 3.1.2 CURD特性 -3

    一.ThinkPHP 3 的CURD介绍  (了解) 二.ThinkPHP 3 读取数据    (重点) 对数据的读取 Read $m=new Model('User'); $m=M('User'); ...

  5. 黄聪:jquery.bootgrid表格插件有的属性(visibleInSelection、cssClass、headerCssClass、headerAlign)不能识别的解决办法

    主要是属性大小写问题,修改jquery.bootgrid.js文件,在function loadColumns()方法里面添加下面的语句就好了 data.headerAlign = data.head ...

  6. 模拟a标签click,弹出新页面

    $("<a>").attr("href", url).attr("target", "_blank")[0] ...

  7. Hadoop概念学习系列之Java调用Shell命令和脚本,致力于hadoop/spark集群(三十六)

    前言 说明的是,本博文,是在以下的博文基础上,立足于它们,致力于我的大数据领域! http://kongcodecenter.iteye.com/blog/1231177 http://blog.cs ...

  8. 阿里云kubernetes遭入侵pubg进程占用cpu资源100%解决方法

    发现服务器CPU占用100%,通过top命令发现pubg -c config.json -t 2占用CPU资源,kill进程会自动启动.黑客入侵方式是kubernetes创建pod. Name: ku ...

  9. R语言—统计结果输出至本地文件方法总结

    1.sink()在代码开始前加一行:sink(“output.txt”),就会自动把结果全部输出到工作文件夹下的output.txt文本文档.这时在R控制台的输出窗口中是看不到输出结果的.代码结束时用 ...

  10. Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法-un

    ylbtech-Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法 1.返回顶部 1. Java 实例 - 汉诺塔算法  Java 实例 汉诺塔(又称河内塔)问题是源 ...