当前位置: 首页 > news >正文

【知识】pytorch中的pinned memory和pageable memory

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn]

如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~

目录

概念简介

pytorch用法

速度测试

反直觉情况


概念简介

        默认情况下,主机 (CPU) 数据分配是可分页的。GPU 无法直接从可分页主机内存访问数据,因此当调用从可分页主机内存到设备内存的数据传输时,CUDA 驱动程序必须首先分配一个临时的页面锁定或“固定”主机数组,将主机数据复制到固定数组,然后将数据从固定阵列传输到设备内存。 

        如图所示,固定内存用作从设备到主机的传输暂存区域。通过直接在固定内存中分配主机阵列,我们可以避免在可分页主机阵列和固定主机阵列之间传输的成本。使用 cudaMallocHost() 或 cudaHostAlloc() 在 CUDA C/C++ 中分配固定主机内存,并使用 cudaFreeHost() 解除分配。固定内存分配可能会失败,因此应始终检查错误。

        数据传输速率可能取决于主机系统的类型(主板、CPU 和芯片组)以及 GPU。通过运行BandwidthTest会产生以下结果。可见,固定传输的速度是可分页传输的两倍多。(我的测试发现,基本上能跑满PCIe的带宽。

Device: NVS 4200M
Transfer size (MB): 16Pageable transfersHost to Device bandwidth (GB/s): 2.308439Device to Host bandwidth (GB/s): 2.316220Pinned transfersHost to Device bandwidth (GB/s): 5.774224Device to Host bandwidth (GB/s): 5.958834

        不过,不应过度分配固定内存。这样做会降低整体系统性能,因为它会减少操作系统和其他程序可用的物理内存量。多少是太多是很难提前判断出来的,因此与所有优化一样,测试你的应用程序及其运行的系统以获得最佳性能参数。

用法示例

        由于pinned memory后,可以使用DMA传输而不占用CPU,因此通常需要搭配non_blocking使用。

# tensor.pin_memory() 就行
pinned_tensor = torch.randn(data_size, dtype=torch.float32).pin_memory()device = torch.device("cuda")
pinned_tensor.to(device, non_blocking=True)

速度测试

import torch
import time
import torch.multiprocessing as mp# 数据大小
data_size = 10**7  # 例如,10M数据def test_pinned_memory(rank, normal_tensor, pinned_tensor, device):# 测试普通内存到GPU传输时间start_time = time.perf_counter()normal_tensor_gpu = normal_tensor.to(device, non_blocking=True)torch.cuda.synchronize()  # 等待数据传输完成normal_memory_time = time.perf_counter() - start_timeprint(f"[进程 {rank}] 普通内存到GPU传输时间: {normal_memory_time:.6f} 秒")# 测试固定内存到GPU传输时间start_time = time.perf_counter()pinned_tensor_gpu = pinned_tensor.to(device, non_blocking=True)torch.cuda.synchronize()  # 等待数据传输完成pinned_memory_time = time.perf_counter() - start_timeprint(f"[进程 {rank}] 固定内存到GPU传输时间: {pinned_memory_time:.6f} 秒")# 比较结果speedup = normal_memory_time / pinned_memory_timeprint(f"[进程 {rank}] 固定内存的传输速度是普通内存的 {speedup:.2f} 倍")if __name__ == '__main__':# 分配普通内存中的张量normal_tensor = torch.randn(data_size, dtype=torch.float32)# 分配固定内存中的张量pinned_tensor = torch.randn(data_size, dtype=torch.float32).pin_memory()# 目标设备device = torch.device("cuda")# 使用mp.spawn启动多进程测试mp.spawn(test_pinned_memory, args=(normal_tensor, pinned_tensor, device), nprocs=2, join=True)

输出:

[进程 0] 普通内存到GPU传输时间: 1.054590 秒
[进程 0] 固定内存到GPU传输时间: 0.012945 秒
[进程 0] 固定内存的传输速度是普通内存的 81.47 倍
[进程 1] 普通内存到GPU传输时间: 1.169124 秒
[进程 1] 固定内存到GPU传输时间: 0.013019 秒
[进程 1] 固定内存的传输速度是普通内存的 89.80 倍

可以看到速度还是非常快的。

反直觉情况

        我再瞎试的过程中发现,如果将pinned memory放在一个class中,那么多进程时候,pinned memory的移动很慢。暂不清楚为什么。

        示例代码(反例,仅供观看,请勿使用):

import torch
import torch.multiprocessing as mp
class PinnedMemoryManager:def __init__(self, data_size):self.data_size = data_sizeself.normal_tensor = Noneself.pinned_tensor = Nonedef allocate_normal_memory(self):# 分配普通内存self.normal_tensor = torch.randn(self.data_size, dtype=torch.float32)def allocate_pinned_memory(self):# 分配固定内存self.pinned_tensor = torch.randn(self.data_size, dtype=torch.float32).pin_memory()def transfer_to_device(self, device, use_pinned_memory=False):# 选择使用普通内存或固定内存tensor = self.pinned_tensor if use_pinned_memory else self.normal_tensorif tensor is None:raise ValueError("Tensor not allocated. Call allocate_memory first.")# 数据传输start_time = torch.cuda.Event(enable_timing=True)end_time = torch.cuda.Event(enable_timing=True)start_time.record()tensor_gpu = tensor.to(device, non_blocking=True)end_time.record()# 同步并计算传输时间torch.cuda.synchronize()transfer_time = start_time.elapsed_time(end_time) / 1000.0  # 转换为秒return tensor_gpu, transfer_timedef free_memory(self):# 释放内存del self.normal_tensordel self.pinned_tensorself.normal_tensor = Noneself.pinned_tensor = Nonedef test_pinned_memory(rank, manager, device):# 测试普通内存到GPU传输时间normal_gpu, normal_memory_time = manager.transfer_to_device(device, use_pinned_memory=False)print(f"[进程 {rank}] 普通内存到GPU传输时间: {normal_memory_time:.6f} 秒")# 测试固定内存到GPU传输时间pinned_gpu, pinned_memory_time = manager.transfer_to_device(device, use_pinned_memory=True)print(f"[进程 {rank}] 固定内存到GPU传输时间: {pinned_memory_time:.6f} 秒")# 比较结果speedup = normal_memory_time / pinned_memory_timeprint(f"[进程 {rank}] 固定内存的传输速度是普通内存的 {speedup:.2f} 倍")if __name__ == '__main__':# 数据大小data_size = 10**7  # 例如,10M数据# 初始化固定内存管理器manager = PinnedMemoryManager(data_size)manager.allocate_normal_memory()manager.allocate_pinned_memory()# 目标设备device = torch.device("cuda")# 使用mp.spawn启动多进程测试mp.spawn(test_pinned_memory, args=(manager, device), nprocs=2, join=True)# 释放内存manager.free_memory()

输出:

[进程 1] 普通内存到GPU传输时间: 0.013695 秒
[进程 1] 固定内存到GPU传输时间: 0.013505 秒
[进程 1] 固定内存的传输速度是普通内存的 1.01 倍
[进程 0] 普通内存到GPU传输时间: 0.013752 秒
[进程 0] 固定内存到GPU传输时间: 0.013593 秒
[进程 0] 固定内存的传输速度是普通内存的 1.01 倍

可以看到基本上没啥改进。

暂不清楚原因,只能先无脑避免这种用法了。

相关文章:

【知识】pytorch中的pinned memory和pageable memory

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 目录 概念简介 pytorch用法 速度测试 反直觉情况 概念简介 默认情况下,主机 (CPU) 数据分配是可分页的。GPU 无…...

【系统架构设计】数据库系统(五)

数据库系统(五) 数据库模式与范式数据库设计备份与恢复分布式数据库系统数据仓库数据挖掘NoSQL大数据 数据库模式与范式 数据库设计 备份与恢复 分布式数据库系统 数据仓库 数据挖掘 对数据挖掘技术进行支持的三种基础技术已经发展成熟&#xff0c…...

如何对人工智能系统进行测试|要点,方法及流程

当今社会,人工智能发展非常快。现在人工智能的发展已经渗透到了我们生活的方方面面,自动驾驶、或者我们手机里经常用到的一些应用都或多或少涉及到了一些人工智能的功能,比如说美图秀秀、新闻推荐、机器翻译以及个性化的购物推荐等等都涉及到…...

CVE-2023-37569~文件上传【春秋云境靶场渗透】

# 今天我们拿下CVE-2023-37569这个文件上传漏洞# 经过简单账号密码猜测 账号:admin 密码:password# 找到了文件上传的地方# 我们直接给它上传一句话木马并发现上传成功# 上传好木马后,右键上传的木马打开发现上传木马页面# 直接使用蚁剑进行连…...

MySQL简介 数据库管理与表管理

文章目录 1 MySQL的优势2 MySQL数据类型1 数字类型2 日期和时间类型3 字符串类型 3 数据库管理4 数据表管理参考 1 MySQL的优势 性能优化:通过优化存储引擎(InnoDB,MyISAM)和查询优化。解决大规模数据处理和查询优化开源&#xf…...

PHP 函数性能优化的技巧是什么?

本文由 ChatMoney团队出品 本文将详细介绍 PHP 函数性能优化的技巧。通过分析 PHP 函数的执行过程和性能瓶颈,提供一系列实用的优化方法,并结合代码示例,帮助读者提升 PHP 代码的执行效率。文章内容将涵盖变量作用域、递归算法、循环优化、内…...

小程序支付(前端)

前端只需要调用 wx.requestPayment(Object object) 文档 参考代码 const openId wx.getStorageSync(openId)payOrder({payId: this.data.resData.payId,openId}).then((res) > {console.log(2222, res);try {const data JSON.parse(res.res)console.log(22, data)const {…...

开发一个自己的VSCode插件

1、前言 对于一个前端开发者来说,开发工具,最常用的应该就是VSCode了,因为它免费,速度快,提供了丰富了插件等优点,使得越来越多的前端开发者都来使用它了,在开发的时候如果有丰富的插件提供支持…...

Milvus 向量数据库进阶系列丨构建 RAG 多租户/多用户系统 (上)

本系列文章介绍 在和社区小伙伴们交流的过程中,我们发现大家最关心的问题从来不是某个具体的功能如何使用,而是面对一个具体的实战场景时,如何选择合适的向量数据库解决方案或最优的功能组合。在 “Milvus 向量数据库进阶” 这个系列文章中&…...

前缀和(更新中)

目录 1.寻找数组的中心下标 2.除自身以外数组的乘积 3.和为k的子数组 4.可被k整除的子数组 5.连续数组 1.寻找数组的中心下标 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int pivotIndex(vector<int>& nums) {int size nums.size();v…...

记录一次单例模式乱用带来的危害。

项目场景&#xff1a; 我们在接受到短信网关下发的回执之后&#xff0c;需要将回执内容也下发给我们的下游服务。为了防止下游响应超时&#xff0c;我们需要将超时的信息存放到Redis中然后进行补发操作。 问题描述 在使用Redis进行数据存储的时候&#xff0c;报NPE问题。 原因…...

外卖项目day14(day11)---数据统计

Apache ECharts 大家可以看我这篇文章&#xff1a; Apache ECharts-CSDN博客 营业额统计 产品原型 接口设计 新建admin/ReportController /*** 数据统计相关接口*/ RestController RequestMapping("/admin/report") Api(tags "数据统计相关接口") Slf…...

养猫科普!牙口不好的猫咪怎么选粮?好吃易消化主食罐推荐

我家的猫猫已经九岁了&#xff0c;已经是一位老奶奶了&#xff0c;她的牙口不太好。对于她来说&#xff0c;膨化猫粮过于硬&#xff0c;很难咀嚼&#xff0c;所以我为她准备了质地柔软的主食罐头。哪种主食罐头更适合牙口不好的猫咪呢&#xff1f;下面&#xff0c;我就来分享一…...

力扣刷题之3143.正方形中的最多点数

题干描述 给你一个二维数组 points 和一个字符串 s &#xff0c;其中 points[i] 表示第 i 个点的坐标&#xff0c;s[i] 表示第 i 个点的 标签 。 如果一个正方形的中心在 (0, 0) &#xff0c;所有边都平行于坐标轴&#xff0c;且正方形内 不 存在标签相同的两个点&#xff0c…...

【更新2022】省级经济高质量发展指标体系测度 含代码 2000-2022

重磅更新&#xff01;【章汕】制作“省级经济高质量发展指标体系测度 含代码”&#xff0c;市面上有这个版本的数据&#xff0c;但其内容非常不全面&#xff0c;个别指标有误&#xff0c;没有stata和代码&#xff0c;即使有代码小白也很容易报错&#xff1b;没有权重、宽面板等…...

缓冲流练习

练习1&#xff1a;拷贝文件 四种方式拷贝文件&#xff0c;并统计各自用时。 字节流的基本流&#xff1a;一次读写一个字节 字节流的基本流&#xff1a;一次读写一个字节数组 字节缓冲流&#xff1a;一次读写一个字节 字节缓冲流&#xff1a;一次读写一个字节数组 这里我只使用了…...

自己履行很多的话语,依旧按照这个方式进行生活

《明朝那些事儿》最后一段讲述了徐霞客的故事&#xff0c;作者当年明月通过徐霞客的生平表达了一种人生哲学。在书的结尾&#xff0c;当年明月写道&#xff1a;"成功只有一个——按照自己的方式&#xff0c;去度过人生"&#xff0c;这句话被用作《明朝那些事儿》的结…...

交通预测数据文件梳理:METR-LA

文章目录 前言一、adj_METR-LA.pkl文件读取子文件1读取子文件2读取子文件3 二、METR-LA.h5文件 前言 最近做的实验比较多&#xff0c;对于交通预测数据的各种文件和文件中的数据格式理解愈加混乱&#xff0c;因此打算重新做一遍梳理来加深实验数据集的理解&#xff0c;本文章作…...

按钮类控件

目录 1.Push Button 代码示例: 带有图标的按钮 代码示例: 带有快捷键的按钮 代码示例: 按钮的重复触发 2.Radio Buttion 代码示例: 选择性别 代码示例: click, press, release, toggled 的区别 代码示例: 单选框分组 3.3 Check Box 代码示例: 获取复选按钮的取值 1.Pu…...

opencascade AIS_ViewController源码学习 视图控制、包含鼠标事件等

opencascade AIS_ViewController 前言 用于在GUI和渲染线程之间处理视图器事件的辅助结构。 该类实现了以下功能&#xff1a; 缓存存储用户输入状态&#xff08;鼠标、触摸和键盘&#xff09;。 将鼠标/多点触控输入映射到视图相机操作&#xff08;平移、旋转、缩放&#xff0…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...