3.6.共享内存的学习

news2024/11/14 19:00:45

目录

    • 前言
    • 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) // 第一个thread
        printf("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.coloradmin.cn/o/735780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Qt5 实现的简易慕课爬取程序

基于Qt5 实现的简易慕课爬取程序 一、项目概述二、源代码 一、项目概述 名称&#xff1a;MookScrapy 这个项目主要是使用了 Qt 里面的 QNetworkAccessManager 去下载慕课网站的数据 https://coding.imooc.com&#xff0c;也就是这个网站里面的卡片信息。然后做一定的分析和展示…

【架构设计】酒店预订应用的系统设计架构(如 Airbnb、OYO)

Airbnb、Booking.com 和 OYO 等酒店预订应用程序如何提供从酒店列表到预订再到付款的流畅流程&#xff1f;而且都没有一个小故障&#xff01;在此博客中&#xff0c;您将获得对此的详细解释。由于它们非常庞大&#xff0c;以至于它们需要处理大量的用户流量。所以要管理这些&am…

计算机视觉:卷积核的参数可以通过反向传播学习到吗?

本文重点 在深度学习中,卷积神经网络(Convolutional Neural Networks, CNN)是一种常用的神经网络结构,其中卷积核是CNN的核心组件之一。卷积核是一个小矩阵,用于对输入数据进行卷积操作。卷积操作可以提取输入数据的特征,通过不同的卷积核可以提取不同的特征。 在前面课…

Wireshark TS | 二谈访问网页失败

前言 又一个访问网页失败的案例&#xff0c;该案例来自于 Wireshark sharkfest 2018 - Point And ShootPacket&#xff0c;其中的 Case 2 Cannot see homepage&#xff0c;描述的是来自 OSAKA 的用户抱怨访问一些网站页面不能显示&#xff0c;但是另外一些网站页面可以&#x…

软件测试岗位新标准:ISTQB认证与软件测试工程师职业发展

随着信息技术的飞速发展&#xff0c;软件测试行业也变得越来越重要。软件测试是保证软件质量的关键环节&#xff0c;因此&#xff0c;软件测试工程师的岗位也越来越受到重视。 ISTQB认证成为了衡量软件测试工程师职业能力的标准。 下面领测国际ISTQB考试认证中心就带您了解一下…

depot_tools问题记录 - 执行fetch/gclient命令无响应

文章目录 前言开发环境问题描述问题分析解决方案最后 前言 在研究将Dart dill文件序列化为可读文本时遇到的问题。 开发环境 macOS: 13.4 问题描述 之前使用depot_tools中的fetch/gclient命令还是正常的&#xff0c;今天想实测--no-history参数时突然遇到命令无响应的情况…

Redis 删除 key用 del 和 unlink 有啥区别?

问题 del 和 unlink 有啥区别啊&#xff1f;为什么String类型删除不会做异步删除&#xff1f; 彬彬回答 DEL 和 UNLINK 都是同步的释放 key 对象&#xff0c;区别是怎么释放后面的 value 对象 DEL 每次都是同步释放 value 部分&#xff0c;如果 value 很大&#xff0c;例如一…

Openssh升级方法详解

项目组linux服务器被绿盟扫描出openssh 1.0.2版本有漏洞&#xff0c;需要升级到7.5版本&#xff0c;以下是升级过程&#xff1a; 第一步 安装Telnet服务 先下Openssh软件包 看你需要什么版本http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/ 1.查看当前的ssh服务版本 …

【前端】网页开发精讲与实战 HTML Day 2

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;前端 &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对你有…

看完这篇 教你玩转渗透测试靶机Vulnhub——The Planets:Mercury

Vulnhub靶机The Planets:Mercury渗透测试详解 Vulnhub靶机介绍&#xff1a;Vulnhub靶机下载&#xff1a;Vulnhub靶机安装&#xff1a;Vulnhub靶机漏洞详解&#xff1a;①&#xff1a;信息收集&#xff1a;②&#xff1a;漏洞发现&#xff1a;③&#xff1a;SSH登入&#xff1a;…

架构师进阶之路 - 微服务怎么划分

目录 微服务划分目标 业务、技术、团队导向规划服务 领域检查 依赖DAG检查 分布式事务检查 性能分布检查 稳定&#xff08;易变&#xff09;性检查 调用链检查 微服务划分目标 我们常说服务的合理划分是微服务成功的重中之重&#xff0c;一个合理的服务划分应该符合一下…

SQL中如何用快照,恢复被误删的数据?

什么是快照 数据库快照是sql server 2005的一个新功能。MSDN上对它的定义是&#xff1a; 数据库快照是数据库&#xff08;称为“源数据库”&#xff09;的只读静态视图。在创建时&#xff0c;每个数据库快照在事务上都与源数据库一致。在创建数据库快照时&#xff0c;源数据库…

THREE.JS镜头随鼠标晃动效果

为了让动画更灵活并且简单 借助gsap让其具有更多可能&#xff0c;在未来更容易扩充其他动效 gsap Dom跟随鼠标移动 gsap.quickTo() 首先要监听鼠标移动&#xff0c;并且将移动的值转换到 -1 和 1 之间 方便处理 private mousemove(e: MouseEvent) {const x (e.clientX / inner…

spring10-配置数据元

他的作用是提高我们程序性能的&#xff1a;我们怎么用呢&#xff01;先创建我们数据源对象&#xff1a;创建初始化对象之后&#xff0c;创建数据源对象之后&#xff0c;会给我们一些初始化资源。 使用完后还给他 &#xff0c;这是一种环保的思想。 常见的数据源&#xff1a;底…

干货-卷起来,企业级web自动化测试实战落地(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 WebDriver的基本使…

毫米波雷达 TI IWR1443 测试官方程序(Out Of Box Demo)

IWR1443 windows 文章目录 1、准备工作1.1、mmWave SDK1.2、Code Composer Studio&#xff08;CCS&#xff09;1.3、Uniflash1.4、TI Cloud Agent 2、导入工程3、烧录3.1、先将 IWR1443 调到 Flashing Mode3.2、使用 UniFlash 软件 4、运行GUI4.1、IWR1443 调到 Functional Mo…

【计算机组成与体系结构Ⅰ】实验0 Logisim 入门实验

一、实验目的 1&#xff1a;掌握加减法器工作原理。 2&#xff1a;能够设计出一个n位加减法器。 3&#xff1a;熟悉Logisim软件使用。 二、实验环境 &#xff08;1&#xff09;Logisim 2.7.1 &#xff08;2&#xff09;Microsoft Windows 10 三、实验内容 1&#xff1a;设…

FastAPI中如何正确理解和使用:async和await

1 缘起 项目需要, 技术选型使用FastAPI。 开发过程中,遇到需要异步操作的场景, 查阅相关FastAPI异步信息的过程中,发现了async和await组合技, 通过阅读官方文档和实际测试,发现,async和await并不是传统意义上的异步(如线程池异步执行任务), async和await的融合技是应…

SEGA: Semantic Guided Attention on Visual Prototype for Few-Shot Learning

方法比较简单&#xff0c;利用语义改进prototype&#xff0c;能促进性提升

如何系统学习分布式?

关键词&#xff1a;想要走存储/数据库方向的话&#xff0c;具体路线是啥&#xff1f;重点需要掌握精通哪些知识&#xff1f; 回答 那我简单说一下走存储/数据库这块的学习路线吧。 目前做存储比较热门的是分布式存储方向&#xff0c;有NoSQL的也有关系型数据库的&#xff0c…