3.6.共享内存的学习

目录

    • 前言
    • 1. 共享内存
    • 2. shared memory案例
    • 3. 补充知识
    • 总结

前言

杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。

本次课程学习精简 CUDA 教程-共享内存

课程大纲可看下面的思维导图

在这里插入图片描述

1. 共享内存

对于共享内存(shared_memory)你需要知道:

  1. 共享内存因为更靠近计算单元,所以访问速度更快(越近越快,越近越贵
  2. 共享内存通常可以作为访问全局内存的缓存使用
  3. 可以利用共享内存是实现线程间的通信
  4. 通常与 __syncthreads() 同时出现,这个的函数是同步 block 内的所有线程,全部执行到这一行才往下走
  5. 常用方式,通常是在线程 ID 为 0 的时候从 global memory 取值,然后 syncthreads,然后再使用

2. shared memory案例

shared memory 案例的 main.cpp 示例代码如下:


#include <cuda_runtime.h>
#include <stdio.h>#define checkRuntime(op)  __check_cuda_runtime((op), #op, __FILE__, __LINE__)bool __check_cuda_runtime(cudaError_t code, const char* op, const char* file, int line){if(code != cudaSuccess){    const char* err_name = cudaGetErrorName(code);    const char* err_message = cudaGetErrorString(code);  printf("runtime error %s:%d  %s failed. \n  code = %s, message = %s\n", file, line, op, err_name, err_message);   return false;}return true;
}void launch();int main(){cudaDeviceProp prop;checkRuntime(cudaGetDeviceProperties(&prop, 0));printf("prop.sharedMemPerBlock = %.2f KB\n", prop.sharedMemPerBlock / 1024.0f);launch();checkRuntime(cudaPeekAtLastError());checkRuntime(cudaDeviceSynchronize());printf("done\n");return 0;
}

shared memory 案例的 main.cpp 示例代码如下:

#include <cuda_runtime.h>
#include <stdio.h>//demo1 //
/* 
demo1 主要为了展示查看静态和动态共享变量的地址*/
const size_t static_shared_memory_num_element = 6 * 1024; // 6KB
__shared__ char static_shared_memory[static_shared_memory_num_element]; 
__shared__ char static_shared_memory2[2]; __global__ void demo1_kernel(){extern __shared__ char dynamic_shared_memory[];      // 静态共享变量和动态共享变量在kernel函数内/外定义都行,没有限制extern __shared__ char dynamic_shared_memory2[];printf("static_shared_memory = %p\n",   static_shared_memory);   // 静态共享变量,定义几个地址随之叠加printf("static_shared_memory2 = %p\n",  static_shared_memory2); printf("dynamic_shared_memory = %p\n",  dynamic_shared_memory);  // 动态共享变量,无论定义多少个,地址都一样printf("dynamic_shared_memory2 = %p\n", dynamic_shared_memory2); if(blockIdx.x == 0 && threadIdx.x == 0) // 第一个threadprintf("Run kernel.\n");
}/demo2//
/* 
demo2 主要是为了演示的是如何给 共享变量进行赋值*/
// 定义共享变量,但是不能给初始值,必须由线程或者其他方式赋值
__shared__ int shared_value1;__global__ void demo2_kernel(){__shared__ int shared_value2;if(threadIdx.x == 0){// 在线程索引为0的时候,为shared value赋初始值if(blockIdx.x == 0){shared_value1 = 123;shared_value2 = 55;}else{shared_value1 = 331;shared_value2 = 8;}}// 等待block内的所有线程执行到这一步__syncthreads();printf("%d.%d. shared_value1 = %d[%p], shared_value2 = %d[%p]\n", blockIdx.x, threadIdx.x,shared_value1, &shared_value1, shared_value2, &shared_value2);
}void launch(){demo1_kernel<<<1, 1, 12, nullptr>>>();demo2_kernel<<<2, 5, 0, nullptr>>>();
}

运行效果如下:

在这里插入图片描述

图2-1 shared memory案例运行效果

在主函数中我们通过调用 cudaGetDeviceProperties 函数获取当前设备的属性,并打印出设备的共享内存的大小,一般为 48KB。

上述示例代码依次展示了使用共享内存 (shared memory)的两个示例:demo1_kerneldemo2_kernel

demo1_kernel

这个示例主要用于展示静态共享变量和动态共享变量的地址。在这个示例中,我们使用了两个静态共享变量和两个动态共享变量,二者在 kernel 函数内外定义都行,没有限制。我们启动的核函数只有一个线程块,每个线程块只有一个线程,因此只有一个线程会执行这个 kernel 函数,并打印对应的共享变量的地址。

通过打印语句,我们可以看到静态共享变量的地址会依次增加,而动态共享变量的地址始终是一样的

demo2_kernel

这个示例主要演示如何给共享变量赋值,可看 图2-2 的示意图

在这里插入图片描述

图2-2 demo2_kernel说明示意图

在这个示例中,我们定义的两个共享变量 shared_value1shared_value2,我们启动的核函数有两个线程块,每个线程块有 5 个线程,每个线程块的第一个线程会进行共享变量的赋值操作,因此当执行到 __syncthreads() 这一步时,每个 block 的其它 4 个线程会等待第一个线程完成赋值操作。

第一个 block 对应的共享变量赋值为 123 和 55,第二个 block 对应的共享变量赋值为 331 和 8,又由于共享内存(shared memory)是在块(block)级别上进行共享的,因此第一个 block 中所有线程打印的共享变量结果为 123 和 55,第二个 block 中所有线程打印的共享变量结果为 331 和 8,这点可以从运行结果中看到。

共享内存案例展示了使用共享内存的基本概念和用法。共享内存可以在同一个线程块中的线程之间共享数据,并且具有低延迟和高带宽的特性。在实际的 CUDA 程序中,共享内存常用于提高访存效率和实现协作式算法。

3. 补充知识

关于共享内存的知识点:(from 杜老师)

  1. sharedMemPerBlock 指示了 block 中最大可用的共享内存
  • 所以可用使得 block 内的 threads 可以相互通信
    • sharedMemPerBlock的应用例子如下图

在这里插入图片描述

在这里插入图片描述

  1. 共享内存是片上内存,更靠近计算单元,因此比 globalMem 速度更快,通常可以充当缓存使用
  • 数据先读入到 sharedMem,做各类计算时,使用 sharedMem 而非 globalMem
  1. demo_kernel<<<1, 1, 12, nullptr>>>();其中第三个参数 12,是指定动态共享内存 dynamic_shared_memory 的大小
  • dynamic_shared_memory 变量必须使用 extern __shared__ 开头
  • 并且定义为不确定大小的数组 []
  • 12 的单位是 bytes,也就是可以安全存放 3 个 float
  • 变量放在函数外面和里面是一样的
  • 其指针由 cuda 调度器执行时赋值
  1. static_shared_memory 作为静态分配的共享内存
  • 不加 extern,以 __shared__ 开头
  • 定义时需要明确数组的大小
  • 静态分配的地址比动态分配的地址低
  1. 动态共享变量,无论定义多少个,地址都一样
  2. 静态共享变量,定义几个地址随之叠加
  3. 如果配置的各类共享内存总和大于 sharedMemPerBlock,则核函数执行错误,Invalid argument
  • 不同类型的静态共享变量定义,其内存划分并不一定是连续的
  • 中间会有内存对齐策略,使得第一个和第二个变量之间可能存在间隙
  • 因此你的变量之间如果存在空隙,可能小于全部大于的共享内存就会报错

总结

本次课程学习了共享内存的使用,shared memory 可以在一个线程块共享数据,由于它靠近计算单元,因此访问速度相比于 global memory 更快。共享内存通常与 __syncthreads 同时出现,为了同步 block 中的所有线程。共享内存变量有静态和动态之分,静态共享内存变量,定义几个地址随之叠加,而动态共享变量,无论定义多少个,地址都一样。定义的共享变量并不能给初始值,必须由线程或者其它方式赋值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14894.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于C++、GDAL、OpenCV的矢量数据骨架线提取算法

基于C、GDAL、OpenCV的矢量数据骨架线提取算法 CGAL已经实现了该功能&#xff0c;但由于CGAL依赖于Boost库&#xff0c;编译后过大&#xff0c;因此本文所采用的这套方式实现骨架线提取功能。 效果&#xff1a; 思路&#xff1a; 1、将导入shp按照要素逐一拆分成新的shp 2、…

类Twitter风格的RSS阅读器

本文完成于 2 月中旬&#xff0c;其中的反代还是 frp npm 方案&#xff1b; 什么是 RSS ? RSS 是用 PHP、Laravel、Inertia.js、Tailwind 和 Vue.js 编写的简单的类Twitter 风格的 RSS阅读器&#xff0c;支持 RSS和ATOM 格式。 命令行安装 在群晖上以 Docker 方式安装。 官…

Nacos2.3.0源码启动报错找不到符号com.alibaba.nacos.consistency.entity

一. 源码下载编译&#xff1a;找不到符号com.alibaba.nacos.consistency.entity 如果报错找不到符号com.alibaba.nacos.consistency.entity Nacos\consistency\src\main\java\com\alibaba\nacos\consistency\entity 这个包下没有相关的java文件&#xff0c;其实是我们没有编译…

hadoop --- MapReduce

MapReduce定义&#xff1a; MapReduce可以分解为Map (映射) Reduce (规约) &#xff0c; 具体过程&#xff1a; Map : 输入数据集被切分成多个小块&#xff0c;并分配给不同的计算节点进行处理Shuffle and Sort&#xff1a;洗牌和排序&#xff0c;在 Map 阶段结束后&#xf…

15.1 BP神经网络实现图像压缩——了解神经网络在图像处理方面的应用(matlab程序)

1.简述 BP神经网络现在来说是一种比较成熟的网络模型了,因为神经网络对于数字图像处理的先天优势,特别是在图像压缩方面更具有先天的优势,因此,我这一段时间在研究神经网络的时候同时研究了一下关于BP网络实现图像压缩的原理和过程,并且是在MATLAB上进行了仿真的实验,结果发现设…

TinyStories: How Small Can Language Models Be and Still Speak Coherent English?

本文是LLM系列的文章之一&#xff0c;针对《TinyStories: How Small Can Language Models Be and Still Speak Coherent English?》的翻译。 TinyStories&#xff1a;语言模型能有多小&#xff0c;还能说连贯的英语&#xff1f; 摘要1 引言2 TinyStories数据集的描述2.1 Tiny…

3D模型轻量化开发工具HOOPS与WebGL的对比分析

HOOPS是一种商业级的3D开发平台&#xff0c;由Tech Soft 3D公司开发。它提供了一套全面的工具和API&#xff0c;用于构建和展示高度复杂的3D场景和模型&#xff0c;可以在多个平台和环境中使用&#xff0c;包括Web、移动设备和桌面&#xff0c;这使得开发者能够在不同的设备上展…

UE5接入在线直播视频源,如hls(m3u8)格式

文章目录 1.实现目标2.实现过程2.1 VlcMedia插件重编译2.2 UE5接入在线直播2.3 创建材质3.参考资料1.实现目标 通过重编译VlcMedia插件,以支持在线直播视频在UE5中的播放,GIF动图如下: 2.实现过程 本文主要包括插件的重编译、在线直播视频的接入,以及材质的创建三个部分。…

ELK部署安装

目录 一、环境准备 1.准备三台服务器&#xff08;带图形化的linuxCentOS7&#xff0c;最小化缺少很多环境&#xff09; 2.修改主机名 3.关闭防火墙 4.elk-node1、elk-node2 用系统自带的java 5.上传软件包到node1和node2 二、部署elasticsearch 1、node1、node2操作 2.no…

Coggle 30 Days of ML(23年7月)任务四:线性模型训练与预测

Coggle 30 Days of ML&#xff08;23年7月&#xff09;任务四&#xff1a;线性模型训练与预测 任务四&#xff1a;使用TFIDF特征和线性模型完成训练和预测 说明&#xff1a;在这个任务中&#xff0c;你需要使用TFIDF特征和线性模型&#xff08;如逻辑回归&#xff09;完成训练…

Jmeter做单接口测试-超详细步骤讲解

测试项目&#xff1a;本章节将以此测试项目为大家讲解怎么使用jmeter做一个接口测试 CSDN - 专业开发者社区CSDN是全球知名中文IT技术交流平台,创建于1999年,包含原创博客、精品问答、职业培训、技术论坛、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区.h…

基于梯度下降算法的无约束函数极值问题求解

基于梯度下降算法的无约束函数极值问题求解 1 知识预警1.1导数1.2偏导数1.3方向导数1.4梯度 2 梯度下降算法3 无约束函数极值问题求解3.1 算例13.1.1 Python编程求解3.1.2 求解结果与可视化 3.2 算例2 Rosenbrock函数3.2.1 Python编程求解3.2.2 求解结果与可视化 1 知识预警 1…