《CUDA高性能并行计算》----2.2 需要知道的CUDA API和C语言拓展

简介: CUDA并行所需要的基本任务包含以下几点: 使用特定的网格维度加载核函数(线程块和线程的数目)。 明确哪些函数编译后运行在设备(GPU)上、主机(CPU)上,或者两者之上。 访问和运用线程块和线程的计算索引值。 分配内存和传输数据。

本 节 书 摘 来 自 华 章 出 版 社 《CUDA高性能并行计算》 一 书 中 的 第2章,第2.2节, 作 者 CUDA for Engineers: An Introduction to High-Performance Parallel Computing[美] 杜安·斯托尔蒂(Duane Storti)梅特·尤尔托卢(Mete Yurtoglu) 著,苏统华 项文成 李松泽 姚宇鹏 孙博文 译 , 更 多 章 节 内 容 可 以 访 问 云 栖 社 区 “华 章 计 算 机” 公 众 号 查 看。

2.2 需要知道的CUDA API和C语言拓展

CUDA并行所需要的基本任务包含以下几点:

使用特定的网格维度加载核函数(线程块和线程的数目)。

明确哪些函数编译后运行在设备(GPU)上、主机(CPU)上,或者两者之上。

访问和运用线程块和线程的计算索引值。

分配内存和传输数据。

让我们从介绍核函数的加载开始。正如上面讨论的,核函数是一种特殊的函数,加载核函数与常规的函数调用看起来很像,详细来说,加载核函数从一个函数名开始,比如aKernel,然后以一个包含了以逗号分开的参数列表的括号结尾。现在我们来看一下编程语言拓展:为了自然地表达并行并且声明计算网格,在函数名和含有参数的括号中间加入了网格的维度和线程块的维度(被放在三个尖括号中):

需要注意的是,Dg、网格中的线程块数和Db、线程块中的线程数目,一起组成了加载核函数中的执行配置和维度的声明。

这构成了加载一个和函数的语法,但是如何声明一个从主机端调用但是在设备端执行的函数仍有一些疑问。CUDA使用在函数前面添加下面的一个函数标识符来作为区分:

__global__是标志着和函数的标识符(可以在主机端调用并在设备端执行)。

__host__函数从主机端调用在主机端执行。(这是一个默认的限定符,通常被省略。)

__device__函数从设备端调用并在设备端执行。(从核函数中调用的函数需要有__device__限定符。)

在函数头添加__host____device__函数会让系统分别编译这个函数的主机版本和设备版本。


68428a2f88b07d466995c0c115ce6046f1ba8eaa

核函数有几个值得注意的权限和限制:
核函数不能带有返回值,因此返回类型通常为void。并且核函数需如下声明:

核函数提供了对于每一个线程块和线程的维度数和索引变量。

维度数目变量:
gridDim声明了网格中的线程块数目。

blockDim声明了每个线程块中的线程数目。

索引变量:
blockIdx给出了这个线程块在网格中的索引。

threadIdx给出了这个线程在线程块中的索引。

在GPU上执行的核函数通常不能访问主机端CPU可以访问的内存中的数据。


c8d8b99a681345ab708d77051d19ae3ed8dc1c8e

CUDA运行时API提供了一些可以将输入数据传输到设备端和将结果传回到主机端的函数,如下所示:

cudaMalloc()函数可以分配设备端内存。

cudaMemcpy()将数据传入或传出设备。

cudaFree()释放掉设备中不再使用的内存。

核函数并行进行多次运算,但是它们也放弃了对执行顺序的控制。CUDA为需要同步和并发执行时提供了相应的函数:

__syncThreads()可以在一个线程块中进行线程同步。

cudaDeviceSynchronize()函数可以有效地同步一个网格中的所有线程。

原子操作,例如atomicAdd(),可以防止多线程并发访问一个变量时造成的冲突。

除了上文介绍的函数和标识符以外,CUDA同时提供了一些额外的有用的数据类型:

size_t:代表内存大小的专用变量类型。

cudaError_t:错误处理的专用变量。

向量类型:CUDA将标准C的向量数据类型拓展到了4个。独立的组件通过后缀.x、.y、.z和.w进行访问。


379962e59cdf64eb114769d3cc935ec74544257c
相关文章
|
5月前
|
人工智能 自然语言处理 搜索推荐
WordPress AI 原创文章自动生成插件,新增自定义生成图片API功能,支持自定义99%的生图API,拓展性超强
这是一款功能强大的WordPress AI原创文章自动生成插件,支持两种智能生成模式:传统自动方式和懒人智能方式。通过AI生成长尾关键词、多语言文章、动态化标题与内容结构,优化SEO效果,去AI特征,吸引更多点击。插件可自动生成配图、TAG标签及摘要,支持24小时无人值守自动化生成文章,并提交至各大搜索引擎。同时提供关键词管理、定时任务、API集成等功能,兼容主流AI模型,助力网站内容创作与SEO优化。适合个人站长及企业用户提升内容生产力。
|
8月前
|
缓存 NoSQL Java
自研一套高性能API网关,你都需要做什么?
本文介绍了自研API网关的基本组成和架构,涵盖网关的作用、请求生命周期、功能点详解(如插件和规则)、技术选型(Java、Netty、Nacos)及设计要点。通过异步化设计、缓存、串行化优化、提高吞吐量和合理配置工作线程,确保高性能与稳定性。最后,提供了网关的架构图,帮助读者全面理解其构建过程。
414 0
|
10月前
|
SQL 缓存 测试技术
构建高性能RESTful API:最佳实践与避坑指南###
—— 本文深入探讨了构建高性能RESTful API的关键技术要点,从设计原则、状态码使用、版本控制到安全性考虑,旨在为开发者提供一套全面的最佳实践框架。通过避免常见的设计陷阱,本文将指导你如何优化API性能,提升用户体验,确保系统的稳定性和可扩展性。 ###
233 12
|
11月前
|
中间件 Go API
使用Go语言构建高性能RESTful API
在现代软件开发中,RESTful API因其简洁和高效而成为构建网络服务的首选。Go语言以其并发处理能力和高性能著称,是开发RESTful API的理想选择。本文将介绍如何使用Go语言构建RESTful API,包括基础的路由设置、中间件的使用、数据验证、错误处理以及性能优化。通过实际代码示例,我们将展示Go语言在API开发中的强大功能和灵活性。
|
Go API 开发者
深入探讨:使用Go语言构建高性能RESTful API服务
在本文中,我们将探索Go语言在构建高效、可靠的RESTful API服务中的独特优势。通过实际案例分析,我们将展示Go如何通过其并发模型、简洁的语法和内置的http包,成为现代后端服务开发的有力工具。
|
缓存 API 数据库
打造高性能后端API:从设计到部署的实战之旅
【8月更文挑战第31天】在数字化时代的浪潮中,后端API成为了连接用户、数据与服务的桥梁。本文将带领读者踏上一段从API设计、开发到部署的旅程,通过实际案例分析,揭示如何构建一个高性能的后端系统。我们将探讨现代后端架构的关键要素,包括RESTful API设计原则、数据库优化技巧、缓存策略、以及容器化部署的实践。文章旨在为开发者提供一套实用的方法论,帮助他们在面对复杂业务需求时,能够设计出既高效又可扩展的后端服务。
|
11月前
|
消息中间件 缓存 API
构建高性能RESTful API的策略与实践
构建高性能RESTful API的策略与实践
109 0
|
存储 缓存 编译器
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(下篇)
scanf处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存进⾏解读。 解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。
350 2
|
存储 C语言
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(上篇)
printf 的作⽤是将参数⽂本输出到屏幕。它名字⾥⾯的 f 代表 format (格式化),表⽰可以定制输出⽂本的格式。
217 1
|
SQL 并行计算 API
Dask是一个用于并行计算的Python库,它提供了类似于Pandas和NumPy的API,但能够在大型数据集上进行并行计算。
Dask是一个用于并行计算的Python库,它提供了类似于Pandas和NumPy的API,但能够在大型数据集上进行并行计算。