CUDA学习笔记(十四) Constant Memory
转载至https://www.cnblogs.com/1024incn/tag/CUDA/
CONSTANT MEMORY
constant Memory对于device来说只读但是对于host是可读可写。constant Memory和global Memory一样都位于DRAM,并且有一个独立的on-chip cache,比直接从constant Memory读取要快得多。每个SM上constant Memory cache大小限制为64KB。
constant Memory的获取方式不同于其它的GPU内存,对于constant Memory来说,最佳获取方式是warp中的32个thread获取constant Memory中的同一个地址。如果获取的地址不同的话,只能串行的服务这些获取请求了。
constant Memory使用__constant__限定符修饰变量。
constantMemory的生命周期伴随整个应用程序,并且可以被同一个grid中的thread和host中调用的API获取。因为constant Memory对device来说是可读的,所以只能在host初始化,使用下面的API:
cudaError_t cudaMemcpyToSymbol(const void *symbol, const void * src, size_t count, size_t offset, cudaMemcpyKind kind)
Implementing a 1D Stencil with Constant Memory
实现一个1维Stencil(数值分析领域的东,卷积神经网络处理图像的时候那个stencil),简单说就是计算一个多项式,系数放到constant Memory中,即y=f(x)这种东西,输入是九个点,如下:
{x − 4h, x − 3h, x − 2h, x − h, x, x + h, x + 2h, x + 3h, x + 4h}
在内存中的过程如下:

公式如下:
![]()
那么要放到constant Memory中的便是其中的c0、c1、c2 ……
因为每个thread使用九个点来计算一个点,所以可以使用shared memory来降低延迟。
__shared__ float smem[BDIM + 2 * RADIUS];
RADIUS定义了x两边点的个数,对于本例,RADIUS就是4。如下图所示,每个block需要RADIUS=4个halo(晕)左右边界:

#pragma unroll用来告诉编译器,自动展开循环。
![]()
View Code
Comparing with the Read-only Cache
Kepler系列的GPU允许使用texture pipeline作为一个global Memory只读缓存。因为这是一个独立的使用单独带宽的只读缓存,所以对带宽限制的kernel性能有很大的提升。
Kepler的每个SM有48KB大小的只读缓存,一般来说,在读地址比较分散的情况下,这个只读缓存比L1表现要好,但是在读同一个地址的时候,一般不适用这个只读缓存,只读缓存的读取粒度为32比特。
有两种方式来使用只读缓存:
- 使用__ldg限定
- 指定特定global Memory称为只读缓存
下面代码片段对于第一种情况:
__global__ void kernel(float* output, float* input) {...output[idx] += __ldg(&input[idx]);...
}
下面代码对应第二种情况,使用__restrict__来指定该数据的要从只读缓存中获取:
void kernel(float* output, const float* __restrict__ input) {...output[idx] += input[idx];
}
一般使用__ldg是更好的选择。通过constant缓存存储的数据必须相对较小而且必须获取同一个地址以便获取最佳性能,相反,只读缓存则可以存放较大的数据,且不必地址一致。
下面的代码是之前stencil的翻版,使用过了只读缓存来存储系数,二者唯一的不同就是函数的声明:
![]()
View Code
由于系数原本是存放在global Memory中的,然后读进缓存,所以在调用kernel之前,我们必须分配和初始化global Memory来存储系数,代码如下:
const float h_coef[] = {a0, a1, a2, a3, a4};
cudaMalloc((float**)&d_coef, (RADIUS + 1) * sizeof(float));
cudaMemcpy(d_coef, h_coef, (RADIUS + 1) * sizeof(float), cudaMemcpyHostToDevice);
下面是运行在TeslaK40上的结果,从中可知,使用只读缓存性能较差。
Tesla K40c array size: 16777216 (grid, block) 524288,32 3.4517ms stencil_1d(float*, float*) 3.6816ms stencil_1d_read_only(float*, float*, float const *)
总的来说,constant缓存和只读缓存对于device来说,都是只读的。二者都有大小限制,前者每个SM只能有64KB,后者则是48KB。对于读同一个地址,constant缓存表现好,只读缓存则对地址较分散的情况表现好。
The Warp Shuffle Instruction
之前我们有介绍shared Memory对于提高性能的好处,在CC3.0以上,支持了shuffle指令,允许thread直接读其他thread的寄存器值,只要两个thread在 同一个warp中,这种比通过shared Memory进行thread间的通讯效果更好,latency更低,同时也不消耗额外的内存资源来执行数据交换。
这里介绍warp中的一个概念lane,一个lane就是一个warp中的一个thread,每个lane在同一个warp中由lane索引唯一确定,因此其范围为[0,31]。在一个一维的block中,可以通过下面两个公式计算索引:
laneID = threadIdx.x % 32
warpID = threadIdx.x / 32
例如,在同一个block中的thread1和33拥有相同的lane索引1。
Variants of the Warp Shuffle Instruction
有两种设置shuffle的指令:一种针对整型变量,另一种针对浮点型变量。每种设置都包含四种shuffle指令变量。为了交换整型变量,使用过如下函数:
int __shfl(int var, int srcLane, int width=warpSize);
该函数的作用是将var的值返回给同一个warp中lane索引为srcLane的thread。可选参数width可以设置为2的n次幂,n属于[1,5]。
eg:如果shuffle指令如下:
int y = shfl(x, 3, 16);
则,thread0到thread15会获取thread3的数据x,thread16到thread31会从thread19获取数据x。
当传送到shfl的lane索引相同时,该指令会执行一次广播操作,如下所示:

另一种使用shuffle的形式如下:
int __shfl_up(int var, unsigned int delta, int width=warpSize)
该函数通过使用调用方的thread的lane索引减去delta来计算源thread的lane索引。这样源thread的相应数据就会返回给调用方,这样,warp中最开始delta个的thread不会改变,如下所示:

第三种shuffle指令形式如下:
int __shfl_down(int var, unsigned int delta, int width=warpSize)
该格式是相对__shfl_down来说的,具体形式如下图所示:

最后一种shuffle指令格式如下:
int __shfl_xor(int var, int laneMask, int width=warpSize)
这次不是加减操作,而是同laneMask做抑或操作,具体形式如下图所示:

所有这些提及的shuffle函数也都支持单精度浮点值,只需要将int换成float就行,除此外,和整型的使用方法完全一样。
相关文章:
CUDA学习笔记(十四) Constant Memory
转载至https://www.cnblogs.com/1024incn/tag/CUDA/ CONSTANT MEMORY constant Memory对于device来说只读但是对于host是可读可写。constant Memory和global Memory一样都位于DRAM,并且有一个独立的on-chip cache,比直接从constant Memory读取要快得多…...
使用MFC创建一个SaleSystem
目录 1、项目的创建: 2、项目的配置: 3、设置窗口属性: (1)、设置图标 1)、添加导入资源 2)、代码初始化图标 (2)、设置标题 (3)、设置窗口…...
grafana v10.1版本设置告警
1. 相关概念概述 如图所示,点击切换菜单标志,可以看到警报相关子选项。 警报规则:通过PromQL语句定义告警规则,即达到怎样的状态触发告警。 联络点: 设置当警报规则实例触发时,如何通知联系人,…...
Python+Requests+PyTest+Excel+Allure 接口自动化测试实战
本文主要介绍了PythonRequestsPyTestExcelAllure 接口自动化测试实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 Unittest是Python标准库中自带的单元测试框架…...
日志分析系统——ELK
目录 一、ELK概述 ELK的组成 1、ElasticSearch 2、Logstash 3、Kiabana 完整日志采集系统基本特征 ELK的工作原理 二、ELK的部署 1、环境准备 2、部署ElasticSearch软件 3、安装Elasticsearch-head插件 4、Logstash部署 5、Kibana部署 三、FilebeatELK部署 1、安…...
Ubuntu小知识总结
Ubuntu相关的小知识总结 一、Ubuntu系统下修改用户开机密码二、Vmware虚拟机和主机之间复制、粘贴内容、拖拽文件的详细方法问题描述Vmware tools灰色不能安装解决方法小知识点:MarkDown的空格 三、Ubuntu虚拟机网络无法连接的几种解决方法1.重启网络编辑器2. 重启虚…...
2023年全球市场新能源汽车车载充电器总体规模、主要生产商、主要地区、产品和应用细分研究报告
按收入计,2022年全球新能源汽车车载充电器收入大约 百万美元,预计2029年达到 百万美元,2023至2029期间,年复合增长率CAGR为 %。同时2022年全球新能源汽车车载充电器销量大约 ,预计2029年将达到 。2022年中国市场规模大…...
基于stm32控制的ESP8266在设备模式下通讯
一、文章中要用的指令 指令作用ATUART115200,8,1,0,0之前的51通讯是9600,这里的321用的是115200,需要改一下波特率ATCWMODEXX是1代表station(设备)模式 ,X是2代表AP(路由)模式 ,X是…...
用PHP组合数组,生成笛卡尔积。写几个例子
#创作灵感# [红色,白色,黄色,蓝色] [128G,256G,512G] [国行,港版,美版,韩版] 用PHP组合数组,生成笛卡尔积。写几个例子 你可以使用嵌套的循环来生成这些数组的笛卡尔积。以下是一些示例代码: // 示例…...
软设上午题错题知识点7
软设上午题错题知识点7 1、数据流图摆脱系统的物理内容,在逻辑上描述系统的功能、输入、输出和数据存储等,是系统逻辑模型的重要组成部分。 2、HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议。 它是一个安全通信…...
让uniGUI支持https
今天在专家的帮助下,成功的让uniGUI支持https了。 首先,去申请个**的证书。我同事去阿里申请的,申请回是一个zip文件,里面有两个文件,一个扩展是per,一个key 然后,把这两个证书文件放到uniGUI…...
iPhone怎么导出微信聊天记录?3个值得收藏的方法
随着时间的推移,微信占用的内存空间会“膨胀”得越来越大。当手机内存不足时,清理微信中的聊天记录是一个可行的方法。但是很多小伙伴觉得有些重要的聊天记录还有用,可能以后需要进行查看。 因此,他们想将一些聊天记录进行导出或…...
【Proteus仿真】【STM32单片机】自动饲养控制系统
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用LCD1604显示模块、红外传感器、有害气体检测模块、PCF8591 ADC模块,蜂鸣器、DHT11温湿度、SG90舵机、风扇加热加湿等。 主要功能&a…...
【设计模式】模板方法模式
模板方法模式 1. 什么是模板方法 模板方法模式:定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构来重定义该算法的 2. 什么时候使用模板方法 实现一些操作时,…...
c语言进制的转换二进制转换10进制
c语言进制的转换之二进制转换10进制 c语言的进制的转换 c语言进制的转换之二进制转换10进制一、二进制转换10进制的方法二、10进制程序打印 一、二进制转换10进制的方法 二进制: 二进制逢二进一,所有的数组是0、1组成 十进制转二进制: 除二反…...
C++ 纠错题总结2
1、for循环中的判断语句: 要注意初始赋值、< 还是 < for(int i 0; i < n; i) 2、cin.getline(char[], int, char) 注意:第二个参数为不是char[]的有效元素个数,因为最后一个元素位置要用来存储 \0 3、函数形参有默认值的,有默认…...
Jmeter性能 —— 事务控制器
统计性能测试结果一定会关注TPS,TPS表示:每秒处理事务数,JMeter默认每个事务对应一个请求。我们可以用逻辑控制器中的事务控制器将多个请求统计为一个事务。 1、添加事务控制器 2、事务控制器参数说明 Generate parent sample:如…...
Android C/C++ native编程NDK开发中logcat的使用
Android C/C native编程NDK开发中logcat的使用 前言具体用法 前言 在NDK开发过程中,C/C层,需要对代码进行一些调试,日志打印是我们解决异常或崩溃的重要手段,这里我就简单介绍下日志打印三步走。 首先我们先看下官方文档关于日志…...
什么是美颜SDK?深入了解直播实时美颜SDK
美颜已经成为了现代社交媒体和直播应用中的重要元素,它使用户能够在拍摄自拍照片或进行直播时改善其外貌特征。美颜技术的普及离不开美颜SDK(软件开发工具包),特别是在直播应用中,直播实时美颜SDK正变得越来越流行。在…...
TensorFlow2从磁盘读取图片数据集的示例(tf.data.Dataset.list_files)
import os import warnings warnings.filterwarnings("ignore") import tensorflow as tf from tensorflow.keras.optimizers import Adam from tensorflow.keras.applications.resnet import ResNet50 from pathlib import Path import numpy as np#数据所在文件夹 …...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
