CUDA中的常量内存__constant__
GPU包含数百个数学计算单元,具有强大的处理运算能力,可以强大到计算速率高于输入数据的速率,即充分利用带宽,满负荷向GPU传输数据还不够它计算的。CUDA C除全局内存和共享内存外,还支持常量内存,常量内存用于保存在核函数执行期间不会发生变化的数据,使用常量内存在一些情况下,能有效减少内存带宽,降低GPU运算单元的空闲等待。
使用常量内存提升性能
使用常量内存可以提升运算性能的原因如下:
- 对常量内存的单次读操作可以广播到其他的“邻近(nearby)”线程,这将节约15次读取操作;
- 高速缓存。常量内存的数据将缓存起来,因此对于相同地址的连续操作将不会产生额外的内存通信量;
常量内存的声明
常量内存使用示例
#include "cuda_runtime.h"
#include <highgui/highgui.hpp>
#include <time.h>
using namespace cv;
#define INF 2e10f
#define rnd(x) (x*rand()/RAND_MAX)
#define SPHERES 100 //球体数量
#define DIM 1024    //图像尺寸
struct Sphere
{
	float r, g, b;
	float radius;
	float x, y, z;
	__device__ float hit(float ox, float oy, float *n)
	{
		float dx = ox - x;
		float dy = oy - y;
		if (dx*dx + dy*dy < radius*radius)
		{
			float dz = sqrt(radius*radius - dx*dx - dy*dy);
			*n = dz / sqrt(radius*radius);
			return dz + z;
		}
		return -INF;
	}
};
// Sphere *s;
__constant__ Sphere s[SPHERES];
/************************************************************************/
//__global__ void rayTracing(unsigned char* ptr, Sphere* s)
__global__ void rayTracing(unsigned char* ptr)
{
	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 / 2);
	float oy = (y - DIM / 2);
	float r = 0, g = 0, b = 0;
	float maxz = -INF;
	for (int i = 0; i < SPHERES; i++)
	{
		float n;
		float t = s[i].hit(ox, oy, &n);
		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 * 3 + 2] = (int)(r * 255);
	ptr[offset * 3 + 1] = (int)(g * 255);
	ptr[offset * 3 + 0] = (int)(b * 255);
}
/************************************************************************/
int main(int argc, char* argv[])
{
	cudaEvent_t start, stop;
	cudaEventCreate(&start);
	cudaEventCreate(&stop);
	cudaEventRecord(start, 0);
	Mat bitmap = Mat(Size(DIM, DIM), CV_8UC3, Scalar::all(0));
	unsigned char *devBitmap;
	(cudaMalloc((void**)&devBitmap, 3 * bitmap.rows*bitmap.cols));
	//  cudaMalloc((void**)&s, sizeof(Sphere)*SPHERES);  
	Sphere *temps = (Sphere*)malloc(sizeof(Sphere)*SPHERES);
	srand(time(0));  //随机数种子
	for (int i = 0; i < SPHERES; i++)
	{
		temps[i].r = rnd(1.0f);
		temps[i].g = rnd(1.0f);
		temps[i].b = rnd(1.0f);
		temps[i].x = rnd(1000.0f) - 500;
		temps[i].y = rnd(1000.0f) - 500;
		temps[i].z = rnd(1000.0f) - 500;
		temps[i].radius = rnd(100.0f) + 20;
	}
	//  cudaMemcpy(s, temps, sizeof(Sphere)*SPHERES, cudaMemcpyHostToDevice);
	cudaMemcpyToSymbol(s, temps, sizeof(Sphere)*SPHERES);
	free(temps);
	dim3 grids(DIM / 16, DIM / 16);
	dim3 threads(16, 16);
	//  rayTracing<<<grids, threads>>>(devBitmap, s);
	rayTracing << <grids, threads >> > (devBitmap);
	cudaMemcpy(bitmap.data, devBitmap, 3 * bitmap.rows*bitmap.cols, cudaMemcpyDeviceToHost);
	cudaEventRecord(stop, 0);
	cudaEventSynchronize(stop);
	float elapsedTime;
	cudaEventElapsedTime(&elapsedTime, start, stop);
	printf("Processing time: %3.1f ms\n", elapsedTime);
	imshow("CUDA常量内存使用示例", bitmap);
	waitKey();
	cudaFree(devBitmap);
	//  cudaFree(s);
	return 0;
}CUDA中的常量内存__constant__的更多相关文章
- GPU CUDA常量内存使用
		#include <cuda.h> #include <stdio.h> int getMulprocessorCount(){ cudaDeviceProp prop; cu ... 
- 《GPU高性能编程CUDA实战》第六章 常量内存
		▶ 本章介绍了常量内存的使用,并给光线追踪的一个例子.介绍了结构cudaEvent_t及其在计时方面的使用. ● 章节代码,大意是有SPHERES个球分布在原点附近,其球心坐标在每个坐标轴方向上分量绝 ... 
- CUDA: 常量内存与事件
		常量内存: 常量内存用于保存在核函数执行期间不会发生变化的数据,在变量面前添加 __constant__ 修饰符: __constant__ Sphere s[SPHERES]; cudaMe ... 
- CUDA中多维数组以及多维纹理内存的使用
		纹理存储器(texture memory)是一种只读存储器,由GPU用于纹理渲染的图形专用单元发展而来,因此也提供了一些特殊功能.纹理存储器中的数据位于显存,但可以通过纹理缓存加速读取.在纹理存储器中 ... 
- 【CUDA 基础】5.0 共享内存和常量内存
		title: [CUDA 基础]5.0 共享内存和常量内存 categories: - CUDA - Freshman tags: - 共享内存 - 常量内存 toc: true date: 2018 ... 
- Eclipse中的快捷键快速生成常用代码(例如无参、带参构造,set、get方法),以及Java中重要的内存分析(栈、堆、方法区、常量池)
		(一)Eclipse中的快捷键: ctrl+shift+f自动整理选择的java代码 alt+/ 生成无参构造器或者提升信息 alt+shift+s+o 生成带参构造 ctrl+shift+o快速导 ... 
- cuda学习3-共享内存和同步
		为什么要使用共享内存呢,因为共享内存的访问速度快.这是首先要明确的,下面详细研究. cuda程序中的内存使用分为主机内存(host memory) 和 设备内存(device memory),我们在这 ... 
- GPU编程自学7 —— 常量内存与事件
		深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ... 
- CUDA中关于C++特性的限制
		CUDA中关于C++特性的限制 CUDA官方文档中对C++语言的支持和限制,懒得每次看英文文档,自己尝试翻译一下(没有放lambda表达式的相关内容,太过于复杂,我选择不用).官方文档https:// ... 
随机推荐
- 设计模式--单例模式之Lock
			1.为什么用Lock及关键知识 当我们使用线程的时候,效率最高的方式当然是异步,即个个线程同时运行,其间互不依赖和等待.当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进 ... 
- struts2笔记---struts2的执行过程
			1.服务器启动: 加载项目web.xml 创建struts核心过滤器对象,执行filter-->init() struts-default.xml 核心功能的初始化 struts-plu ... 
- HDU 1997汉诺塔VII
			又是汉诺塔~ 回顾一下汉诺塔的移动过程. 从左到右设为A,B,C 3个盘子的时候 1: No.1 A -> C 2: No.2 A -> B 3: No.1 C -> B 4 ... 
- OC学习篇之---协议的概念和用法
			这一篇文章我们在来看一下OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Java中的接口(抽象类),只不过OC中的名字 ... 
- 【u252】泽泽在巴西
			Time Limit: 1 second Memory Limit: 128 MB [问题描述] 泽泽帮助了英国某街道尽量减少酸雨的伤害,街道办主任非常感激他,就把他领到一扇门前,告诉他这扇门能通往好 ... 
- Java反射机制的简单应用
			一直感觉java的反射机制非常强大,可是可用的地方不多.在android学习的时候.一直想实现挂断电话的功能,可是系统并没有提供开放的api接口,看了一下网上使用反射机制来实现该功能,确实非常强大,非 ... 
- stm32的电源
			有人说rtc会不工作 
- HDU 3791 二叉搜索树 (数据结构与算法实验题 10.2 小明)  BST
			传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3791 中文题不说题意. 建立完二叉搜索树后进行前序遍历或者后序遍历判断是否一样就可以了. 跟这次的作业第 ... 
- 通过onTouch来确定点击的是listView哪一个item
			事实上这主要是用了ListView的一个方法,通过坐标就能够确定当前是哪一个listView,别的我就不多说了直接看看代码吧, lv_flide.setOnTouchListener(new OnTo ... 
- 【编程】常见概念的理解 —— inplace、vanity url、vanilla(code/software)、编译、链接、build、(delegate、proxy)
			inplace: 如修改一个文件等对象时, inplace=True,不创建新的对象,直接在原始对象上尽心修改: inplace=False,在对原始对象进行修改,而会创建新的对象: vanity u ... 
