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
英文地址,請注明出處:http://en.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;一方面可能通過內存耗盡…