zcyandrew 发表于 2025-2-19 05:43

关于统一内存数据从内存到显存移动速度

mac虽然是统一内存,但是在torch中,数据从内存到“显存”还是要移动一下的,否则计算的时候会提示两个张量不在同一个设备

那么问题来了,macos到底是划分一部分内存做显存,数据需要从内存的内存部分移动到显存部分(类似windows?),还是真的实现的统一内存只是需要重新assign一下内存的mode?(https://developer.apple.com/documentation/metal/choosing-a-resource-storage-mode-for-apple-gpus)

写了一个简单的script测试数据从内存到显存移动速度,只要有torch就能运行

大概就是用在内存里创建一个Tensor然后再移动到显存

https://gist.github.com/Eeeeclipse/ea52ddbd5a79ab2745a4087647c69b92

可能不严谨,只能说是写着玩的,需要>4G的显存

测试了一下,m3 pro残血版大概是0.15秒,colab免费的t4则需要1s左右

有人有Strix Halo/GH200可以跑一下看看时间吗?

a010301208 发表于 2025-2-19 05:58

本帖最后由 a010301208 于 2025-2-19 06:35 编辑

内存速度受光速限制,所以除非把内存封装进CPU里的统一内存,用CPU直接计算,或者用核显,剩下的都不用期待,就算DDR组的通道数足够多,甚至超过4090本身带宽也没用,道路再宽车速都是龟速车一多也会堵车。

内存和显存之间的距离那更是有延迟,所以最优解就是一块显卡直接显存够大,因为就算是显卡和显卡PCIE之间也有延迟有损失,不过还是比访问内存快多了

至于MAC因该没把内存直接整体封装吧,只是封装在非常靠近核心,而实际读取的时候2者并没有完全物理复制,首先在软件面发送了指令,所以有点延迟[偷笑]

不过延迟已经很低了,说到底还是MAC本身算力不够,这个方案还是可行的

hawie 发表于 2025-2-19 07:00

默认是共享吧,在默认模式下不需数据移动,没有瓶颈。问题是这时候带宽实际达到多少?
Populate and update on the CPU
Data shared by the CPU and GPU. Use MTLStorageMode.shared. The CPU and GPU share data. This is the default for buffer and texture storage.

zcyandrew 发表于 2025-2-19 07:09

hawie 发表于 2025-2-19 07:00
默认是共享吧,在默认模式下不需数据移动,没有瓶颈。问题是这时候带宽实际达到多少?
Populate and update ...

我就是这里搞不明白,理论上统一内存GPU和CPU共享内存,应该几乎不需要时间,但是实际上运行.to(“mps”)是需要0.几秒的,而且会随着tensor size的增加而线形增加,所以我怀疑这里也是从内存的内存部分移动到了显存部分

zcyandrew 发表于 2025-2-19 07:16

问了一下chat**:

在 Apple Silicon 设备(如 M1、M2、M3 芯片)上,由于其 统一内存架构(Unified Memory Architecture, UMA),CPU 和 GPU 共享相同的物理内存,而不是像传统 x86 设备那样分别使用 RAM 和 VRAM。

是否仍然需要 to(device) 进行复制?

即使在 Apple Silicon 设备上,PyTorch 仍然需要 to("mps") 来将张量转换为 MPS 设备,但这不代表数据真的从 RAM 复制到一个独立的 VRAM。
        •        to("mps") 的作用主要是让 PyTorch 标记 该张量为 MPS 设备可用,确保后续计算在 GPU 上进行,而不是在 CPU 上运行。
        •        由于 Apple Silicon 使用统一内存,底层可能只是修改了张量的设备属性,而不是实际的数据复制,这比传统的 CPU ↔ GPU 复制(如 cuda)更高效。
        •        但 PyTorch 仍然按照传统 CPU-GPU 分离的模型管理张量,因此 to("mps") 仍然是必须的。

有没有支持直接使用统一内存的 PyTorch 版本?

目前,PyTorch 的 MPS 后端 仍然遵循传统的 “to(device)” 设备管理方式,并不支持直接在 CPU 和 GPU 之间无缝共享数据,尽管底层硬件具备这个能力。

在理想情况下,PyTorch 可以像 tensorflow-metal 那样充分利用 统一内存,自动在 CPU/GPU 之间调度计算,而不需要显式地 to("mps")。但目前,PyTorch 仍然使用 MPS 作为一个 独立设备 来管理计算,因此不能直接跨 CPU/GPU 使用同一个张量,而是需要手动 to("mps") 和 to("cpu")。

未来的可能改进
        •        苹果和 PyTorch 社区可能会改进 MPS 后端,使其更好地适配统一内存架构,但目前仍然遵循传统的 device 管理方式。
        •        PyTorch 2.x 的动态调度(dynamo)和编译优化 可能会在未来减少这种显式的数据移动需求。

总结
        1.        在 Apple Silicon 上,to("mps") 仍然需要,但它可能不会真的复制数据,而只是调整设备标识。
        2.        当前 PyTorch 版本(包括 PyTorch 2.x) 仍然要求显式 to("mps"),没有完全支持 Apple Silicon 统一内存的透明共享。
        3.        未来可能会有更好的优化,让 PyTorch 在 Apple Silicon 设备上更高效地利用统一内存,无需显式转换。

zcyandrew 发表于 2025-2-19 08:14

5090@PCIE3x16: 0.3966
我现在更加怀疑MacOS的torch并没有使用统一内存了

21PENNY 发表于 2025-2-19 16:34

本帖最后由 21PENNY 于 2025-2-19 16:35 编辑

不了解显卡本身的显存管理模式,查了篇集成集成显卡的旧文恶补了下:
https://happyseeker.github.io/kernel/2016/07/22/memory-management-from-graphic-card-view.html
应该还是为了方便软件设计,使用内存当显存的gpu:显存从io mem resource(只是地址资源,这个一般是用作framebuffer)中allocate_resource出来,然后mmap到一段内存上,这样的话和pcie显卡没什么区别,软件结构一致(pcie显卡则是要映射到自己的本地显存)。
这样的话,gpu处理数据的时候,还是要做dma把数据从其它内存搬到刚才显存mmap的内存上,但是比pcie显卡经过pcie往显卡显存上搬带宽和延迟要好很多。
页: [1]
查看完整版本: 关于统一内存数据从内存到显存移动速度