CUDA中的内存管理、锁页内存、UVA统一虚拟地址、零拷贝、统一内存

文章目录

  • 0 前言
  • 1 swap内存跟锁页内存
  • 2 UVA(Unified Virtual Addressing)统一虚拟地址
  • 3 先看最普通的cuda内存分配、释放、传输
  • 4 申请锁页内存
    • 4.1 `cudaHostAllocDefault`
    • 4.2 `cudaHostAllocPortable`
    • 4.3 `cudaHostAllocWriteCombined`
    • 4.3 `cudaHostAllocMapped`
    • 4.4 几种锁页内存总结
    • 4.5 cudaHostAllocDefault补充说明
    • 4.6 cudaMallocHost
    • 4.7 零拷贝内存
      • 4.7.1 补充说明:ZeroCopy 的注意事项
    • 4.8 malloc、cudaHostAllocDefault()、cudaHostAllocMapped() 对比
  • 5 统一内存(Unified Memory) cudaMallocManaged
  • 6 汇总比较

0 前言

翻了下以前关于CUDA的UVA、零拷贝、统一内存的笔记,感觉顺序有些乱,而且里面有个描述还是错的,这次重新整理一下。

1 swap内存跟锁页内存

Swap 是操作系统提供的一种“虚拟内存扩展机制”。当物理内存(比如一根 4GB 内存条)不够用时,操作系统会将某些暂时不活跃的内存页(比如后台程序的数据)换出(swap out)到磁盘上的交换空间(Swap 分区或 Swap 文件),从而释放物理内存,给当前活跃的程序使用。

通俗地说:

“房子床位不够,就把出差的人行李先收拾塞进仓库(磁盘),腾出床位给新来的程序。老住户回来时,再从仓库拿回来换入(swap in)。”

与此相反,锁页内存就是告诉操作系统,这块内存是我“强占”的,不能随便给我换到磁盘上去

2 UVA(Unified Virtual Addressing)统一虚拟地址

在这里插入图片描述

“以前 CPU 和 GPU 各自管理自己的虚拟地址空间,彼此之间的指针不能通用。而有了统一虚拟地址(UVA)后,CPU 内存和 GPU 显存共享同一个虚拟地址空间,指针在 CPU 和 GPU 间可以直接传递、访问更自然、管理更统一。”

3 先看最普通的cuda内存分配、释放、传输

先看内存分配和释放

float * devMem=NULL;
cudaError_t cudaMalloc((float**) devMem, count)
cudaError_t cudaMemset(void * devPtr,int value,size_t count)
cudaError_t cudaFree(void * devPtr)

然后是内存传输

cudaError_t cudaMemcpy(void *dst,const void * src,size_t count,enum cudaMemcpyKind kind)

然后最后一个参数有下面四个枚举值

cudaMemcpyHostToHost
cudaMemcpyHostToDevice
cudaMemcpyDeviceToHost
cudaMemcpyDeviceToDevice

4 申请锁页内存

cudaError_t cudaHostAlloc(void ** pHost,size_t count,unsigned int flags)

这里的第三个参数flags可以有下面四个选项,这个 flags 可以是以下这些值之一或多个(可 OR 组合)

cudaHostAllocDefalt
cudaHostAllocPortable
cudaHostAllocWriteCombined
cudaHostAllocMapped

4.1 cudaHostAllocDefault

  • 说明:这是默认行为,分配常规的锁页内存。
  • 特性
    • 分配的内存是锁页内存(pinned),不允许被操作系统换出(swap)。
    • 适合用于 CPU↔GPU 传输的缓冲区,支持高效的 DMA 传输。
    • 不保证能被所有 CUDA 上下文共享,也不保证是写结合(write-combined)内存。
  • 使用场景
    • 一般常规的主机缓冲区分配,兼顾传输性能和通用性

4.2 cudaHostAllocPortable

  • 说明:分配的内存是可被所有 CUDA 上下文共享的锁页内存。
  • 特性
    • cudaHostAllocDefault 类似,但确保这块内存在所有 CUDA 上下文中都可用
    • 适合多 GPU 或多上下文应用程序。
  • 使用场景
    • 多 GPU 环境下,多个上下文都需要访问同一块主机内存。

4.3 cudaHostAllocWriteCombined

  • 说明:分配写结合(Write-Combined, WC)内存。
  • 特性
    • 写结合内存不保证 CPU 读取效率高,但对 GPU 写入性能有利。
    • 适合CPU 主要写入、GPU 主要读取的场景。
    • CPU 读这块内存时速度可能较慢(因为写结合内存是针对写优化)。
    • 仍是锁页内存,支持高速传输。
  • 使用场景
    • CPU 向缓冲区写数据,GPU 读取数据的流式处理场景,如视频解码后处理。

4.3 cudaHostAllocMapped

  • 说明:分配映射的锁页内存,允许 GPU 直接访问这块主机内存。
  • 特性
    • 这块内存同时映射到 CPU 和 GPU 地址空间。
    • GPU 可以通过特定设备指针直接访问主机内存,实现零拷贝(Zero-Copy)。
    • 减少了显存占用和显存间的显式数据拷贝,但访问速度受限于 PCIe 带宽。
  • 使用场景
    • 适合小数据量、对延迟敏感、不想显式拷贝的场景。
    • 需要调用 cudaHostGetDevicePointer() 获取对应的 GPU 设备指针。
    • 零拷贝场景。

4.4 几种锁页内存总结

标志特点与说明使用建议
cudaHostAllocDefault普通锁页内存,等价于 cudaMallocHost()最常用,适合常规 H↔D 拷贝
cudaHostAllocPortable多 context 多 GPU 共享主机内存多 GPU / 多线程环境
cudaHostAllocWriteCombined主机只写,优化 CPU→GPU 传输性能,读很慢图像、音频、传感器流式写缓冲区
cudaHostAllocMapped支持 ZeroCopy,GPU 可访问主机内存,需要配合 cudaHostGetDevicePointer() 使用小数据共享、无需频繁 memcpy 场景

4.5 cudaHostAllocDefault补充说明

这个cudaHostAllocDefault也是比较常用的一个flag.

特性说明
✅ 分配主机锁页(Pinned)内存比普通 malloc 分配的 pageable memory 更适合 cudaMemcpy
✅ 提高 H2D / D2H 的数据传输速率DMA 传输,绕过页交换机制,避免内核拷贝中断
✅ 适用于大多数单 GPU、单 context 应用也是最不容易踩坑的分配方式
✅ 行为与 cudaMallocHost() 完全一致所以也可以用它来替代后者

当我们在host端申请内存,而我们可能需要再host和device相互之间memcpy这块内存的时候,用这个申请内存要比用malloc申请的内存更快。

因为 malloc() 分配的是 pageable memory(可分页内存):

  • 操作系统可以把它 swap 到磁盘;
  • 在进行 cudaMemcpy() 时,驱动需要:
    1. 临时创建一块锁页缓冲区;
    2. 先从 malloc 的内存拷贝到临时锁页内存;
    3. 再拷贝到 GPU 显存;
  • 整个过程是 双拷贝 + page fault 风险速度较慢

cudaHostAllocDefault() 分配的是 pinned memory(锁页内存):

  • 操作系统保证这块内存 不会被分页
  • 可以被 CUDA 驱动直接用于 DMA(直接内存访问)拷贝
  • 是真正的 单次、高速拷贝

4.6 cudaMallocHost

cudaError_t cudaMallocHost(void ** devPtr,size_t count)
cudaError_t cudaFreeHost(void *ptr)

一句话总结,cudaMallocHost相当于是cudaHostAlloc的第三个参数选cudaHostAllocDefault。

4.7 零拷贝内存

    /*** Allocate ZeroCopy mapped memory, shared between CUDA and CPU.** @note although two pointers are returned, one for CPU and GPU, they both resolve to the same physical memory.** @param[out] cpuPtr Returned CPU pointer to the shared memory.* @param[out] gpuPtr Returned GPU pointer to the shared memory.* @param[in] size Size (in bytes) of the shared memory to allocate.** @returns `0` if the allocation succeeded, otherwise faield.* @ingroup cudaMemory*/int cudaAllocMapped(void** cpuPtr, void** gpuPtr, size_t size) {if (!cpuPtr || !gpuPtr || size == 0)return -1;CUDA_SAFECALL(cudaHostAlloc(cpuPtr, size, cudaHostAllocMapped), "cudaHostAlloc failed", -1);CUDA_SAFECALL(cudaHostGetDevicePointer(gpuPtr, *cpuPtr, 0), "cudaHostGetDevicePointer failed", -1);memset(*cpuPtr, 0, size);VLOG(3) << "[InferServer] cudaAllocMapped " << size << " bytes, CPU " << *cpuPtr << " GPU " << *gpuPtr;return 0;}/*** Allocate ZeroCopy mapped memory, shared between CUDA and CPU.** @note this overload of cudaAllocMapped returns one pointer, assumes that the*       CPU and GPU addresses will match (as is the case with any recent CUDA version).** @param[out] ptr Returned pointer to the shared CPU/GPU memory.* @param[in] size Size (in bytes) of the shared memory to allocate.** @returns `0` if the allocation succeeded, otherwise failed.* @ingroup cudaMemory*/int cudaAllocMapped(void** ptr, size_t size) {void* cpuPtr{};void* gpuPtr{};if (!ptr || size == 0)return cudaErrorInvalidValue;auto error = cudaAllocMapped(&cpuPtr, &gpuPtr, size);if (error != cudaSuccess)return error;CUDA_SAFECALL(cpuPtr != gpuPtr, "cudaAllocMapped() - addresses of CPU and GPU pointers don't match", cudaErrorMemoryAllocation);*ptr = gpuPtr;return cudaSuccess;}

这个零拷贝内存其实就是在申请锁页内存的基础上,用cudaHostGetDevicePointer获取了跟锁页内存对应的GPU设备内存指针。cpuPtr 和 gpuPtr 实际上指向的是同一块物理内存。这是通过CUDA的统一虚拟寻址(Unified Virtual Addressing, UVA)实现的。

4.7.1 补充说明:ZeroCopy 的注意事项

  • cudaHostAllocMapped 产生的内存虽然 CPU 和 GPU 都能访问,但仍然是主机内存,GPU 访问时通过 PCIe 远程访问(不是cuda驱动自动背后memcpy),性能远不如显存;
  • 即使有了 UVA(统一虚拟寻址),也仍需调用 cudaHostGetDevicePointer() 获取 GPU 可访问的地址;
  • 不适合大数据频繁访问,用在小数据共用、高效开发场景更好。

4.8 malloc、cudaHostAllocDefault()、cudaHostAllocMapped() 对比

方法是否锁页内存GPU是否可直接访问性能
malloc()❌ 否❌ 否普通 CPU 内存,传输慢
cudaHostAllocDefault()✅ 是❌ 否高效 H2D/D2H 拷贝
cudaHostAllocMapped()✅ 是✅ 是(需映射)可 ZeroCopy,但访问慢
主机内存类型拷贝方式带宽性能(相对)
malloc()cudaMemcpy()1.0x
cudaHostAlloc()cudaMemcpy()🔺 1.5x ~ 2.5x
cudaHostAllocMapped() + 直接访问ZeroCopy⚠️ 慢,适合小数据

5 统一内存(Unified Memory) cudaMallocManaged

统一内存是从 CUDA 6.0 引入的一项机制,其核心目标是:

✅ 简化内存管理 —— 让 CPU 和 GPU 使用同一个指针访问数据,CUDA 运行时自动在主机和设备之间迁移数据,无需手动调用 cudaMemcpy

特点:

  • 使用 cudaMallocManaged() 分配的托管内存,可以被 CPU 和 GPU 共同访问;
  • 背后会在 CPU/GPU 之间 自动分页迁移(通过页错误机制),无需手动拷贝;
  • 依赖于 UVA(统一虚拟地址)实现统一指针;
  • 内存不再需要分别分配 host 和 device 内存再同步内容
  • 更适合新手开发、代码更简洁,但有时性能不如手动拷贝。

6 汇总比较

类型分配方式是否锁页内存是否需 memcpyGPU 是否直接访问性能表现适合场景
普通主机内存malloc()❌ 否✅ 需要❌ 否⚠️ 最慢,H2D需拷贝最普通的内存,不推荐传输用
锁页主机内存cudaHostAllocDefault()cudaMallocHost()✅ 是✅ 需要❌ 否✅ 快速拷贝(H2D/D2H)高效拷贝用,推荐用于传输
零拷贝内存(ZeroCopy)cudaHostAllocMapped()✅ 是❌ 不需要✅ 是(映射)⚠️ 延迟高,带宽低小数据共享、开发阶段调试
统一内存(Unified Memory)cudaMallocManaged()✅ 是(托管)❌ 不需要✅ 是(自动迁移)✅ 自动迁移但性能波动开发方便,复杂数据结构共享等

补充说明

  • 锁页内存(Pinned Memory):不能被操作系统 swap,提高了传输效率。
  • ⚠️ ZeroCopy:虽然不需要显式拷贝,但实际通过 PCIe 总线远程访问,延迟和带宽都劣于显存。
  • Unified Memory:托管内存在访问时由 CUDA 运行时系统自动分页迁移,适合开发快速验证,性能不易控制。
  • cudaMemcpy():适用于大数据高吞吐传输,配合显存使用效率最佳。

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

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

相关文章

微服务环境下的灰度发布与金丝雀发布实战经验分享

微服务环境下的灰度发布与金丝雀发布实战经验分享 在大规模微服务架构中&#xff0c;如何平滑安全地上线新功能是每个后端团队的痛点。本文将结合生产环境中的真实案例&#xff0c;分享灰度发布&#xff08;Gray Release&#xff09;与金丝雀发布&#xff08;Canary Release&am…

MEF 在 WPF 中的简单应用

MEF核心笔记MEF 的开发模式主要适用于插件化的业务场景中&#xff0c;C/S 和 B/S 中都有相应的使用场景&#xff0c;其中包括但不限于 ASP.NET MVC 、ASP WebForms、WPF、UWP 等开发框架。当然&#xff0c;DotNet Core 也是支持的。 以下是搜索到一些比较好的博文供参考&#…

Gitlab跑CICD的时候,maven镜像和pom.xml使用的maven版本冲突导致没办法build成功的解决方法

是这样的&#xff01;最近遇到一个非常棘手的难题&#xff0c;我搞了大概2周时间才把他弄出来&#xff0c;因为自己搭了个私服的maven仓库&#xff0c;他不像maven官方仓库一样&#xff0c;可以跟nginx一样转的&#xff0c;所以遇到好几个难点&#xff01;第一点&#xff1a;就…

Linux内核IPv4路由查找:LPC-Trie算法的深度实践

在互联网基础设施的核心领域,路由查找性能直接决定了网络转发效率。Linux内核作为现代网络系统的基石,其IPv4路由子系统采用了一种名为LPC-Trie(Level-Compressed Trie) 的创新数据结构,在net/ipv4/fib_trie.c文件中实现了高效的路由管理方案。本文将深入剖析这一机制的设…

【设计模式】装饰(器)模式 透明装饰模式与半透明装饰模式

装饰模式&#xff08;Decorator Pattern&#xff09;详解一、装饰模式简介 装饰模式&#xff08;Decorator Pattern&#xff09; 是一种 结构型设计模式&#xff0c;它允许你动态地给对象添加行为或职责&#xff0c;而无需修改其源代码&#xff0c;也不需要使用继承来扩展功能。…

NAT原理与实验指南:网络地址转换技术解析与实践

NAT实验 NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;&#xff1a; NAT技术的介绍&#xff1a; 随着Internet用户的快速增长&#xff0c;以及地址分配不均等因素&#xff0c;IPv4地址&#xff08;约40亿的空间地址&#xff09;已经陷入不…

设计模式之【观察者模式】

目录 观察者模式中的角色 通过一个简单案例来演示观察者模式 被观察者接口 事件类型 up主类作为被观察者 观察者接口 粉丝类作为观察者 测试 测试结果 观察者模式中的角色 被观察者(observable)观察者(observer) 通过一个简单案例来演示观察者模式 被观察者接口 /*…

Linux sudo host权限提升漏洞(CVE-2025-32462)复现与原理分析

免责声明 本文所述漏洞复现方法仅供安全研究及授权测试使用&#xff1b; 任何个人/组织须在合法合规前提下实施&#xff0c;严禁用于非法目的&#xff1b; 作者不对任何滥用行为及后果负责&#xff0c;如发现新漏洞请及时联系厂商并遵循漏洞披露规则。 漏洞简述 Linux sudo是l…

【uni-ui】hbuilderx的uniapp 配置 -小程序左滑出现删除等功能

1.网址&#xff1a;https://ext.dcloud.net.cn/plugin?id181](https://ext.dcloud.net.cn/plugin?id181) 2.csdn讲解&#xff1a;https://blog.csdn.net/qq_40323256/article/details/114337128 3.uni-ui git&#xff1a;https://github.com/dcloudio/uni-ui 4.官方网址文档&…

记一次POST请求中URL中文参数乱码问题的解决方案

POST请求中URL中文参数乱码前言&#xff1a;一个常见的开发痛点一、问题现象与原因深度解析1. 典型问题场景2. 根本原因分析URL编码规范问题&#xff1a;编码解码过程不一致&#xff1a;IE浏览器特殊行为&#xff1a;二、前端解决方案1. 手动编码URL参数&#xff08;推荐&#…

从存储热迁移流程了解 QEMU block layer

文章目录存储热迁移流程总体流程代码路径QEMU Block layer架构简述Block Job结构体设计状态转换Mirror block job拓扑结构构建过程数据结构存储热迁移流程 总体流程 Libvirt migrate 命令提供 copy-storage-all 选项支持存储热迁移&#xff0c;相应地&#xff0c;Libvirt 热迁…

【设计模式】命令模式 (动作(Action)模式或事务(Transaction)模式)宏命令

命令模式&#xff08;Command Pattern&#xff09;详解一、命令模式简介 命令模式&#xff08;Command Pattern&#xff09; 是一种 行为型设计模式&#xff08;对象行为型模式&#xff09;&#xff0c;它将一个请求封装为一个对象&#xff0c;从而使你可以用不同的请求对客户进…

HTML5智能排班日历:动态排班一目了然

这个日历将具备以下功能: 显示一个标准的月度日历视图。可以自由切换上一个月和下一个月。在日历的每一天自动显示当天值班的人员。您可以很方便地在文件中修改值班人员列表和排班的起始日期。包括:动态生成日历网格处理月份切换根据排班规则计算并显示每天的值班人员<!DO…

深度剖析C++生态系统:一门老牌语言如何在开源浪潮中焕发新生?

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、前言&#xff1a;C的“长寿秘诀”是什么&#xff1f; C 诞生已超过 40 年。它经历了桌面应用、互联网爆发、移动时代&#xff0c;再…

60个功能OfficeBox 万彩办公大师:PDF 格式转换 OCR识别免费无广告

各位办公小能手们&#xff01;今天给大家介绍个超厉害的免费办公工具套装——OfficeBox万彩办公大师&#xff0c;是广州万彩科技整出来的。软件下载地址安装包 它里面有60多个没广告的绿色组件&#xff0c;简直像个百宝箱&#xff01;涵盖了PDF处理、格式转换、OCR识别、屏幕录…

拥抱主权AI:OpenCSG驱动智能体运营,共筑新加坡智能高地

2025年7月11日&#xff0c;由Linux基金会AI & Data、TikTok及LF Edge联合主办的 【LF AI & Data Day Singapore 2025】 在新加坡TikTok总部盛大启幕。本次大会以“Agent for SWE”为核心议题&#xff0c;汇聚全球顶尖AI开发者、企业领袖及开源社区先锋。作为国家主权AI…

单片机学习笔记.根据芯片数据手册写驱动程序(这里使用的是普中开发版,以DS1302为例)

硬件原理图部分&#xff1a; VCC2:是主电源 VCC1&#xff1a;是备用电源&#xff0c;此处没有使用VCC1 查芯片数据手册的网站&#xff1a; ALLDATASHEETCN.COM - 电子元件和半导体及其他半导体的数据表搜索网站。https://www.alldatasheetcn.com/ 1.由原理图可知对应引脚&…

Capture One24下载与保姆级安装教程!

软件下载 软件名称&#xff1a;Capture One24 软件语言&#xff1a;简体中文 软件大小&#xff1a;1.06G 系统要求&#xff1a;Windows7或更高&#xff0c;32/64位操作系统 硬件要求&#xff1a;CPU2.5GHz&#xff0c;RAM4G或更高 下载通道丨下载&#xff1a;https://too…

微信小程序(数据库)

const dbwx.cloud.database()//连接数据库db.collection("test").doc("b69f67c0626fac9000e123fc1ff07a42&#xff08;为要查询数据的id&#xff09;").get({success:res>{console.log(res)}})或getData(){db.collection("test").doc("&…

Apache CXF 漏洞曝光:存在拒绝服务与数据泄露双重风险

Apache软件基金会近日披露了一个影响多个Apache CXF版本的安全漏洞&#xff08;CVE-2025-48795&#xff09;。Apache CXF是开发者广泛使用的开源Web服务框架&#xff0c;用于构建基于SOAP和REST的应用程序。漏洞双重威胁该漏洞具有双重危害性&#xff1a;一方面可能通过内存耗尽…