Caffe源码解析2:SycedMem
from:https://www.cnblogs.com/louyihang-loves-baiyan/p/5150554.html
轉(zhuǎn)載請注明出處,樓燚(yì)航的blog,http://www.cnblogs.com/louyihang?loves baiyan/
看到SyncedMem就知道,這是在做內(nèi)存同步的操作。這類個類的代碼比較少,但是作用是非常明顯的。文件對應(yīng)著syncedmem.hpp,著syncedmem.cpp
首先是兩個全局的內(nèi)聯(lián)函數(shù)。如果機器是支持GPU的并且安裝了cuda,通過cudaMallocHost分配的host memory將會被pinned,這里我谷歌了一下,pinned的意思就是內(nèi)存不會被paged out,我們知道內(nèi)存里面是由頁作為基本的管理單元。分配的內(nèi)存可以常駐在內(nèi)存空間中對效率是有幫助的,空間不會被別的進(jìn)程所搶占。同樣如果內(nèi)存越大,能被分配的Pinned內(nèi)存自然也越大。還有一點是,對于單一的GPU而言提升并不會太顯著,但是對于多個GPU的并行而言可以顯著提高穩(wěn)定性。
這里是兩個封裝過的函數(shù),內(nèi)部通過cuda來分配主機和釋放內(nèi)存的接口
inline void CaffeMallocHost(void** ptr, size_t size, bool* use_cuda) { #ifndef CPU_ONLYif (Caffe::mode() == Caffe::GPU) {CUDA_CHECK(cudaMallocHost(ptr, size));// GPU模式下cuda分配內(nèi)存*use_cuda = true;return;} #endif*ptr = malloc(size);//如果沒有cuda則通過c的malloc函數(shù)分配*use_cuda = false;CHECK(*ptr) << "host allocation of size " << size << " failed"; }inline void CaffeFreeHost(void* ptr, bool use_cuda) { #ifndef CPU_ONLYif (use_cuda) {CUDA_CHECK(cudaFreeHost(ptr));//cuda的主機內(nèi)存釋放操作return;} #endiffree(ptr);//c的釋放操作 }SyncedMemory類,首先是構(gòu)造函數(shù)和析構(gòu)函數(shù)
class SyncedMemory {public:SyncedMemory() //參數(shù)構(gòu)造函數(shù),負(fù)責(zé)初始化: cpu_ptr_(NULL), gpu_ptr_(NULL), size_(0), head_(UNINITIALIZED),own_cpu_data_(false), cpu_malloc_use_cuda_(false), own_gpu_data_(false),gpu_device_(-1) {}explicit SyncedMemory(size_t size)//帶explicit關(guān)鍵字的,單個參數(shù)構(gòu)造函數(shù),explicit禁止單參數(shù)構(gòu)造函數(shù)的隱式轉(zhuǎn)換: cpu_ptr_(NULL), gpu_ptr_(NULL), size_(size), head_(UNINITIALIZED),own_cpu_data_(false), cpu_malloc_use_cuda_(false), own_gpu_data_(false),gpu_device_(-1) {}~SyncedMemory();//其在析構(gòu)時調(diào)用的也是CaffeFreeHost這幾個函數(shù)分別是
const void* cpu_data();void set_cpu_data(void* data);const void* gpu_data();void set_gpu_data(void* data);cpu_data()主要是獲得cpu上data的地址,set_cpu_data是將cpu的data指針指向一個新的區(qū)域由data指針傳入,并且將原來申請的內(nèi)存釋放。下面兩個同理,分別是獲得gpu數(shù)據(jù)地址和set gpu數(shù)據(jù)地址。
void* mutable_cpu_data();void* mutable_gpu_data();enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };SyncedHead head() { return head_; }size_t size() { return size_; }前兩個分別是返回cpu和gpu上的data指針,并且置狀態(tài)為head_ = HEAD_AT_CPU和響應(yīng)的gpu版本。SyncedHead主要是個枚舉類型,用來設(shè)定head_的狀態(tài),head()函數(shù)即返回相應(yīng)的數(shù)據(jù)狀態(tài),而size()函數(shù)返回數(shù)據(jù)大小
#ifndef CPU_ONLYvoid async_gpu_push(const cudaStream_t& stream); #endif這是一個cuda拷貝的異步傳輸,從數(shù)據(jù)從cpu拷貝到gpu,異步傳輸是已經(jīng)假定caller會在使用之前做同步操作。
private:void to_cpu();void to_gpu();void* cpu_ptr_;void* gpu_ptr_;size_t size_;SyncedHead head_;bool own_cpu_data_;bool cpu_malloc_use_cuda_;bool own_gpu_data_;int gpu_device_;DISABLE_COPY_AND_ASSIGN(SyncedMemory);//禁止該類的拷貝與賦值 }; // class SyncedMemory其實這里的東西也不多了,to_cpu(),to_gpu()這個看名字就知道了,需要注意的是,如果head 是未被初始化的狀態(tài),那么首先需要先分配內(nèi)存,這個根據(jù)cpu和gpu視情況而定,之后再將數(shù)據(jù)從cpu或者gpu拷貝到另一處。之后函數(shù)會重新標(biāo)記Head的狀態(tài),數(shù)據(jù)是否在cpu或者在gpu中,cpu這里是簡稱,其實是主機。
cpu_ptr和gpu_ptr分別是在cpu和gpu中的數(shù)據(jù)指針,size_這就不再說了,head_之前也液晶提到過了,后面都是幾個相應(yīng)的標(biāo)記為,以及gpu的ID號
總結(jié)
以上是生活随笔為你收集整理的Caffe源码解析2:SycedMem的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MATLAB混合编程视频教程下载 SIM
- 下一篇: JPG PNG GIF BMP图片格式的