1. 程式人生 > >CUDA統一記憶體、零複製記憶體、鎖頁記憶體

CUDA統一記憶體、零複製記憶體、鎖頁記憶體

CUDA 6.0以後,出現了:統一記憶體,unified memory,其具有以下特性:
1 其宣告有以下兩種方式:
a 使用關鍵字managed,可選的和device,一起使用,比如:device managed int ret[1000];
b 使用函式cudaMallocManaged():
int *ret;
cudaMallocManaged(&ret,1000*sizeof(int));
cudaFree(ret);

2 使用上面兩種方式宣告的記憶體,能夠被cpu和gpu同時訪問,不需要顯式的在cpu和gpu之間使用cudaMemcpy()在cpu和gpu之間進行記憶體傳輸
3 cuda的managed記憶體和其zero-copy memory之間的區別在於:
a zero-copy分配的是CPU中的固定頁記憶體(pinned memory in cpu system ),這種方式下,根據從哪裡索引這個記憶體,其速度將更快或者更慢,零複製記憶體
實際上是一種特殊形式的記憶體對映,它允許你將主機記憶體直接對映到GPU記憶體空間上。
b 統一記憶體,將記憶體與執行空間分開,這樣所有的資料訪問都很快

cuda中鎖頁記憶體和零複製記憶體
鎖頁記憶體允許GPU上的DMA控制器請求主機傳輸,而不需要CPU主機處理器的參與
CPU仍然可以訪問上述鎖頁記憶體,但是此記憶體是不能移動或換頁到磁碟上的
在GPU上分配的記憶體預設都是鎖頁記憶體,這只是因為GPU不支援將記憶體交換到磁碟上
在主機上分配鎖頁記憶體有以下兩種方式:
a 使用特殊的cudaHostAlloc函式,對用的釋放記憶體使用cudaFreeHost函式進行記憶體釋放
b 使用常規的malloc函式,然後將其註冊為(cudaHostRegister)鎖頁記憶體,註冊為鎖頁記憶體只是設定一些內部標誌位以確保記憶體不被換出,並告訴CUDA驅動程式,該記憶體為鎖頁記憶體,可以直接使用而不需要使用臨時緩衝區

使用鎖頁記憶體需要注意以下幾點:
a 不能分配太多,太多的話會降低系統整體效能
b 鎖頁記憶體和視訊記憶體之間的拷貝速度是6G/s,普通的記憶體和視訊記憶體之間的拷貝速度是3G/s(視訊記憶體之間的拷貝速度是30G/s,CPU之間的速度是10G/s)
c 使用cudaHostAlloc函式分配記憶體,其內的內容需要從普通記憶體拷貝到鎖頁記憶體中,因此會存在:這種拷貝會帶來額外的CPU記憶體拷貝時間開銷,CPU需要把資料從可分頁記憶體拷貝到鎖頁,但是採用cudaHostRegister把普通記憶體改為鎖頁記憶體,則不會帶來額外的cpu記憶體拷貝時間開銷,因為cudaHostAlloc的做法是先分配鎖頁記憶體,這時裡面是沒有資料的,那麼需要將一般的記憶體拷貝過來,而對於cudaHostRegister記憶體,他是之間就使用malloc分配好的,cudaHostRegister只是設定一些內部標誌位以確保其不被換出,相當於只是更改了一些標誌位,就不存在前面說的資料拷貝
d 在某些裝置上,裝置儲存器和主機鎖頁儲存器之間的資料拷貝和核心函式可以併發執行
e 在某些裝置上,可以將主機的鎖頁記憶體對映到裝置地址空間,減少主機和裝置之間的資料拷貝,要訪問資料的時候不是像上面那那樣將資料拷貝過來,而是直接通過主機匯流排到主機上訪問 ,使用cudaHostAlloc分配時傳入cudaHostAllocMapped,或者使用cudaHostRegister時傳入cudaHostRegisterMapped標籤
f 預設情況下,鎖頁記憶體是可以快取的。在使用cudaHostAlloc分配時傳入cudaHostAllocWriteCombined標籤,將其標定為寫結合,這意味著該記憶體沒有一級二級快取,這樣有利用主機寫該記憶體,而如果主機讀取的話,速度將會極其慢,所以這種情況下的記憶體應當只用於那些主機只寫的儲存器

鎖頁記憶體分配的記憶體,也有對應的三種形式:

cudaMemcpyToSymbol可以將資料從host拷貝到global,cudaMemcpy也是從host到>global,這種情況下二個函式有什麼區別嗎?
和各位大佬討論一下後,和大家分享一下~

cudaMemcpyToSymbol也有將資料從host拷貝到global的功能,以前只用過這個函式拷貝constant memory。拷貝方式的不同是由目的記憶體申請的方式決定的。申請的是device記憶體,cudaMemcpyToSymbol拷貝就是從host拷貝到global。申請的是constant記憶體,cudaMemcpyToSymbol拷貝就是從host拷貝到constant memory。

CUDA中與記憶體相關的一些函式:
cudaMemcpyToSymbol(主要用於將資料從host拷貝到device的constant memory,但也可以用於將資料從host拷貝到device的global區)

cudamalloc分配,對應使用cudaFree釋放,使用cudaMemcpy在裝置和主機之間進行資料傳輸

cudaHostAlloc(核心是,在主機上分配鎖頁記憶體,對應的釋放函式cudaFreeHost,opencv中的資料結構CudaMem是使用的該函式進行記憶體分配,其優勢有:
d 在某些裝置上,裝置儲存器和主機鎖頁儲存器之間的資料拷貝和核心函式可以併發執行
e 在某些裝置上,可以將主機的鎖頁記憶體對映到裝置地址空間,減少主機和裝置之間的資料拷貝,要訪問資料的時候不是像上面那那樣將資料拷貝過來,而是直接通過主機匯流排到主機上訪問 ,使用cudaHostAlloc分配時傳入cudaHostAllocMapped,或者使用cudaHostRegister時傳入cudaHostRegisterMapped標籤
f 預設情況下,鎖頁記憶體是可以快取的。在使用cudaHostAlloc分配時傳入cudaHostAllocWriteCombined標籤,將其標定為寫結合,這意味著該記憶體沒有一級二級快取,這樣有利用主機寫該記憶體,而如果主機讀取的話,速度將會極其慢,所以這種情況下的記憶體應當只用於那些主機只寫的儲存器)

這裡講下個人對cudaMalloc和cudaHostAlloc的理解:
cudaHostAlloc個人認為主要是在主機和裝置之間進行資料互動的時候使用效率會比cudaMalloc高,另外需要注意的是,cudaHostAlloc分配的是主機上的記憶體,裝置通過某種方式進行訪問,cudaMalloc分配的是裝置上的記憶體,其需要把相應的內容使用cudaMemcpy將資料從主機拷貝到裝置,cudaHostAlloc函式的第三個引數有三個可選列舉,分別是:
cudaHostAllocDefault:
cudaHostAllocMapped(對應到cudaHostRegister函式是cudaHostRegisterMapped):在該標誌位下,將會分配一塊可對映到裝置地址空間的分頁鎖定主機儲存器。這塊儲存器有兩個地址,一個是主機儲存器上的,一個是裝置儲存器上的,主機指標是cudaHostAlloc返回,裝置指標通過cudaHostGetDevicePointer函式檢索到,可以使用這個裝置指標在核心中訪問這塊儲存器,但是也有例外:
在支援統一虛擬地址空間的裝置上,主機通過cudaHostAlloc和cudaMalloc分配的記憶體使用,單個虛擬地址空間,指標指向哪個儲存空間(主機儲存器或任意一個裝置儲存器),可以通過cudaPointerGetAttributes確定:
當在使用統一地址空間的裝置間複製儲存器時,cudaMemcpy*中的cudaMemcpyKind引數沒有作用,可設定成cudaMemcpyDefault
通過cudaHostAlloc分配的儲存器預設在使用統一地址空間的裝置間是可分享的,cudaHostAlloc返回的指標可被在這些裝置上的核心直接使用,而不需要cudaHostGetDevicePointer獲得裝置指標

cudaHostAllocWriteCombined:主要是去掉一級二級快取,這樣主機寫資料的時候會很快,而主機讀取的時候極慢,所以用於就是用處主機只寫不讀

cudaHostRegister:是得到鎖頁記憶體的另一種方式,和cudaHostAlloc的區別是,cudaHostRegister是將現有的記憶體標記成鎖頁記憶體
cudaMallocPitch(opencv中的GpuMat使用的該函式對影象進行記憶體分配)

注意的是,位於同一個Block中的執行緒才能實現通訊,不同Block中的執行緒不能通過共享記憶體、同步進行通訊,而應採用原子操作或主機介入。

相關推薦

CUDA統一記憶體複製記憶體記憶體

CUDA 6.0以後,出現了:統一記憶體,unified memory,其具有以下特性: 1 其宣告有以下兩種方式: a 使用關鍵字managed,可選的和device,一起使用,比如:device managed int ret[1000]; b 使用函

CUDA記憶體

主機處理器(CPU)支援虛擬記憶體系統,允許程式設計師使用比實際空間更大的記憶體空間,可以認為虛擬記憶體是記憶體容量受限留下的後遺症。 大多數系統中虛擬記憶體空間被劃分成許多頁,它們是定址的單元,頁的大小至少4096個位元組。虛擬定址能使一個連續的虛擬地址空間對映到實體

資料探勘實驗(一)資料規範化【最小-最大規範化-均值規範化小數定標規範化】

本文程式碼均已在 MATLAB R2019b 測試通過,如有錯誤,歡迎指正。 [toc] ## 一、資料規範化的原理 資料規範化處理是資料探勘的一項基礎工作。不同的屬性變數往往具有不同的取值範圍,數值間的差別可能很大,不進行處理可能會影響到資料分析的結果。為了消除指標之間由於取值範圍帶來的差異,需要進行標準化

作業系統核心原理-5.記憶體管理(中):分記憶體管理

  在上一篇介紹的幾種多道程式設計的記憶體管理模式中,以交換記憶體管理最為靈活和先進。但是這種策略也存在很多重大問題,而其中最重要的兩個問題就是空間浪費和程式大小受限。那麼有什麼辦法可以解決交換記憶體存在的這些問題呢?答案是分頁,它是我們解決交換缺陷的“不二法門”。 一、分頁記憶體管理 1.1 解決問題之

非同步記憶體直接複製及流處理複製對比

#include<iostream> #include<cuda.h> #include<cuda_runtime.h> using namespace std; template<const int n> __device_

CUDA進階第六篇-GPU資源(視訊記憶體控制代碼等)管理

最近在加速一個影象演算法,符合《CUDA進階第五篇-如何估算出程式的GPU加速比》中的第二種情況,程式由核函式和GPU API實現,但是資源管理特別差,視訊記憶體和控制代碼在程式中使用時才申請。每次函式執行都要申請和釋放一遍,非常耗費時間。優化方案一:C++重構我想到的第一個

關於Class物件類載入機制虛擬機器執行時記憶體佈局的全面解析和推測

簡介: 本文是對Java的類載入機制,Class物件,反射原理等相關概念的理解、驗證和Java虛擬機器中記憶體佈局的一些推測。本文重點講述瞭如何理解Class物件以及Class物件的作用。 歡迎探討,如有錯誤敬請指正 如需轉載,請註明出處 http://www.cnblogs.com/nul

11.1 js中級,資料型別資料儲存方式作用域記憶體空間的區別以及例識別。

一. 基本資料型別和引用資料型別的區別。     1.基本資料型別:基本資料型別就是簡單的操作值。     2.引用資料型別:就是把引用的地址賦給變數。   堆記憶體:     就是存放程式碼塊的,存放形式有兩種       1)物件以鍵值對的形式存放       2)引用資料型別的賦值,是把引用

個人筆記:ORACLE大記憶體hugepage和SGAPGA的經驗,SGA並不是越大越好

背景:ORACLE 11.2,SGA 64G,PGA 8G,壓測出現作業系統記憶體耗盡WARNING: Heavy swapping observed on system in last 5 mins.pct of memory swapped in [1.94%] pct of memory swapped

Redis記憶體資料庫命令大全——字串雜湊

個人原創,簡約實戰無廢話,歡迎大家轉載,不足之處期待您在留言處指出,謝謝! 在window上將redis安裝到服務中,redis-server --service-install  redis.windows-service.conf 一 字串型別鍵值操作命令 2 glob

解釋記憶體中的棧(stack)堆(heap)和靜態儲存區的用法。

String str = new String(“hello”); 答:通常我們定義一個基本資料型別的變數,一個物件的引用,還有就是函式呼叫的現場儲存都使用記憶體中的棧空間;而通過new關鍵字和構造器建立的物件放在堆空間;程式中的字面量(literal)如直接書寫的100、“hello”和常

Java記憶體管理之類似-Xms-Xmx 這些引數的含義

Java記憶體管理之類似-Xms、-Xmx 這些引數的含義 答: 1.堆記憶體分配: JVM 初始分配的記憶體由**-Xms** 指定,預設是實體記憶體的 1/64; JVM 最大分配的記憶體由**-Xmx** 指定,預設是實體記憶體的 1/4; 預設空餘

Direct3D基礎——預備知識:多重取樣畫素格式記憶體交換鏈和頁面置換深度快取頂點運算裝置效能

多重取樣 用畫素矩陣表示影象的時候往往會出現塊狀效應,多重取樣便是一項用於平滑塊狀影象的技術。 圖片來自:DirectX9.03D遊戲開發程式設計基礎 左邊那條是一條鋸齒線,右邊是一條經過取樣的反走樣線,看上去要平滑的多。 D3DMULTISAMPLE_TYPE列舉型別包含

JVM (三)--記憶體模型變數可見性指令重排記憶體屏障

Java記憶體模型 Java記憶體模型(JMM):Java定義的一中抽象規範,用來遮蔽不同硬體和作業系統的記憶體訪問差異,讓Java程式在不同平臺下都能達到一致的記憶體訪問效果。 Java記憶體圖示: 1、主記憶體:執行緒共享記憶體,執行緒讀寫訪問較慢; 包括方法區和Jav

Java記憶體區域(堆區虛擬機器棧本地方法棧程式計數器和方法區)和GC機制

目錄 Java垃圾回收概況 Java記憶體區域 Java物件的訪問方式 Java記憶體分配機制 Java GC機制 垃圾收集器 Java垃圾回收概況   Java GC(Garbage Collection,垃圾收集,垃圾回收)機制,是Java與C

6LwIP協議規範翻譯——緩衝及記憶體管理

6、緩衝及記憶體管理 在一個通訊系統中,記憶體緩衝管理系統必須容納各種大小的緩衝資料,其範圍從包含具有數百個位元組的資料的全尺寸TCP段到只有幾個位元組的短ICMP回覆包。此外,為了避免拷貝,應該讓資料內容緩衝駐留不被網路子系統管理的記憶體中。例如應用程式記憶體或或者ROM。 6.1、包緩衝——pbufs

名詞解釋:arm記憶體空間arm地址空間與arm實體記憶體

看過了一些資料,感覺這三個名詞容易混淆,以下是我自己的理解。 arm與powerpc兩種處理器跟x86不同,arm與powerpc一樣,它們的外設I/O埠是統一編址的,即與實體記憶體等外設統一編址在4GB的地址空間中(32為處理器)。而x86是將記憶體單獨編址在一個地址空間,外設I/O埠在另外的

Java虛擬機器7:記憶體溢位和記憶體洩露並行和併發Minor GC和Full GCClient模式和Server模式的區別

記憶體溢位和記憶體洩露的區別 1、記憶體溢位 記憶體溢位指的是程式在申請記憶體的時候,沒有足夠大的空間可以分配了。 2、記憶體洩露 記憶體洩露指的是程式在申請記憶體之後,沒有辦法釋放掉已經申請到記憶體,它始終佔用著記憶體,即被分配的物件可達但無用。記憶體洩露一般都是因

JavaScript基礎總結深入(資料型別資料_變數_記憶體物件函式回撥函式this)

資料型別 1、分類 JavaScript 資料型別分為兩大類,分別為:基本型別,又稱為值型別;物件型別,又稱為引用型別。 基本(值)型別 String:任意字元 Number:任意的數字 boolean: true/false undefined: undefi

面試問題:你瞭解Java記憶體模型麼(Java789記憶體模型的區別)

Java記憶體模型是每個java程式設計師必須掌握理解的,這是Java的核心基礎,對我們編寫程式碼特別是併發程式設計時有很大幫助。由於Java程式是交由JVM執行的,所以我們在談Java記憶體區域劃分的時候事實上是指JVM記憶體區域劃分。 首先,我們回顧一下Java程式執行