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

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

 #include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "D:\Code\CUDA\book\common\book.h"
#include "D:\Code\CUDA\book\common\cpu_bitmap.h" #define DIM 1024
#define rnd( x ) (x * rand() / RAND_MAX)
#define INF 2e10f
#define SPHERES 40
#define USE_CONSTANT_MEMORY false struct Sphere
{
float r, b, g;
float radius;
float x, y, z;
__device__ float hit(float ox, float oy, float *n)//计算球体上一点处的法向量n并返回该点到画面平面的距离
{
float dx = ox - x;
float dy = oy - y;
if (dx*dx + dy*dy < radius*radius)
{
float dz = sqrtf(radius*radius - dx*dx - dy*dy);
*n = dz / sqrtf(radius * radius);//球上该点法向量与画面法向量夹角的余弦值
return dz + z;
}
return -INF;
}
}; #if USE_CONSTANT_MEMORY
__constant__ Sphere s[SPHERES];
struct DataBlock
{
unsigned char *dev_bitmap;
};
#else
struct DataBlock
{
unsigned char *dev_bitmap;
Sphere *s;
};
#endif #if USE_CONSTANT_MEMORY
__global__ void kernel(unsigned char *ptr)
#else
__global__ void kernel(Sphere *s, unsigned char *ptr)
#endif
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x;
float ox = (x - DIM / );
float oy = (y - DIM / ); float r = , g = , b = ;//计算该像素应该显示什么颜色
float maxz = -INF;
for (int i = ; i<SPHERES; i++)
{
float n;
float t = s[i].hit(ox, oy, &n);//o理解成"observation",即当前线程代表的坐标
if (t > maxz)//距离画面最近,更新该像素的显示
{
float fscale = n;
r = s[i].r * fscale;
g = s[i].g * fscale;
b = s[i].b * fscale;
maxz = t;
}
} ptr[offset * + ] = (int)(r * );
ptr[offset * + ] = (int)(g * );
ptr[offset * + ] = (int)(b * );
ptr[offset * + ] = ; return;
} int main(void)
{
DataBlock data;
cudaEvent_t start, stop;// 计时器
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, ); CPUBitmap bitmap(DIM, DIM, &data);
unsigned char *dev_bitmap;
#if !USE_CONSTANT_MEMORY
Sphere *s;
#endif
cudaMalloc((void**)&dev_bitmap,bitmap.image_size());
cudaMalloc((void**)&s,sizeof(Sphere) * SPHERES);
Sphere *temp_s = (Sphere*)malloc(sizeof(Sphere) * SPHERES); for (int i = ; i<SPHERES; i++)
{
temp_s[i].r = rnd(1.0f);
temp_s[i].g = rnd(1.0f);
temp_s[i].b = rnd(1.0f);
temp_s[i].x = rnd(1000.0f) - ;
temp_s[i].y = rnd(1000.0f) - ;
temp_s[i].z = rnd(1000.0f) - ;
temp_s[i].radius = rnd(100.0f) + ;
} #if USE_CONSTANT_MEMORY
cudaMemcpyToSymbol(s, temp_s, sizeof(Sphere) * SPHERES);
kernel << < dim3(DIM / , DIM / ), dim3(, ) >> > (dev_bitmap);
#else
cudaMemcpy(s, temp_s, sizeof(Sphere) * SPHERES, cudaMemcpyHostToDevice);
kernel << < dim3(DIM / , DIM / ), dim3(, ) >> > (s, dev_bitmap);
#endif cudaMemcpy(bitmap.get_ptr(), dev_bitmap,bitmap.image_size(),cudaMemcpyDeviceToHost); cudaEventRecord(stop, );//测量计算耗时
cudaEventSynchronize(stop);
float elapsedTime;
cudaEventElapsedTime(&elapsedTime,start, stop);
printf("Time to generate: %3.1f ms\n", elapsedTime);
cudaEventDestroy(start);
cudaEventDestroy(stop); free(temp_s);
cudaFree(dev_bitmap);
cudaFree(s); bitmap.display_and_exit(); getchar();
return;
}

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

 cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop); cudaEventRecord(start, ); //Do something cudaEventRecord(stop, );
cudaEventSynchronize(stop); float elapsedTime;
cudaEventElapsedTime(&elapsedTime, start, stop);
cudaEventDestroy(start);
cudaEventDestroy(stop);

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

 template<class T>
static __inline__ __host__ cudaError_t cudaMemcpyToSymbol(
const T &symbol,
const void *src,
size_t count,
size_t offset = ,
enum cudaMemcpyKind kind = cudaMemcpyHostToDevice)
{
return ::cudaMemcpyToSymbol((const void*)&symbol, src, count, offset, kind);
}

《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. oracle--分组后获取每组数据第一条数据

    SELECT * FROM (SELECT ROW_NUMBER() OVER(PARTITION BY cc.queuename ORDER BY cc.enroldate DESC) rn, cc ...

  2. <亲测>阿里云centos7 挂载数据盘配置

    阿里云centos7 挂载数据盘配置 2018年07月17日 15:13:53 阅读数:235更多 个人分类: linux阿里云ECS数据盘挂载   查看磁盘情况 fdisk -l  其中/dev/v ...

  3. Microsoft.NET.Framework开机报错解决方法

    win10自动更新后每次开机都报错Microsoft.NET.Framework. 如下图所示: 网上查了各种各样的方法折腾了好久. 其中看到了这样一个回答 “有两种可能 你电脑里的某个软件需要使用M ...

  4. ALGO-39_蓝桥杯_算法训练_数组排序去重

    问题描述 输入10个整数组成的序列,要求对其进行升序排序,并去掉重复元素. 输入格式 10个整数. 输出格式 多行输出,每行一个元素. 样例输入 样例输出 解题思路: 若输入的数字存在数组中,剔除,否 ...

  5. Android兼容包之MultiDex

    一.MultiDex的产生背景 当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt.DexOpt的执行过程是在第一次加载Dex文件的时候执 ...

  6. Hadoop 管理工具HUE配置-集成Unix用户和用户组

    HUE安装完成之后,第一次登录的用户就是HUE的超级用户,可以管理用户,等等.但是在用的过程发现一个问题这个用户不能管理HDFS中由supergroup创建的数据. 虽然在HUE中创建的用户可以管理自 ...

  7. vc++获取网页源码之使用import+智能指针包装类

    创建基于对话框的mfc应用程序 使用智能指针包装类IWinHttpRequestptr,它内部采用的是引用计数来管理对象的生命周期 代码: #import "C:\\Windows\\Sys ...

  8. 1.汇编指令介绍(arm)

    本文作为本人学习过程中的记录及时不时的突发奇想偶记.鄙人菜鸟一只,文中如有错误或疏漏,若读者肯不吝赐教,在下感激零涕.文章一直不断更新中 一.汇编语言 汇编语言是一种应用计算机.微处理器.微控制器或其 ...

  9. 学习笔记之Gurobi

    Gurobi Optimization - The State-of-the-Art Mathematical Programming Solver http://www.gurobi.com/ind ...

  10. [C#][EF] 添加表添加不进来

    确认此表有没有主键,没有主键时就会这样.