虚拟内存、内存分段、分页、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博客

相关推荐
碧海潮生_CC2 天前
【CUDA笔记】04 CUDA 归约, 原子操作,Warp 交换
笔记·cuda
fpcc6 天前
并行编程实战——CUDA编程的流的优先级
c++·cuda
碧海潮生_CC8 天前
【CUDA笔记】03 CUDA GPU 架构与一般的程序优化思路(下)
笔记·架构·cuda
中医正骨葛大夫9 天前
一文解决如何在Pycharm中创建cuda深度学习环境?
pytorch·深度学习·pycharm·软件安装·cuda·anaconda·配置环境
lvxiangyu1113 天前
wsl2 ubuntu24 opengl 无法使用nvidia显卡 解决方法记录
wsl·cuda·opengl
李昊哲小课14 天前
wsl ubuntu24.04 cuda13 cudnn9 pytorch 显卡加速
人工智能·pytorch·python·cuda·cudnn
wanzhong233315 天前
CUDA学习2-CPU和GPU的性能优化
深度学习·gpu·cuda·高性能计算
碧海潮生_CC21 天前
【CUDA笔记】01-入门简介
笔记·cuda
喆星时瑜24 天前
关于 ComfyUI 的 Windows 本地部署系统环境教程(详细讲解Windows 10/11、NVIDIA GPU、Python、PyTorch环境等)
python·cuda·comfyui
安全二次方security²1 个月前
CUDA C++编程指南(1)——简介
nvidia·cuda·c/c++·device·cuda编程·architecture·compute unified