了解cuda的統一內存

1. CUDA 6中的統一內存

在CUDA 6中,從Kepler GPU架構(計算能力3.0或更高)開始,在64位Windows 7、8和Linux操作系統(內核2.6.18+)上開始支持統一內存.
在這里插入圖片描述
從CUDA 6開始,NVIDIA推出了CUDA平臺歷史上最引人注目的編程模型改進之一 ---- 統一內存
在當今典型的PC或集群節點中,CPU和GPU的內存在物理上是不同的,并由PCI Express總線分隔。
在CUDA 6之前,程序員必須這樣看待事物。CPU和GPU之間共享的數據必須在兩個內存中分配,并由程序在它們之間明確復制。這給CUDA程序增加了很多復雜性。

在這里插入圖片描述
統一內存創建了一個在CPU和GPU之間共享的托管內存池,彌合了CPU-GPU的鴻溝。
CPU和GPU都可以使用單個指針訪問托管內存。關鍵在于,系統會自動在主機和設備之間遷移統一內存中分配的數據,使其看起來像CPU內存當在CPU上運行代碼時,而在GPU上運行代碼時像是GPU內存。

在這篇文章中,我將向您展示統一內存如何大大簡化GPU加速應用程序中的內存管理。
下圖顯示了一個非常簡單的例子。這兩個代碼都從磁盤加載文件,對其中的字節進行排序,然后在釋放內存之前在CPU上使用排序后的數據。右側的代碼使用CUDA和統一內存在GPU上運行.
兩個代碼的唯一的區別是GPU版本啟動內核函數(并在啟動后進行同步),并使用新的API cudaMallocManaged()為加載的文件在統一內存中分配空間.

在這里插入圖片描述
如果你以前用過CUDA C/C++編程,你無疑會被右邊代碼的簡潔性所打動。請注意,我們只分配了一次內存,并且我們有一個指向主機和設備都可以訪問的數據的指針。我們可以直接從文件讀取內容到分配的內存,然后將指針直接傳遞給在設備上運行的CUDA內核。然后,在等待內核完成之后,我們可以再次從CPU訪問數據。CUDA運行時隱藏了所有的復雜性,自動將數據遷移到訪問它的地方。

2 統一內存提供了什么

程序員從統一內存中受益的主要方式有兩種。

2.1 更簡單的編程和內存模型

統一內存降低了CUDA平臺上并行編程的門檻,通過使設備內存管理成為一種優化,而不是一種要求
有了統一內存,現在程序員可以直接開發并行CUDA內核,而不會陷入分配和復制設備內存的細節中。
這將使學習CUDA平臺的編程和將現有代碼移植到GPU更簡單。但這不僅僅適用于初學者。
本文后面的示例展示了統一內存如何使復雜的數據結構更容易與設備代碼一起使用,以及它與C++結合時的強大功能。

2.2 通過數據本地化提升性能

通過在CPU和GPU之間按需遷移數據,統一內存可以在GPU上提供本地數據的性能,同時提供全局共享數據的易用性。此功能的復雜性被隱藏在CUDA驅動程序和運行時的保護之下,確保應用程序代碼更易于編寫。遷移的目的是實現每個處理器的全帶寬;250 GB/s的GDDR5內存對于提升開普勒GPU的計算吞吐量至關重要。

一個重要的點是,一個經過精心調優的CUDA程序,它使用流和cudaemcpyAsync來有效地將執行與數據傳輸重疊,可能會比只使用統一內存的CUDA軟件表現得更好。容易理解的是:CUDA運行時永遠不會像程序員那樣了解需要數據的位置和時間!CUDA程序員仍然可以訪問顯式設備內存分配和異步內存副本,以優化數據管理和CPU-GPU并發性。統一內存首先是一種生產力功能,它為并行計算提供了更平滑的入口,而不會剝奪CUDA為高級用戶提供的任何功能。

3 統一內存還是統一虛擬尋址?

CUDA自CUDA 4以來一直支持統一虛擬尋址(UVA),雖然統一內存依賴于UVA,但它們不是一回事。UVA為系統中的所有內存提供了一個單一的虛擬內存地址空間,并允許從GPU代碼訪問指針,無論它們位于系統的哪個位置,無論是設備內存(在相同或不同的GPU上)、主機內存還是片上共享內存。它還允許使用cudaMemcpy,而無需指定輸入和輸出參數的確切位置。UVA支持“零拷貝”內存,即設備代碼可以直接通過PCI Express訪問的固定主機內存,無需memcpy。Zero Copy提供了統一內存的一些便利,但沒有提供任何性能,因為它總是使用PCI Express的低帶寬和高延遲進行訪問。

UVA不會像統一內存那樣自動將數據從一個物理位置遷移到另一個。由于統一內存能夠在主機和設備內存之間自動遷移單個頁面級別的數據,因此需要大量的工程來構建,因為它需要CUDA運行時、設備驅動程序甚至操作系統內核中的新功能。以下示例旨在讓您了解其功能。

3.1 例子:消除深拷貝

統一內存的一個關鍵好處是簡化了異構計算內存模型,因為在訪問GPU內核中的結構化數據時不需要深度副本。將包含指針的數據結構從CPU傳遞到GPU需要進行“深度復制”,如下圖所示。
在這里插入圖片描述
dataElem結構如下

struct dataElem {int prop1;int prop2;char *name;
}

要在設備上使用此結構,我們必須復制結構本身及其數據成員,然后復制結構指向的所有數據,然后更新結構副本中的所有指針。這導致了以下復雜的代碼,只是為了將數據元素傳遞給內核函數。

void launch(dataElem *elem) {dataElem *d_elem;char *d_name;int namelen = strlen(elem->name) + 1;// Allocate storage for struct and namecudaMalloc(&d_elem, sizeof(dataElem));cudaMalloc(&d_name, namelen);// Copy up each piece separately, including new “name” pointer valuecudaMemcpy(d_elem, elem, sizeof(dataElem), cudaMemcpyHostToDevice);cudaMemcpy(d_name, elem->name, namelen, cudaMemcpyHostToDevice);cudaMemcpy(&(d_elem->name), &d_name, sizeof(char*), cudaMemcpyHostToDevice);// Finally we can launch our kernel, but CPU & GPU use different copies of “elem”Kernel<<< ... >>>(d_elem);
}

可以想象,在CPU和GPU代碼之間共享復雜數據結構所需的額外主機端代碼對生產率有重大影響。在統一內存中分配我們的dataElem結構消除了所有多余的設置代碼,只剩下內核啟動,它與宿主代碼在同一指針上運行。這是一個很大的進步!

void launch(dataElem *elem) {kernel<<< ... >>>(elem);
}

但這不僅僅是代碼復雜性的一大改進。統一內存還可以做以前無法想象的事情。讓我們來看另一個例子:

3.2 例子: CPU/GPU之間共享鏈表

在這里插入圖片描述
鏈表是一種非常常見的數據結構,但由于它們本質上是由指針組成的嵌套數據結構,在內存空間之間傳遞它們非常復雜。如果沒有統一內存,CPU和GPU之間共享鏈表是無法管理的。唯一的選擇是在零拷貝內存(固定主機內存)中分配列表,這意味著GPU訪問僅限于PCI express性能。通過在統一內存中分配鏈表數據,設備代碼可以在GPU上正常跟隨指針,并具有設備內存的全部性能。該程序可以維護一個鏈表,可以在主機或設備上添加和刪除列表元素.

將具有現有復雜數據結構的代碼移植到GPU曾經是一項艱巨的任務,但統一內存使這變得更加容易。我預計統一內存將為CUDA程序員帶來巨大的生產力提升。

4. c++中使用統一內存

統一內存在C++數據結構中大放異彩。C++通過使用帶有復制構造函數的類簡化了深度復制問題。復制構造函數是一個函數,它知道如何創建類的對象,為其成員分配空間,并從另一個對象復制它們的值。C++還允許重載new和delete內存管理運算符。這意味著我們可以創建一個基類,我們稱之為Managed,它在重載的new運算符中使用cudaAllocManaged(),如下代碼所示。

class Managed {
public:void *operator new(size_t len) {void *ptr;cudaMallocManaged(&ptr, len);cudaDeviceSynchronize();return ptr;}void operator delete(void *ptr) {cudaDeviceSynchronize();cudaFree(ptr);}
};

然后,我們可以讓String類從Managed類繼承,并實現一個復制構造函數,為復制的字符串分配統一內存。

// Deriving from “Managed” allows pass-by-reference
class String : public Managed {int length;char *data;public:// Unified memory copy constructor allows pass-by-valueString (const String &s) {length = s.length;cudaMallocManaged(&data, length);memcpy(data, s.data, length);}// ...
};

同樣,我們使dataElem類繼承Managed。

// Note “managed” on this class, too.
// C++ now handles our deep copies
class dataElem : public Managed {
public:int prop1;int prop2;String name;
};

通過這些更改,C++類在統一內存中分配存儲,并自動處理深度副本。我們可以像任何C++對象一樣在統一內存中分配dataElem。

dataElem *data = new dataElem;

請注意,您需要確保繼承樹中的每個類都繼承自Managed,否則您的內存映射中會出現漏洞。實際上,您可能需要在CPU和GPU之間共享的所有內容都應該繼承Managed。如果你更喜歡簡單地使用統一內存來處理所有事情,你可以在全局范圍內重載new和delete,但這只有在沒有僅CPU數據的情況下才有意義,否則數據將不必要地遷移。
現在,當我們將對象傳遞給內核函數時,我們有一個選擇;與C++中的正常情況一樣,我們可以按值傳遞或按引用傳遞,如下面的示例代碼所示。

// Pass-by-reference version
__global__ void kernel_by_ref(dataElem &data) { ... }// Pass-by-value version
__global__ void kernel_by_val(dataElem data) { ... }int main(void) {dataElem *data = new dataElem;...// pass data to kernel by referencekernel_by_ref<<<1,1>>>(*data);// pass data to kernel by value -- this will create a copykernel_by_val<<<1,1>>>(*data);
}

得益于統一內存,深度拷貝、按值傳遞和按引用傳遞都能正常工作。這為在GPU上運行C++代碼提供了巨大的價值。
這篇文章中的例子可以在Github上找到。

5. 統一內存的光明未來

CUDA 6中統一內存最令人興奮的事情之一是它只是一個開始。cuda圍繞統一內存計劃了一個漫長的改進和功能路線圖。
統一內存的第一個版本旨在使CUDA編程更容易,特別是對于初學者。從CUDA 6開始,cudaemcpy()不再是必需的。通過使用cudaAllocManaged(),您可以有一個指向數據的指針,并且可以在CPU和GPU之間共享復雜的C/C++數據結構。這使得編寫CUDA程序變得更加容易,因為您可以直接編寫內核,而不是編寫大量數據管理代碼并維護所有數據的重復主機和設備副本。您仍然可以自由地使用cudaemcpy()(特別是cudamemppyAsync())來提高性能,但這不是一項要求,而是一種優化。

CUDA的未來版本可能會通過添加數據預取和遷移提示來提高使用統一內存的應用程序的性能。統一內存還將增加對更多操作系統的支持。nv的下一代GPU架構將帶來一系列硬件改進,以進一步提高性能和靈活性.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63650.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63650.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63650.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

unity 最小后監聽鍵盤輸入

當Untiy最小化后&#xff0c;游戲窗口不會立刻失去焦點&#xff0c;此時依然可以使用Input來獲取按鍵&#xff0c;但是點擊其他窗口后&#xff0c;就會失去焦點&#xff0c;此時系統會把按鍵輸入分配到其他窗口里&#xff0c;此時要用windowsAPI獲取按鍵輸入&#xff0c;應對兩…

Pytorch | 從零構建MobileNet對CIFAR10進行分類

Pytorch | 從零構建MobileNet對CIFAR10進行分類 CIFAR10數據集MobileNet設計理念網絡結構技術優勢應用領域 MobileNet結構代碼詳解結構代碼代碼詳解DepthwiseSeparableConv 類初始化方法前向傳播 forward 方法 MobileNet 類初始化方法前向傳播 forward 方法 訓練過程和測試結果…

Electronjs+Vue如何開發PC桌面客戶端(Windows,Mac,Linux)

electronjs官網 https://www.electronjs.org/zh/ Electron開發PC桌面客戶端的技術選型非常適合已經有web前端開發人員的團隊。能夠很絲滑的過渡。 Electron是什么&#xff1f; Electron是一個使用 JavaScript、HTML 和 CSS 構建桌面應用程序的框架。 嵌入 Chromium 和 Node.…

【1.排序】

排序 筆記記錄 1.排序的基本概念1.1 排序的定義 2. 插入排序2.1 直接插入排序2.2 折半插入排序2.3 希爾排序 3. 交換排序3.1 冒泡排序3.2 快速排序 4. 選擇排序4.1 簡單選擇排序4.2 堆排序 5. 歸并排序、基數排序和計數排序5.1 歸并排序4.2 基數排序4.3 計數排序 6. 各種內部排…

Linux Swap: 深入解析 mkswap, mkfs.swap, 和 swapon

文章目錄 Linux Swap: 深入解析 mkswap, mkfs.swap, 和 swapon什么是 Swap&#xff1f;主要命令介紹1. mkswap2. mkfs.swap3. swapon 創建和管理 Swap 的步驟1. 創建 Swap 分區2. 初始化 Swap3. 激活 Swap4. 持久化配置5. 查看 Swap 狀態 刪除 Swap 分區或文件1. 停用 Swap2. 刪…

取子串(指針)

#include <stdio.h> #include <string.h>char* substr(char *s, int startloc, int len) {static char result[51]; // 定義一個足夠大的靜態數組來存儲結果static char result1[] {N,U,L,L,\0};int i, j;// 檢查startloc是否在字符串的范圍內if (startloc < 1…

「Mac暢玩鴻蒙與硬件45」UI互動應用篇22 - 評分統計工具

本篇將帶你實現一個評分統計工具&#xff0c;用戶可以對多個選項進行評分。應用會實時更新每個選項的評分結果&#xff0c;并統計平均分。這一功能適合用于問卷調查或評分統計的場景。 關鍵詞 UI互動應用評分統計狀態管理數據處理多目標評分 一、功能說明 評分統計工具允許用…

類與對象的理解

面向對象中兩個重要的概念&#xff1a;類與對象 類 簡單理解&#xff0c;它指的是類型或者分類或某個模塊 比如&#xff1a;人類、動物類……&#xff1b;入公司的入職單&#xff0c;沒寫上任何人的情況下 對象 簡單理解&#xff0c;它指的具體的個體 備注&#xff1a;對…

遞歸實現指數型枚舉(遞歸)

92. 遞歸實現指數型枚舉 - AcWing題庫 每個數有選和不選兩種情況 我們把每個數看成每層&#xff0c;可以畫出一個遞歸搜索樹 葉子節點就是我們的答案 很容易寫出每dfs函數 dfs傳入一個u表示層數 當層數大于我們n時&#xff0c;去判斷每個數字的選擇情況&#xff0c;輸出被選…

Linux相關概念和易錯知識點(25)(信號原理、操作系統的原理、volatile)

目錄 1.信號的產生 &#xff08;1&#xff09;kill &#xff08;2&#xff09;raise、abort 2.對block、pending、handler表的管理 &#xff08;1&#xff09;信號集&#xff08;sigset_t&#xff09; &#xff08;2&#xff09;block表的管理 ①操作相關的函數 ②sigpr…

opencv中的色彩空間及其轉換

在 OpenCV 中&#xff0c;色彩空間&#xff08;Color Space&#xff09;指的是表示顏色的一種方式&#xff0c;或是用數學模型對顏色的表達。不同的色彩空間采用不同的方式來描述顏色的三要素&#xff08;如亮度、飽和度、色調&#xff09;&#xff0c;因此可以在不同的應用場景…

OPPO 數據分析面試題及參考答案

如何設計共享單車數據庫的各個字段? 對于共享單車的數據庫設計,首先考慮用戶相關的字段。用戶表可以包含用戶 ID,這是一個唯一標識符,用于區分不同用戶;姓名,記錄用戶的真實姓名;聯系方式,比如手機號碼,方便在出現問題時聯系用戶;注冊時間,記錄用戶何時開始使用共享…

在Ubuntu下運行QEMU仿真FreeBSD riscv64系統

在Ubuntu下運行QEMU仿真FreeBSD riscv64系統 突發奇想&#xff0c;嘗試在Ubuntu下運行QEMU仿真FreeBSD riscv64系統&#xff0c; 參考這篇文檔&#xff1a;手把手教你在QEMU上運行RISC-V Linux_qemu 運行 .bin-CSDN博客 并參考FreeBSD的Wiki&#xff1a;riscv - FreeBSD Wik…

大模型微調---Prompt-tuning微調

目錄 一、前言二、Prompt-tuning實戰2.1、下載模型到本地2.2、加載模型與數據集2.3、處理數據2.4、Prompt-tuning微調2.5、訓練參數配置2.6、開始訓練 三、模型評估四、完整訓練代碼 一、前言 Prompt-tuning通過修改輸入文本的提示&#xff08;Prompt&#xff09;來引導模型生…

Visual Studio 、 MSBuild 、 Roslyn 、 .NET Runtime、SDK Tools之間的關系

1. Visual Studio Visual Studio 是一個集成開發環境&#xff08;IDE&#xff09;&#xff0c;為開發者提供代碼編寫、調試、測試和發布等功能。它內置了 MSBuild、Roslyn 和 SDK Tools&#xff0c;并提供圖形化界面來方便開發者進行項目管理和構建。與其他組件的關系&#xf…

Winnows基礎(2)

Target 了解常見端口及服務&#xff0c;熟練cmd命令&#xff0c;編寫簡單的 .bat 病毒程序。 Trail 常見服務及端口 80 web 80-89 可能是web 443 ssl心臟滴血漏洞以及一些web漏洞測試 445 smb 1433 mssql 1521 oracle 2082/2083 cpanel主機管理系統登陸&#xff08;國外用的…

Edge Scdn用起來怎么樣?

Edge Scdn&#xff1a;提升網站安全與性能的最佳選擇 在當今互聯網高速發展的時代&#xff0c;各種網絡攻擊層出不窮&#xff0c;特別是針對網站的DDoS攻擊威脅&#xff0c;幾乎每個行業都可能成為目標。為了確保網站的安全性與穩定性&#xff0c;越來越多的企業開始關注Edge …

通信技術以及5G和AI保障電網安全與網絡安全

摘 要&#xff1a;電網安全是電力的基礎&#xff0c;隨著智能電網的快速發展&#xff0c;越來越多的ICT信息通信技術被應用到電力網絡。本文分析了歷史上一些重大電網安全與網絡安全事故&#xff0c;介紹了電網安全與網絡安全、通信技術與電網安全的關系以及相應的電網安全標準…

梯度(Gradient)和 雅各比矩陣(Jacobian Matrix)的區別和聯系:中英雙語

雅各比矩陣與梯度&#xff1a;區別與聯系 在數學與機器學習中&#xff0c;梯度&#xff08;Gradient&#xff09; 和 雅各比矩陣&#xff08;Jacobian Matrix&#xff09; 是兩個核心概念。雖然它們都描述了函數的變化率&#xff0c;但應用場景和具體形式有所不同。本文將通過…

時間序列預測論文閱讀和相關代碼庫

時間序列預測論文閱讀和相關代碼庫列表 MLP-based的時間序列預測資料DLinearUnetTSFPDMLPLightTS 代碼庫以及論文庫&#xff1a;Time-Series-LibraryUnetTSFLightTS MLP-based的時間序列預測資料 我會定期把我的所有時間序列預測論文有關的資料鏈接全部同步到這個文章中&#…