日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > Caffe >内容正文

Caffe

Caffe Blob Dtype理解

發布時間:2023/12/4 Caffe 83 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Caffe Blob Dtype理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.luoyetx.com/2015/10/reading-caffe-2/

關于Blob:

Blob 在 Caffe 中扮演了重要的角色,用于存儲數據和網絡參數,同時也在 CPU 和 GPU 之間做了數據同步。Blob 原本在 Caffe 中被表示為一個 4 維數組 (num x channel x height x width),現在可以表示多維數組,最高維數由宏?kMaxBlobAxes?確定,目前 blob.hpp 中設置了?const int kMaxBlobAxes = 32;。Blob 類的代碼主要集中在 blob.hpp 和 blob.cpp 中。

正常的類別和數據在聲明時候,都沒有<Dtype>這種東西,這里為了配合template <typename Dtype> 才搞出了

class LossLayer: public Layer 變成了class LossLayer: public Layer<Dtype>?

const vector<Blob*>& top 變成了?const vector<Blob<Dtype>*>& top

const vector<Blob<Dtype>*>& top 說明 top是指向一系列Blob指針的集合的一個總指針。

數據與相關操作函數

Blob 類主要包括如下成員

1 2 3 4 5 6 shared_ptr<SyncedMemory> data_; // data 數據 shared_ptr<SyncedMemory> diff_; // diff 數據 shared_ptr<SyncedMemory> shape_data_; // 每一維數據的大小 vector<int> shape_; // 跟 shape_data_ 一樣 int count_; // 當前容納的數據大小 int capacity_; // 最大能夠容納的數據大小

其中 SyncedMemory 主要用來實現數據在 CPU 和 GPU 上的管理。同時 Blob 類提供一組函數來操作這些數據。

1 2 3 4 5 6 7 8 9 10 const Dtype* cpu_data() const; void set_cpu_data(Dtype* data); const int* gpu_shape() const; const Dtype* gpu_data() const; const Dtype* cpu_diff() const; const Dtype* gpu_diff() const; Dtype* mutable_cpu_data(); Dtype* mutable_gpu_data(); Dtype* mutable_cpu_diff(); Dtype* mutable_gpu_diff();

我們可以通過這些函數拿到 Blob 內部的數據包括修改 Blob 的內部數據。其中的 Dtype 是泛型類型,在定義 Blob 變量時設置的,一般為 float 或者 double。

Blob 類在內部所存儲的數據是一塊連續的內存,為了表示多維數組,shape_ 和 shapedata?記錄了每一維的大小,這樣就能夠很輕松地從給出的坐標中計算出 offset 從而得到那個點的數據。由于 Blob 主要還是用來表示 4 維數組 (最初就是這樣的),Blob 類中仍使用了?int num(); int channels(); int height(); int width();?這些函數,其實 num 等價于 shape()[0],channels 等價于 shape()[1],height 等價于 shape()[2],width 等價于 shape()[3]。計算 offset 時可以使用這四個數字或者直接給出坐標。

1 2 int offset(const int n, const int c = 0, const int h = 0, const int w = 0); int offset(const vector<int>& indices);

有了 Blob 提供的這組函數和上一組函數,我們就可以輕易地操作 Blob 內部的數據了。

動態多維數組

Blob 類可以動態改變數組的尺寸,當拓展數組導致原有內存空間不足以存放下數據時 (count?> capacity),就會重新分配內存。Blob 提供了一組 Reshape 函數來完成這個功能。

1 2 3 4 void Reshape(const int num, const int channels, const int height, const int width); // Deprecated void Reshape(const vector<int>& shape); void Reshape(const BlobShape& shape); void ReshapeLike(const Blob& other);

Blob 類在初始化時并沒有分配內存,也是通過調用 Reshape 來分配內存的。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 template <typename Dtype> void Blob<Dtype>::Reshape(const vector<int>& shape) { CHECK_LE(shape.size(), kMaxBlobAxes); // 檢查維數 count_ = 1; // 用于計算新的多維數組的大小 shape_.resize(shape.size()); // 更新維數 if (!shape_data_ || shape_data_->size() < shape.size() * sizeof(int)) { // shape_data_ 未初始化或者內存太小 shape_data_.reset(new SyncedMemory(shape.size() * sizeof(int))); } int* shape_data = static_cast<int*>(shape_data_->mutable_cpu_data()); for (int i = 0; i < shape.size(); ++i) { CHECK_GE(shape[i], 0); CHECK_LE(shape[i], INT_MAX / count_) << "blob size exceeds INT_MAX"; count_ *= shape[i]; shape_[i] = shape[i]; shape_data[i] = shape[i]; } if (count_ > capacity_) { // 內存不夠 capacity_ = count_; data_.reset(new SyncedMemory(capacity_ * sizeof(Dtype))); diff_.reset(new SyncedMemory(capacity_ * sizeof(Dtype))); } }

SyncedMemory

Blob 事實上是對 SyncedMemory 的封裝。SyncedMemory 完成了對內存的實際操作,包括數據在 CPU 和 GPU 上的同步。

1 2 3 4 5 6 7 8 9 10 enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED }; void* cpu_ptr_; // cpu 數據 void* gpu_ptr_; // gpu 數據 size_t size_; // 數據大小 SyncedHead head_; // 數據同步狀態 bool own_cpu_data_; // 是否擁有當前 cpu 數據 bool cpu_malloc_use_cuda_; // 是否采用 CUDA 來分配 CPU 數據,默認不用 bool own_gpu_data_; // 是否擁有當前 gpu 數據 int gpu_device_; // gpu 數據所在的顯卡號

SyncedMemory 內部存放了兩份數據,分別位于 CPU 和 GPU 上,用 cpu_ptr 和 gpu_ptr 表示。同時 SyncedMemory 也給出了一組函數來獲取和設置實際數據。

1 2 3 4 5 6 const void* cpu_data(); void set_cpu_data(void* data); const void* gpu_data(); void set_gpu_data(void* data); void* mutable_cpu_data(); void* mutable_gpu_data();

head_ 表示了數據的同步狀態,通過調用?to_cpu()?和?to_gpu()?來做同步。如果 head_ = UNINITIALIZED 則分配相應的內存。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 inline void SyncedMemory::to_cpu() { switch (head_) { case UNINITIALIZED: CaffeMallocHost(&cpu_ptr_, size_, &cpu_malloc_use_cuda_); // 分配內存 caffe_memset(size_, 0, cpu_ptr_); // 初始化為 0 head_ = HEAD_AT_CPU; own_cpu_data_ = true; break; case HEAD_AT_GPU: #ifndef CPU_ONLY if (cpu_ptr_ == NULL) { // 如果未初始化,則分配內存 CaffeMallocHost(&cpu_ptr_, size_, &cpu_malloc_use_cuda_); own_cpu_data_ = true; } // 復制 GPU 數據到 CPU caffe_gpu_memcpy(size_, gpu_ptr_, cpu_ptr_); head_ = SYNCED; #else NO_GPU; #endif break; case HEAD_AT_CPU: case SYNCED: break; } } inline void SyncedMemory::to_gpu() { #ifndef CPU_ONLY switch (head_) { case UNINITIALIZED: CUDA_CHECK(cudaGetDevice(&gpu_device_)); // 獲取顯卡號 CUDA_CHECK(cudaMalloc(&gpu_ptr_, size_)); // 在指定顯卡上分配內存 caffe_gpu_memset(size_, 0, gpu_ptr_); // 初始化為 0 head_ = HEAD_AT_GPU; own_gpu_data_ = true; break; case HEAD_AT_CPU: if (gpu_ptr_ == NULL) { // 未初始化就在指定顯卡上分配內存 CUDA_CHECK(cudaGetDevice(&gpu_device_)); CUDA_CHECK(cudaMalloc(&gpu_ptr_, size_)); own_gpu_data_ = true; } caffe_gpu_memcpy(size_, cpu_ptr_, gpu_ptr_); // 復制數據 head_ = SYNCED; break; case HEAD_AT_GPU: case SYNCED: break; } #else NO_GPU; #endif }

數據序列化

Blob 數據可以通過 Protobuf 來做相應的序列化操作,ToProto?和?FromProto?完成相應的序列化操作。

1 2 3 4 5 6 7 8 9 10 11 12 13 message BlobProto { optional BlobShape shape = 7; repeated float data = 5 [packed = true]; repeated float diff = 6 [packed = true]; repeated double double_data = 8 [packed = true]; repeated double double_diff = 9 [packed = true]; // 4D dimensions -- deprecated. Use "shape" instead. optional int32 num = 1 [default = 0]; optional int32 channels = 2 [default = 0]; optional int32 height = 3 [default = 0]; optional int32 width = 4 [default = 0]; }

小結

Caffe 通過 SyncedMemory 和 Blob 封裝了底層數據,為 Caffe 框架上的其他組件提供最基礎的數據抽象,后面的 Layer 參數,Net 參數以及 Solver 的參數等都是 Blob 數據,所以理解 Blob 抽象和管理數據的實現方式有助于后續 Caffe 源碼的閱讀,也是閱讀 Caffe 源碼的第一步。

總結

以上是生活随笔為你收集整理的Caffe Blob Dtype理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 黄色大片免费在线观看 | 波多野一区二区 | 久久国产精品亚洲 | 国产让女高潮的av毛片 | 亚洲www在线观看 | 奇米影视盒 | 黑人玩弄人妻一区二区三区影院 | 亚洲午夜在线观看 | 韩国精品一区 | 亚洲精品视频播放 | 少妇紧身牛仔裤裤啪啪 | av每日更新在线观看 | 日韩天堂视频 | a亚洲天堂| 日日躁夜夜躁狠狠久久av | 麻豆精品久久 | 久久99精品久久久久久园产越南 | 人人99| 在线观看黄色大片 | 欧美视频在线观看视频 | 性奶老妇 视频 | 久久伊人婷婷 | 一区二区三区视频 | 最新高清无码专区 | 成人在线播放视频 | 精品国产乱码久久久人妻 | 黑料视频在线观看 | 日韩污视频在线观看 | 午夜片在线 | 欧美性做爰大片免费 | 国产精品99无码一区二区 | 四虎国产成人永久精品免费 | 亚洲春色av | 国产精品va无码一区二区 | 三级艳丽杨钰莹三级 | 久久依人网 | 亚洲成人免费视频 | 97在线超碰 | 亚洲图片一区二区三区 | 影音先锋色小姐 | 日韩欧美在线观看视频 | 日本少妇影院 | 国产一区二区三区日韩 | 日韩一区二区免费在线观看 | 极品少妇xxxx精品少妇 | 美味的客房沙龙服务 | 欧美精品一二三 | 俄罗斯av片 | 美女又爽又黄 | 欧美综合另类 | 国产奶水涨喷在线播放 | 久久精品无码专区免费 | 日本中文字幕在线不卡 | 国产乱子伦视频一区二区三区 | 久久精品视频一区 | 日韩av资源站 | 久久综合久 | 精品熟女一区二区三区 | 亚洲8888| 天天看夜夜看 | 大香伊人| 九久久久久 | 一区二区国产在线观看 | 成人黄色在线网站 | 亚洲欧美激情在线观看 | 中文字幕女优 | 国产精品亚洲欧美 | 最新免费av网站 | 国产精品夜夜夜爽张柏芝 | 欧美在线免费播放 | 色视频免费在线观看 | 国产精品久久综合 | 欧美成在线观看 | 在线黄网站| 免费的黄色网址 | 欧美日韩国产伦理 | 一级片视频播放 | 妹子干综合| 久久久久久久久久久影院 | 都市豪门艳霸淫美妇 | 波多野结衣视频免费看 | 四虎影视永久免费观看 | 午夜视频入口 | 日韩精品国产AV | 欧美三级小说 | 青青久在线 | 亚洲午夜18毛片在线看 | youjizz中国少妇 | 成人精品久久久午夜福利 | 99热一区 | 国产综合内射日韩久 | 99av国产精品欲麻豆 | 五十路熟母 | 自拍偷拍第二页 | 高潮喷水一区二区三区 | 午夜精品久久久久久久99老熟妇 | 成人av资源站 | 伊人网综合网 | missav在线|