虚拟内存、内存分段、分页、CUDA编程中的零拷贝

目录

[1 虚拟地址](#1 虚拟地址)

[2 分段管理](#2 分段管理)

[2.1 为什么分段管理会产生碎片](#2.1 为什么分段管理会产生碎片)

3分页管理

[4 CUDA编程中的零拷贝](#4 CUDA编程中的零拷贝)

参考文献:


下面的1 2 3 4都是我的通俗理解,不是官方语言。

1 虚拟地址

cpu发出的地址是虚拟地址,它经过MMU映射到物理地址上。这个自己以前就知道,不赘述了。

2 分段管理

分段管理其实就是,操作系统每次把一个程序需要的虚拟内存分为什么代码段、数据段、堆栈段等,然后操作系统需要从内存条申请一大块连续内存 给代码段,再申请一大块连续内存给数据段,然后程序中使用的当然都是虚拟地址了,然后cpu通过查询段表知道段基址和偏移地址,从而找到物理地址。

2.1 为什么分段管理会产生碎片

这个也简单理解,就是比如一个程序需要100MB内存,然后一会释放了,过一会另一个程序需要200MB内存,那么前面被释放的那100MB可能现在就没法用了,因为太小了,就这么简单理解就可以。

3分页管理

前面分段管理不是有内存碎片吗,分段管理的弊端我觉得其实就是需要申请连续内存,所以分页管理就来了,分页管理把内存条每4KB划分成一个页,然后程序的虚拟地址也是用4KB一个页给管理起来,这样有个好处就是比如一个程序需要100MB,那么不需要从内存条申请一大块连续空间,因为他4kb一个页去管理,那么边边角角的一些零碎内存也给用起来了,这不就没有碎片了吗。

4 CUDA编程中的零拷贝

cpp 复制代码
    /**
    * 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;
    }

其实就是cudaAllocMapped申请的内存,cpu和gpu都能访问,然后就不需要拷贝了,

cudaHostAlloc :用于分配锁页内存,并将其映射到设备地址空间,其中的参数cudaHostAllocMapped 标志表示这块内存是映射的,即可以被GPU直接访问,cudaHostAlloc 分配的内存是共享的,CPU和GPU都可以访问这块内存。这种访问模式通常称为"零拷贝"或"统一虚拟寻址"(UVA)

cudaHostGetDevicePointer:用于获取与锁页内存对应的设备指针。

cpuPtrgpuPtr 实际上指向的是同一块物理内存。这是通过CUDA的统一虚拟寻址(Unified Virtual Addressing, UVA)实现的。统一虚拟寻址(UVA):现代CUDA版本支持统一虚拟寻址,这使得CPU和GPU可以使用相同的地址空间。这意味着同一块物理内存可以同时被CPU和GPU访问,而不需要显式的数据复制。

参考文献:

一篇文 带你搞懂,虚拟内存、内存分页、分段、段页式内存管理(超详细)_一篇文带你搞懂,虚拟内存、内存分页、分段、段页式内存管理(超详细)-CSDN博客

CUDA:cudaHostAlloc()-CSDN博客

CUDA编程------cudaHostAlloc-CSDN博客

CUDA编程------zero copy_cuda zerocopy-CSDN博客

相关推荐
bloglin999991 天前
Ubuntu22.04 离线安装 CUDA12.3 依赖报错解决方案
ai·cuda
fpcc6 天前
并行编程实战——CUDA编程的图之六子图的创建
人工智能·cuda
明月醉窗台7 天前
[jetson] AGX Xavier 安装Ubuntu18.04及jetpack4.5
人工智能·算法·nvidia·cuda·jetson
飞翔的SA7 天前
全程 Python:无需离开 Python 即可实现光速级 CUDA 加速,无需c++支持
开发语言·c++·python·nvidia·cuda
阿钱真强道12 天前
01 飞腾 S5000C 服务器环境搭建实战:PyTorch + CUDA + RTX 4090D 安装与验证
pytorch·cuda·aarch64·深度学习环境搭建·飞腾服务器·s5000c·rtx4090d
酌量15 天前
nvidia orin agx刷机忘记CUDA runtime,安装torch和cuda
linux·笔记·ubuntu·torch·cuda·agx
明月醉窗台16 天前
[Jetson] NVIDIA Jetson 全系列边缘计算芯片进阶指南
人工智能·边缘计算·cuda·jetson
tianrun123416 天前
ARMv8 两级页表内存属性合并原理
虚拟化·mmu·armv8
明月醉窗台20 天前
[Jetson] 在Jetson Xavier AGX编译opencv+cuda
人工智能·opencv·计算机视觉·cuda·jetson
专注VB编程开发20年21 天前
CUDA实现随机切割算法,显卡多线程计算
算法·cuda