CUDA by example Chapter6 常量内存与事件

一种车内UWB圆极化天线的理论推导及具体实现 本文详细描述了一款工作于UWB channel 9也即中心频率为7987.2MHz,带宽为499.2MHz的圆极化天线。首先是理论推导圆极化天线的物理尺寸参数,分析物理尺寸参数对天线性能指标的影响。然后分析圆极化天线在汽车驾驶室这种狭窄空间应用中带来的优势,也即可以最大化的极化损失多径,提高主径接收信号的信噪比。 阅读详情

常量内存

使用常量内存的原因:
GPU中含有数量庞大的计算单元,因此性能瓶颈通常并不在于芯片的数学计算吞吐量,而是在于芯片的内存带宽。
在某些情况下,使用常量内存可以显著减少内存通信量

光线跟踪

光信跟踪是从三维对象场景中生成二维图像的一种方式。将跟踪从像素中投射出的光线穿过场景,直到光线命中某个物体,然后计算这个像素的颜色。

在GPU上实现光线追踪

  1. 构建球面数据结构
struct Sphere
{
	float r, g, b;//颜色值
	float radius;//半径
	float x, y, z;//球心坐标
	//运行在GPU上的函数,计算相机到光线命中球面处的距离
	__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 = sqrtf(radius*radius - dx*dx - dy*dy);
			*n = dz / sqrtf(radius*radius);
			return z + dz;
		}
		return -INF;
	}
};

其中方法hit(float ox,float oy,float *n)对来自(ox,oy)处像素的光线,计算光线是否与这个球面相交。如果光线与球面相交,这个方法将计算从相机到光线命中球面处的距离。当光线命中多个球面时,由于遮挡,只有最接近相机的球面才会被看见。
详细解释示意图:
在这里插入图片描述
在这里插入图片描述
之所以return dz+z是因为:去前球面的距离与取后球面的距离,本质上并没有什么差别。所以return dz+z和return -dz+z效果应该是一样的。

2. 思路说明
先随机生成一些球,然后在核函数中,对每个像素都遍历一遍这些球,找到最短的hit距离,根据这个hit距离与其球心的距离差值,确定这个像素的透明度,然后根据球的颜色和计算出的像素透明度对图像着色。

3.完整代码

// 代码6.2.2在GPU上实现光线跟踪
//时间:2019.07.28
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include "cpu_bitmap.h"

#define INF 2e10f
#define SPHERES 20
#define DIM 1024
#define rnd(x) (x*rand()/RAND_MAX)



struct Sphere
{
	float r, g, b;//颜色值
	float radius;//半径
	float x, y, z;//球心坐标
	//运行在GPU上的函数,计算相机到光线命中球面处的距离
	__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 = sqrtf(radius*radius - dx*dx - dy*dy);
			*n = dz / sqrtf(radius*radius);
			return z + dz;
		}
		return -INF;
	}
};

struct DataBlock
{
	unsigned char *dev_bitmap;
	Sphere *s;
};




__global__ void kernal(Sphere *s,unsigned char *ptr)
{
	//将threadIDX/blockIdx映射到像素位置
	int x = threadIdx.x + blockIdx.x*blockDim.x;
	int y = threadIdx.y + blockIdx.y*blockDim.y;
	int offset = x + y*DIM;
	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 * 4 + 0] = (int)(r * 255);
	ptr[offset * 4 + 1] = (int)(g * 255);
	ptr[offset * 4 + 2] = (int)(b * 255);
	ptr[offset * 4 + 3] = 255;

}


int main()
{
	DataBlock data;
	//记录起始时间
	cudaEvent_t start, stop;
	cudaEventCreate(&start);
	cudaEventCreate(&stop);
	cudaEventRecord(start, 0);

	CPUBitmap bitmap(DIM, DIM, &data);
	unsigned char *dev_bitmap;
	Sphere *s;

	//在GPU上分配内存以计算输出位图
	cudaMalloc((void **)&dev_bitmap, bitmap.image_size());

	//为Sphere数据集分配内存
	cudaMalloc((void **)&s, sizeof(Sphere)*SPHERES);

	//在CPU上分配Shpere的临时内存,对其初始化,并复制到GPU内存中,然后释放CPU的临时内存
	Sphere *temp_s = (Sphere *)malloc(sizeof(Sphere)*SPHERES);
	for (int i = 0; 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) - 500;
		temp_s[i].y = rnd(1000.0f) - 500;
		temp_s[i].z = rnd(1000.0f) - 500;
		temp_s[i].radius = rnd(100.0f) + 20;
	}
	cudaMemcpy(s, temp_s, sizeof(Sphere)*SPHERES, cudaMemcpyHostToDevice);
	free(temp_s);

	//从球面数据中生成一张位图
	dim3 grids(DIM / 16, DIM / 16);
	dim3 blocks(16, 16);
	kernal << <grids, blocks >> >(s,dev_bitmap);

	//将位图从GPU复制到CPU中
	cudaMemcpy(bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost);

	

	// get stop time, and display the timing results
	cudaEventRecord(stop, 0);
	cudaEventSynchronize(stop);
	float   elapsedTime;
	cudaEventElapsedTime(&elapsedTime,start, stop);
	printf("Time to generate:  %3.1f ms\n", elapsedTime);

	cudaEventDestroy(start);
	cudaEventDestroy(stop);

	//释放GPU内存
	cudaFree(dev_bitmap);
	cudaFree(s);

	//显示
	bitmap.display_and_exit();
}

4. 运行结果(return z+dz)
在这里插入图片描述
在这里插入图片描述
5. 运行结果(return z-dz)
在这里插入图片描述
在这里插入图片描述

通过常量内存来实现光线追踪

1. 常量内存定义
**常量内存是指那些在程序运行过程中不能修改的内存空间。**光线追踪示例中只有一个输入数据,即球面数组,它在程序运行过程中不需要修改,因此将这个数据保存到常量内存中,以期待更少的内存通信量和更高效的运行性能。
2. 常量内存的使用方法
定义方法:
由原来的Sphere *s变成:

__constant__ Sphere s[SPHERES]

分配内存方法:
常量内存的分配不需要调用cudaMalloc()和cudaFree(),而是有专门的copy函数cudaMemcpyToSymbol,这个函数将会把CPU的内存内容copy到GPU中的常量内存中。

cudaMemcpyToSymbol(s,temp_s,sizeof(Sphere)*SPHERES);

其中temp_s是CPU内存指针。
cudaMemcpyToSymbol会复制到常量内存,而cudaMemcpy()会复制到全局内存。

3. 常量内存带来的性能提升
与从全局内存中读取数据相比,从常量内存中读取相同的数据可以节约内存带宽,主要有两个原因:

  • 对常量内存的单次读操作可以广播到其他的"邻近"线程(半个warp),这将节约15次读取操作。在CUDA架构中,线程束是指一个包含32个线程的集合,这个线程集合被"编织在一起"并且"步调一致"的形式执行。
  • 常量内存的数据将缓存起来,因此对相同地址的连续读操作将不会产生额外的内存通信量。

在光线追踪示例中,使用常量内存后,硬件只需要请求这个数据一次。在缓存数据后,其他每个线程将不会产生内存流量,原因有两个:

  • 线程将在半线程束的广播中收到这个数据
  • 从常量内存缓存中收到数据

讨论:
只有当16个线程每次都只需要相同的读取请求时,才值得将这个读取操作广播到16个线程,如果半线程束中的所有16个线程需要访问常量内存中不同的数据,那么这16次不同的读取操作会被串行化,从而需要16倍的时间来发出请求。但如果从全局内存中读取,那么这些请求会同时发出。在这种情况中,从常量内存读取就慢于从全局内存中读取。
4. 完整代码

// 代码6.2.3在GPU上通过常量内存实现光线跟踪
//时间:2019.07.28
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include "cpu_bitmap.h"

#define INF 2e10f
#define SPHERES 20
#define DIM 1024
#define rnd(x) (x*rand()/RAND_MAX)



struct Sphere
{
	float r, g, b;
	float radius;
	float x, y, z;
	//运行在GPU上的函数,计算相机到光线命中球面处的距离
	__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 = sqrtf(radius*radius - dx*dx - dy*dy);
			*n = dz / sqrtf(radius*radius);
			return z + dz;
		}
		return -INF;
	}
};

//Sphere *s;
__constant__ Sphere s[SPHERES];//GPU常量内存大小直接分配



//__global__ void kernal(Sphere *s, unsigned char *ptr)//也不需要在核函数中传入常量内存的地址,常量内存在核函数中可以直接使用
__global__ void kernal(unsigned char *ptr)
{
	//将threadIDX/blockIdx映射到像素位置
	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 * 4 + 0] = (int)(r * 255);
	ptr[offset * 4 + 1] = (int)(g * 255);
	ptr[offset * 4 + 2] = (int)(b * 255);
	ptr[offset * 4 + 3] = 255;

}

struct DataBlock
{
	unsigned char *dev_bitmap;
};

int main()
{
	DataBlock data;
	//记录起始时间
	cudaEvent_t start, stop;
	cudaEventCreate(&start);
	cudaEventCreate(&stop);
	cudaEventRecord(start, 0);

	CPUBitmap bitmap(DIM, DIM,&data);
	unsigned char *dev_bitmap;

	//在GPU上分配内存以计算输出位图
	cudaMalloc((void **)&dev_bitmap, bitmap.image_size());

	//不需要再为Sphere数据集显式分配内存
	//cudaMalloc((void **)&s, sizeof(Sphere)*SPHERES);

	//在CPU上分配Shpere的临时内存,对其初始化,并复制到GPU内存中,然后释放CPU的临时内存
	Sphere *temp_s = (Sphere *)malloc(sizeof(Sphere)*SPHERES);
	for (int i = 0; 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) - 500;
		temp_s[i].y = rnd(1000.0f) - 500;
		temp_s[i].z = rnd(1000.0f) - 500;
		temp_s[i].radius = rnd(100.0f) + 20;
	}
	//cudaMemcpy(s, temp_s, sizeof(Sphere)*SPHERES, cudaMemcpyHostToDevice);
	cudaMemcpyToSymbol(s,temp_s,sizeof(Sphere)*SPHERES);//这将把CPU内存内容copy到GPU的常量内存上
	free(temp_s);

	//从球面数据中生成一张位图
	dim3 grids(DIM / 16, DIM / 16);
	dim3 blocks(16, 16);
	kernal << <grids, blocks >> >(dev_bitmap);

	//将位图从GPU复制到CPU中
	cudaMemcpy(bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost);



	// get stop time, and display the timing results
	cudaEventRecord(stop, 0);
	cudaEventSynchronize(stop);
	float   elapsedTime;
	cudaEventElapsedTime(&elapsedTime, start, stop);
	printf("Time to generate:  %3.1f ms\n", elapsedTime);

	cudaEventDestroy(start);
	cudaEventDestroy(stop);

	//释放GPU内存
	cudaFree(dev_bitmap);
	//cudaFree(s);//因为不需要显式分配常量内存,所以也不需要显式释放常量内存

	//显示
	bitmap.display_and_exit();
}
  1. 运行结果
    在这里插入图片描述
    在这里插入图片描述
    bang!!!性能并没有提升,如果有同学看到这里,想深究原因的,请联系我一起交流讨论

使用事件来测量性能

为了测量GPU在某个任务上花费的时间,我们将使用CUDA的事件API。CUDA中的事件本质上是一个GPU时间戳,获得一个时间戳只需要两个步骤:1.创建一个事件 2.记录一个事件
使用方法:

cudaEvent_t start,stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);

//在GPU上执行一些工作

cudaEventRecord(stop,0);
//同步stop事件,即只有所有线程的stop事件都发生时,才会执行下面的操作。
//当cudaEventSynchronize返回时,表明在stop事件之前的所有GPU工作已经完成了,
//此时可以安全的读取stop中保存的时间戳
cudaEventSynchronize(stop);

//获得结束事件,并显示计时结果
float elapsedTime;
cudaEventElapsedTime(&elapsedTime,start,stop);
printf("Time to generate: %3.1f ms\n",elapsedTime);
//销毁cuda事件
cudaEventDestroy(start);
cudaEventDestroy(stop);

通过常量内存来实现光线追踪一节的完整代码中已经包含了事件的完整代码,这里不再赘述。

第67步 时间序列建模实战:ARIMA建模(Stata) 阅读详情

相关推荐

保姆级教程:在华为MateBook E Go上安装安卓子系统(含Hyper-V配置和地区切换避坑指南)

本文提供在华为MateBook E Go(ARM架构)上安装Windows 11安卓子系统(WSA)的详细指南。重点阐述了ARM平台无需指令转译的流畅原生体验优势,并逐步讲解启用Hyper-V虚拟化、切换系统区域以安装Amazon Appstore、配置开发人员模式及使用ADB安装第三方应用(如华为应用市场)的全过程,助您解锁高效的原生安卓应用生态。

kafka6courier的博客 544

CUDA动态场景的光线追踪+OPENGL实现

角度1:角度2:角度3:可以发现整个物体呈顺时针旋转,启动程序后不停运转;

qq_52299902的博客 970

Java开发者的福音:Aspose 25.10全系列(Cells/Words/PDF/Slides)最新版破解与集成保姆级教程

本文为Java开发者提供了Aspose 25.10全系列组件(Cells/Words/PDF/Slides)的最新版破解与集成保姆级教程。通过详细的Maven依赖配置、字节码修改技术绕过限制,以及Spring Boot项目中的实战集成指南,帮助开发者高效实现Office文档处理功能,提升开发效率。

weixin_30919429的博客 347

光线跟踪=全局内存+常量内存

光线跟踪通过全局内存和常量内存实现,项目打包下载 全局内存 1 /* 2 * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. 3 * 4 * NVIDIA Corporation and its licensors retain all intellectual property and ...

weixin_30341745的博客 169

正点原子RK3588 Android 12镜像构建实战:从环境配置到烧录验证全指南

本文提供了一份基于正点原子RK3588开发板的Android 12镜像构建全流程实战指南。内容涵盖从Ubuntu环境配置、SDK获取、编译内核与系统,到最终镜像打包与烧录验证的完整步骤,并分享了内核驱动定制与系统优化技巧,旨在帮助开发者高效完成瑞芯微RK3588平台的系统定制工作。

grass的博客 812

OData Request:Create Entity 在 ABAP OData Client Proxy 中的工程化实践

文章摘要 本文针对具备 SAP Gateway 与 ABAP 开发经验的读者,详细讲解如何通过 ABAP OData Client Proxy 实现 OData 服务的 Create 操作。首先对比了 OData V2 与 V4 的 Create 规范差异,强调键、集合 URL 和请求体的标准化要求。随后介绍了 ABAP Client Proxy 的编程模型,包括 Client Proxy、Entity List Resource 和 Create Request/Response 三个核心对象,并提供了完

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 247

光线跟踪的 GPU 程序解读

《CUDA by example》 中的第六章讲解了在 GPU 上实现光线跟踪的一个例子,旨在介绍常量内存(constant memory)和事件,下面给出这个例子的详细解读(http://code2.us/2012/02/cuda_learning_11-constant_memory_and_events/)。   #include #include "co

nkliming的专栏 2120

ABAP Cloud define table 里的 not null 究竟在约束什么?——语义、场景与可运行示例

ABAP Cloud 中 not null 与 NULL 的用法解析 本文探讨了 ABAP Cloud 中 not null 关键字的语义与使用场景,对比了传统 ABAP 与 ABAP Cloud 在表字段定义上的差异: 核心概念 not null 是数据库层的列约束,强制字段不能存储 NULL 值 ABAP Cloud 通过 DDL 显式声明列是否允许 NULL,HANA 上 CDS 表默认创建为 NOT NULL 使用建议 主键、外键、审计字段等必须使用 not null 业务上可缺失的字段(如批准日期

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 302

在GPU上实现光线跟踪

#include "cuda.h" #include "book.h" #include "cpu_bitmap.h" #define DIM 1024   //生成图像的大小,DIM*DIM #define SPHERES 20   //生成的图像中球体的个数 #define rnd( x ) (x * rand() / RAND_MAX)    //产生随机数 #define

wufenxia的专栏 1531

人形机器人开源资源大盘点(四):硬件开源平台

开源人形机器人平台推动技术民主化 本期聚焦四大开源人形机器人平台:斯坦福的ToddlerBot以6000美元低成本实现30自由度运动,支持仿真到现实的零样本迁移;法国Reachy2被HuggingFace收购,融合开源AI与硬件,适配医疗、工业等场景;国内OriginMan基于ROS2全开源,集成大模型能力,支持深度改造;OAN框架则为经典NAO机器人注入开源活力,扩展交互功能。这些平台通过不同路径降低研发门槛,推动人形机器人技术走向开放共享的未来。

Studying…… 370

EtherCAT报文-BRD(广播读)抓包分析

EtherCAT报文之BRD(广播读)报文Wireshark抓包分析。

kevin1499的博客 1214

CUDA中的常量内存__constant__

GPU包含数百个数学计算单元,具有强大的处理运算能力,可以强大到计算速率高于输入数据的速率,即充分利用带宽,满负荷向GPU传输数据还不够它计算的。CUDA C除全局内存和共享内存外,还支持常量内存,常量内存用于保存在核函数执行期间不会发生变化的数据,使用常量内存在一些情况下,能有效减少内存带宽,降低GPU运算单元的空闲等待。 使用常量内存提升性能 使用常量内存可以提升运算性能的

牧野的博客 1万+

AI测试干货:Claude Code Skill 从入门到精通

本文介绍了Claude Code Skill功能如何解决AI重复工作问题。传统提示词方式需要人工复制粘贴,而Skill功能通过建立AI工作记忆库实现智能触发和分层加载。Skill包含工作指令、文档和资源,能自动执行任务。文章以API测试用例生成为例,展示了Skill的创建流程和结构化设计,包括测试框架、覆盖场景和输出格式,显著提升测试工程师的工作效率。

blues_C的博客 2445

《CUDA By Example》【Chapter 06】常量内存与事件 ?

6.1 本章目标 高级些的功能,通过GPU上特殊的内存区域来加速应用程序的执行。其中一种内存区域:常量内存(Constant Memory)。介绍一种增强CUDA C应用程序性能的方法,了解如何通过事件来测量应用程序的性能。 如何在CUDA C中使用常量内存 了解常量内存的性能性能 学习使用CUDA事件来测量应用程序的性能 6.2 常量内存 由于GPU有很多ALU, 所以计算能力往...

wondervictor的博客 330

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

CUDA by example Chapter10 流

流为什么要使用CUDA流页锁存主机内存CUDA流使用单个CUDA流使用多个CUDA流GPU工作调度机制高效地使用多个CUDA流 为什么要使用CUDA流 前面章节实现的GPU并行性都是把同一个任务分成可以并行执行的子任务,利用GPU中数量众多的cuda核来实现单个任务的并行性。而如果要实现任务并行性,就需要使用CUDA流来实现。 页锁存主机内存 1. 页锁存内存的概念及用途 页所存内存也称为固定内...

wolfcsharp的博客 336

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

CUDA by example Chapter7 纹理内存

纹理内存纹理内存简介热传导模拟简单的传热模型代码中温度更新的计算GPU不使用纹理内存的热传导模拟计算GPU使用一维纹理内存的热传导模拟计算GPU使用二维纹理内存的热传导模拟计算 纹理内存简介 和常量内存一样,纹理内存是另一种类型的只读内存。纹理内存是专门为那些在内存访问模式中存在大量空间局部性的图形应用程序而设计的。假如在某个计算应用程序中,一个线程读取的位置与邻近线程读取的位置"非常接近",使用...

wolfcsharp的博客 599

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

《CUDA By Example》【Chapter 07】纹理内存 ?

7.1 本章目标 纹理内存和常量内存一样,都是只读内存,用来减少带宽流量,提升性能。 1,了解纹理内存的特性 2,了解如何在CUDA C中使用一维纹理内存 3,了解如何在CUDA C中使用二维纹理内存 7.2 纹理内存简介(Texture Memory) 7.3 热传导模拟...

wondervictor的博客 357

CUDA by example Chapter3 CUDA C简介

CUDA C简介CPU上的Hello WorldGPU上的Hello World__global__修饰符:向kernal()中传递参数cudaMalloc()函数:cudaFree()函数:cudaMemcpy()函数:查询设备信息cudaGetDeviceCount()函数:结构体cudaDevicePropcudaGetDeviceProperties()函数:设备属性的使用:选择一个符合条...

wolfcsharp的博客 394

《CUDA By Example》【Chapter 10】流?

10.1 概述 并行性分数据并行性和任务并行性。GPU是SIMD天生的数据并行,同时也能支持类似于CPU多线程应用程序中的任务并行性。 GPU任务并行性不像CPU上那样灵活,但仍然可以进一步提高GPU上的运行速度。本章,介绍CUDA流,以及如何通过流在GPU上同时执行多个任务。 了解如何分配也锁定(Page-Locked)类型的主机内存 了解CUDA流的概念 了解如何使用CUDA流...

wondervictor的博客 324

CUDA by example Chapter5 线程协作

线程协作并行线程块的分解使用线程实现GPU上的矢量求和 并行线程块的分解 使用线程实现GPU上的矢量求和

wolfcsharp的博客 388

CUDA by example Chapter9 原子性

原子性在CPU上计算直方图在GPU上计算直方图一些重要函数及技巧使用GPU全局内存原子操作计算直方图使用GPU共享内存原子操作计算直方图 与在操作系统中的线程竞争相似,GPU编程各个线程之间也存在竞态条件,为了保证程序按照我们设计的逻辑运行,原子性操作必不可少。 本章以计算直方图为例,说明在GPU上使用原子操作的方法。 在CPU上计算直方图 这是平凡的 // 代码9.4.1在CPU上计算直方图 /...

wolfcsharp的博客 292

《CUDA By Example》【Chapter 05】线程协作 ?

概述 本章介绍代码在各个并行副本之间的通信和协作。 1,了解不同线程之间的通信机制; 2,了解并行执行线程的同步机制; 5.2 并行线程块的分解 add&lt;&lt;&lt;N,1&gt;&gt;&gt;( dev_a, dev_b, dev_c); //第一个参数为想要启动的线程块数量; //第二个参数为CUDA运行时在每个线程块中创建的线程数量; //共创建了N个线程块,N*1...

wondervictor的博客 294

CUDA by example Chapter4 CUDA C并行编程

CUDA C 并行编程CPU矢量求和运算GPU矢量求和运算尖括号语法<<CPU矢量求和运算 /* //代码4.2.1.1基于CPU的矢量求和运算 //时间:2019.07.20 */ #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <iostream> #define N 1...

wolfcsharp的博客 369

CUDA by example Chapter11 多GPU系统上的CUDA C

多GPU系统上的CUDA C零拷贝主机内存通过零拷贝内存实现点积运算零拷贝内存的性能使用多个GPU 零拷贝主机内存 零拷贝主机内存是另一种固定内存,它也不能被CPU从物理内存交换出去或者重新定位。同时,这种内存除了可以用于主机与GPU之间的内存复制外,还可以在CUDA C核函数中直接访问这种类型的主机内存。由于这种内存不需要复制到GPU,因此也称为零拷贝内存。 通过零拷贝内存实现点积运算 1. 测...

wolfcsharp的博客 400

《CUDA By Example》【Chapter 04】CUDA C 并行编程

GPU计算的应用前景在很大程度上取决于能否从很多问题中发掘出大规模并行性。 add_loop_cpu.cu #include &amp;amp;amp;amp;quot;../common/book.h&amp;amp;amp;amp;quot; #define N 10 void add( int *a, int *b, int *c ) { int tid = 0; // this is CPU zero, so we start at ze...

wondervictor的博客 299

《CUDA By Example》【Chapter 11】多GPU系统上的CUDA C?

11.1 概述 了解如何分配和使用零拷贝内存(zero-copy memory) 了解如何在同一个应用程序中使用多个GPU 了解如何分配和使用可移动的固定内存(Portable pinned Memory) 11.2 零拷贝主机内存 固定内存(页锁定内存)能确保不会交换出物理内存。我们通过调用cudaHostAlloc()来分配这种内存,并且传递参数cudaHostAllocDefa...

wondervictor的博客 613
上一篇: CUDA by example Chapter5 线程协作
下一篇: CUDA by example Chapter7 纹理内存
Leo-Ma
博客等级 码龄11年 1701粉丝 124原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值