caffe学习
来源:互联网 发布:手机京东秒杀软件 编辑:程序博客网 时间:2024/05/29 12:15
初学caffe
caffe中syncedmemory简介
最近在看caffe的源码,Syncedmem类是caffe中内存分配管理的类,主要完成内存的分配和释放,以及cpu和gpu之间数据同步的函数。
1. 头文件
include “caffe/common.hpp”:此文件中主要定义了caffe的单例化接口;
include “caffe/util/math_functions.hpp”:主要定义caffe 中的数学运算函数,主要是矩阵运算;
2. 定义了两个内联函数CaffeMallocHost和CaffeFreeHost通过调用malloc()函数来实现内存的分配和释放,Syncedmem类的主要功能也由这两个函数完成。
caffe/syncedmem.hpp文件的详细介绍
#ifndef CAFFE_SYNCEDMEM_HPP_#define CAFFE_SYNCEDMEM_HPP_#include <cstdlib>#ifdef USE_MKL#include "mkl.h"#endif#include "caffe/common.hpp"namespace caffe {/*内存分配函数,如果caffe编译为cpu—only,则调用c语言中的malloc函数分配内存,如果是gpu,则调用cudaMalloc函数分配内存*/inline void CaffeMallocHost(void** ptr, size_t size, bool* use_cuda) {#ifndef CPU_ONLYif (Caffe::mode() == Caffe::GPU) { CUDA_CHECK(cudaMallocHost(ptr, size));*use_cuda = true;return;}#endif#ifdef USE_MKL *ptr = mkl_malloc(size ? size:1, 64);#else *ptr = malloc(size);#endif *use_cuda = false; CHECK(*ptr) << "host allocation of size " << size << " failed";}/*内存释放函数,cpu模式调用free(),gpu调用cudafree()*/inline void CaffeFreeHost(void* ptr, bool use_cuda) {#ifndef CPU_ONLY if (use_cuda) { CUDA_CHECK(cudaFreeHost(ptr)); return; }#endif#ifdef USE_MKL mkl_free(ptr);#else free(ptr);#endif}/** * @brief Manages memory allocation and synchronization between the host (CPU) * and device (GPU). * * TODO(dox): more thorough description. */class SyncedMemory { public: //默认构造函数 SyncedMemory(); //构造函数 explicit SyncedMemory(size_t size); //析构函数 ~SyncedMemory(); //获取cpu上的数据流 const void* cpu_data(); //设置cpu内存上的数据 void set_cpu_data(void* data); //获取gpu上的数据 const void* gpu_data(); //设置gpu上的数据 void set_gpu_data(void* data); 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_; }#ifndef CPU_ONLY void async_gpu_push(const cudaStream_t& stream);#endif private: void check_device(); //使用cpu内存 void to_cpu(); //使用gpu内存 void to_gpu(); //指向cpu内存的指针 void* cpu_ptr_; //指向gpu内存的指针 void* gpu_ptr_; 分配内存的大小 size_t size_; //同步状态 SyncedHead head_; //是否拥有cpu或gpu数据 bool own_cpu_data_; bool cpu_malloc_use_cuda_; bool own_gpu_data_; int device_; DISABLE_COPY_AND_ASSIGN(SyncedMemory);}; // class SyncedMemory} // namespace caffe#endif // CAFFE_SYNCEDMEM_HPP_
caffe/syncedmem.cpp文件详细介绍
namespace caffe {//构造函数,未初始化SyncedMemory::SyncedMemory() : cpu_ptr_(NULL), gpu_ptr_(NULL), size_(0), head_(UNINITIALIZED), own_cpu_data_(false), cpu_malloc_use_cuda_(false), own_gpu_data_(false) {#ifndef CPU_ONLY#ifdef DEBUG CUDA_CHECK(cudaGetDevice(&device_));#endif#endif}//构造函数,确定分配内存的大小,未初始化SyncedMemory::SyncedMemory(size_t size) : cpu_ptr_(NULL), gpu_ptr_(NULL), size_(size), head_(UNINITIALIZED), own_cpu_data_(false), cpu_malloc_use_cuda_(false), own_gpu_data_(false) {#ifndef CPU_ONLY#ifdef DEBUG CUDA_CHECK(cudaGetDevice(&device_));#endif#endif}//析构函数,释放内存SyncedMemory::~SyncedMemory() { check_device(); if (cpu_ptr_ && own_cpu_data_) {CaffeFreeHost(cpu_ptr_, cpu_malloc_use_cuda_); }#ifndef CPU_ONLY if (gpu_ptr_ && own_gpu_data_) {CUDA_CHECK(cudaFree(gpu_ptr_)); }#endif // CPU_ONLY} //在Hostcpu上分配内存inline void SyncedMemory::to_cpu() { check_device(); switch (head_) { //如果数据未初始化,则申请cpu内存 case UNINITIALIZED: CaffeMallocHost(&cpu_ptr_, size_, &cpu_malloc_use_cuda_); caffe_memset(size_, 0, cpu_ptr_); //数据在cpu上 head_ = HEAD_AT_CPU; own_cpu_data_ = true; break; /*若数据在gpu上,则在cpu上重新申请内存,并将gpu上的数据同步到cpu内存上,同时将数据状态设置为SYNCED(同步)*/ case HEAD_AT_GPU:#ifndef CPU_ONLY if (cpu_ptr_ == NULL) { CaffeMallocHost(&cpu_ptr_, size_, &cpu_malloc_use_cuda_); own_cpu_data_ = true; } caffe_gpu_memcpy(size_, gpu_ptr_, cpu_ptr_); head_ = SYNCED;#else NO_GPU;#endif break; case HEAD_AT_CPU: case SYNCED: break; }}//将数据copy到gpu上inline void SyncedMemory::to_gpu() { check_device();#ifndef CPU_ONLY switch (head_) { //若数据没有初始化,则在gpu上申请内存并将数据状态设置在gpu上 case UNINITIALIZED: CUDA_CHECK(cudaMalloc(&gpu_ptr_, size_)); caffe_gpu_memset(size_, 0, gpu_ptr_); head_ = HEAD_AT_GPU; own_gpu_data_ = true; break; //若数据在cpu上,在gpu上申请相同大小的内存,并将数据copy到gpu上,同时将数据状态设置为SYNCED(同步) case HEAD_AT_CPU: if (gpu_ptr_ == NULL) { 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}//将数据同步到cpu上,并返回指向data的指针const void* SyncedMemory::cpu_data() { check_device(); to_cpu(); return (const void*)cpu_ptr_;}//重新设置cpu上的数据void SyncedMemory::set_cpu_data(void* data) { check_device(); CHECK(data); //若cpu上拥有数据,则将指向该部分数据的内存释放,并将指针cpu_ptr_指向data if (own_cpu_data_) { CaffeFreeHost(cpu_ptr_, cpu_malloc_use_cuda_); } cpu_ptr_ = data; //数据状态设置为在cpu上 head_ = HEAD_AT_CPU; //原有的数据被释放掉了,状态设置为false own_cpu_data_ = false;} //返回指向gpu上数据的指针const void* SyncedMemory::gpu_data() { check_device();#ifndef CPU_ONLY to_gpu(); return (const void*)gpu_ptr_;#else NO_GPU; return NULL;#endif}//重新设置gpu上的数据void SyncedMemory::set_gpu_data(void* data) { check_device();#ifndef CPU_ONLY CHECK(data); //若gpu上含有数据,就将该部分内存释放 if (own_gpu_data_) { CUDA_CHECK(cudaFree(gpu_ptr_)); } //指针指向data gpu_ptr_ = data; //数据存放在gpu上 head_ = HEAD_AT_GPU; own_gpu_data_ = false;#else NO_GPU;#endif}//数据同步到cpu上void* SyncedMemory::mutable_cpu_data() { check_device(); to_cpu(); head_ = HEAD_AT_CPU; return cpu_ptr_;}//数据同步到gpu上void* SyncedMemory::mutable_gpu_data() { check_device();#ifndef CPU_ONLY to_gpu(); head_ = HEAD_AT_GPU; return gpu_ptr_;#else NO_GPU; return NULL;#endif}//将cpu上的数据copy到gpu上#ifndef CPU_ONLYvoid SyncedMemory::async_gpu_push(const cudaStream_t& stream) { check_device(); CHECK(head_ == HEAD_AT_CPU); if (gpu_ptr_ == NULL) { CUDA_CHECK(cudaMalloc(&gpu_ptr_, size_)); own_gpu_data_ = true; } const cudaMemcpyKind put = cudaMemcpyHostToDevice; CUDA_CHECK(cudaMemcpyAsync(gpu_ptr_, cpu_ptr_, size_, put, stream)); // Assume caller will synchronize on the stream before use head_ = SYNCED;}#endif//若有多个gpu,确认数据在哪个gpu上void SyncedMemory::check_device() {#ifndef CPU_ONLY#ifdef DEBUG int device; cudaGetDevice(&device); CHECK(device == device_); if (gpu_ptr_ && own_gpu_data_) { cudaPointerAttributes attributes; CUDA_CHECK(cudaPointerGetAttributes(&attributes, gpu_ptr_)); CHECK(attributes.device == device_); }#endif#endif}} // namespace caffe
作为初入深度学习领域的菜鸟,刚刚接触caffe和c++,写此博客的目的在于加深自己的理解和记忆,当然了在理解上可能存在错误和偏差,欢迎各位大牛多多指教!
阅读全文
0 0
- caffe学习
- caffe 学习
- caffe学习
- caffe学习
- caffe学习
- caffe学习
- caffe学习
- caffe学习
- caffe学习
- caffe学习
- Caffe caffe.pb.h 学习
- 学习Caffe(一)安装Caffe
- Caffe学习之一caffe安装
- caffe学习之一:caffe安装
- 【caffe学习】学习初探
- caffe 学习资料
- caffe学习,持续更新
- caffe学习网页推荐
- python中删除某个元素的3种方法
- CKeditor 使用方法
- POJ 3468 A Simple Problem with Integers(线段树)
- Date类、Canlendar类和DateFormat类
- Nginx学习之安装篇
- caffe学习
- 网络流,最大流
- string的子集求法
- Java Socket编程实例
- 本地存储
- 打印轻量级 web 服务的配置文件 nginx.conf 内容的行号及内容,该如何做
- 编写一个Book类 查看相同价格的对象
- 【PAT】1004. 成绩排名 (20) 浙江大学考试题
- 设计模式——单例模式和多例的区别