caffe的data_reader.cpp分析一下干了点什么
首先说明:下面的内容不一定对
类body:
变量:LayerParameter param_ :它里面放的是:body传进来的layerparameter的参数;
BlockingQueue<shared_ptr<QueuePair> > new_queue_pairs_:这是一个队列,它里面放的是一个队列对指针,
它的初始化:由传入的layerparameter参数赋值param_变量,并开启一个相应的进程;
它的析构函数:让进程停下来;
开启的这个进程它会干什么呢??用来读数据吧。
类data_reader:
变量:shared_ptr<QueuePair> queue_pair_:它是一个队列对的指针,并且用 prefetch*batch_size QueuePair 初始化了指向的queuePair 的实例 ,即里面的 free_ 队列的大小;
shared_ptr<Body> body_: 它是一个类body的指针,
map<const string, boost::weak_ptr<DataReader::Body> > bodies_: 它是一个map的容器,
其中的它键值:网络层的名字+源数据的路径表示,
而它对应的值:是一个指 针,指向了
在data_reader类的初始化时,它传入一个参数LayerParameter,下面是它做的事情:
1,把它的队列对指针queue_pair_ ,并且用 prefetch*batch_size QueuePair 初始化了指向的queuePair 的实例;
2,让body_的指针指向一个用LayerParameter初始化的body指针,并且向它指向的body里的变量阻塞队列new_queue_pairs_里压入一个值:为queue_pair_。
3. 初始化上面的参数bodies_, 它的键值为相关的网络层的名字+源数据的路径表示,而值为:与body_相对应的弱指针。
它的析构函数做的事:
1,把body_指向的空间释放掉,2,把 bodies_ 内的键-值 删除掉,因为里面的弱指针已经过期了。
类queuePair:
变量: BlockingQueue<Datum*> free_; 它是一个存放 datum指针的阻塞队列;
BlockingQueue<Datum*> full_;它也是一个存放 datum指针的阻塞队列;
它的初始化为:初始化一定大小size(传入的参数)的free_的空间;
它的析构函数做的事情:释放掉free里的指针所指向的内存空间,并且把free_的阻塞队列清空;
(它都没有管full_的事情啊,)
还有不懂的地方啊,先粘上吧;;;fuck.
data_reader.hpp
#ifndef CAFFE_DATA_READER_HPP_
#define CAFFE_DATA_READER_HPP_ #include <map>
#include <string>
#include <vector> #include "caffe/common.hpp"
#include "caffe/internal_thread.hpp"
#include "caffe/util/blocking_queue.hpp"
#include "caffe/util/db.hpp" namespace caffe { /**
16 * @brief Reads data from a source to queues available to data layers.
17 * A single reading thread is created per source, even if multiple solvers
18 * are running in parallel, e.g. for multi-GPU training. This makes sure
19 * databases are read sequentially, and that each solver accesses a different
20 * subset of the database. Data is distributed to solvers in a round-robin
21 * way to keep parallel training deterministic.
22 */
class DataReader {
public:
explicit DataReader(const LayerParameter& param);
~DataReader(); inline BlockingQueue<Datum*>& free() const { //返回queue_pair_指向的queuepair里的free_阻塞队列;
return queue_pair_->free_;
}
inline BlockingQueue<Datum*>& full() const { //返回queue_pair_指向的queuepair里的full_阻塞队列;
return queue_pair_->full_;
} protected:
// Queue pairs are shared between a body and its readers
class QueuePair {
public:
explicit QueuePair(int size); //它初始化时,会为free_阻塞队列里push进去size个 Datum*;
~QueuePair(); //做的就是:把free_与full_里的指针指向的空间释放掉; BlockingQueue<Datum*> free_;
BlockingQueue<Datum*> full_; DISABLE_COPY_AND_ASSIGN(QueuePair);
}; // A single body is created per source
class Body : public InternalThread {
public:
explicit Body(const LayerParameter& param);
virtual ~Body(); protected:
void InternalThreadEntry(); //定义的入口函数,就是说对于body来说 ,这个线程是干什么的; ,它根据Layerparameter里的路径读取读据到new_queue_pairs_里的指针指向的queuepair中;
void read_one(db::Cursor* cursor, QueuePair* qp); const LayerParameter param_;
BlockingQueue<shared_ptr<QueuePair> > new_queue_pairs_; //这个阻塞队列里的不同的元素与solver_count有关系啊? ,初始化时,就把queue_pair_放进去了啊; friend class DataReader; DISABLE_COPY_AND_ASSIGN(Body);
}; // A source is uniquely identified by its layer name + path, in case
// the same database is read from two different locations in the net.
static inline string source_key(const LayerParameter& param) { //它做的就是形成一个字符串;
return param.name() + ":" + param.data_param().source();
} const shared_ptr<QueuePair> queue_pair_;
shared_ptr<Body> body_; static map<const string, boost::weak_ptr<DataReader::Body> > bodies_; DISABLE_COPY_AND_ASSIGN(DataReader);
}; } // namespace caffe #endif // CAFFE_DATA_READER_HPP_
data_reader.cpp
#include <boost/thread.hpp>
#include <map>
#include <string>
#include <vector> #include "caffe/common.hpp"
#include "caffe/data_reader.hpp"
#include "caffe/layers/data_layer.hpp"
#include "caffe/proto/caffe.pb.h" namespace caffe { using boost::weak_ptr; map<const string, weak_ptr<DataReader::Body> > DataReader::bodies_;
static boost::mutex bodies_mutex_; DataReader::DataReader(const LayerParameter& param)
: queue_pair_(new QueuePair( //
param.data_param().prefetch() * param.data_param().batch_size())) {
// Get or create a body
boost::mutex::scoped_lock lock(bodies_mutex_);
string key = source_key(param);
weak_ptr<Body>& weak = bodies_[key];
//boost::weak_ptr 必定总是通过 boost::shared_ptr 来初始化的。一旦初始化之后,它基本上只提供一个有用的方法: lock()。
//此方法返回的boost::shared_ptr 与用来初始化弱指针的共享指针共享所有权。 如果这个共享指针不含有任何对象,返回的共享指针也将是空的。
//expired()用于检测所管理的对象是否已经释放;lock()用于获取所管理的对象的强引用指针。
body_ = weak.lock();
if (!body_) {
body_.reset(new Body(param));
bodies_[key] = weak_ptr<Body>(body_);
}
body_->new_queue_pairs_.push(queue_pair_);
} DataReader::~DataReader() {
string key = source_key(body_->param_);
body_.reset();
boost::mutex::scoped_lock lock(bodies_mutex_);
if (bodies_[key].expired()) {
bodies_.erase(key); //删除一个元素;
}
} // DataReader::QueuePair::QueuePair(int size) {
// Initialize the free queue with requested number of datums
for (int i = ; i < size; ++i) {
free_.push(new Datum());
}
} DataReader::QueuePair::~QueuePair() { //释放掉内存;
DataReader::QueuePair::~QueuePair() { //释放掉内存;
Datum* datum;
while (free_.try_pop(&datum)) {
delete datum;
}
while (full_.try_pop(&datum)) {
delete datum;
}
} // DataReader::Body::Body(const LayerParameter& param)
: param_(param),
new_queue_pairs_() {
StartInternalThread();
} DataReader::Body::~Body() {
StopInternalThread();
} void DataReader::Body::InternalThreadEntry() {
shared_ptr<db::DB> db(db::GetDB(param_.data_param().backend())); //我真没有看到db::DB的构造函数这样的初始化啊;
db->Open(param_.data_param().source(), db::READ); //创建环境并打开;
shared_ptr<db::Cursor> cursor(db->NewCursor()); //创建了一个cursor用于读取;
vector<shared_ptr<QueuePair> > qps; //从下面的代码可以看出里面装的是阻塞队列 new_queue_pqirs里的指针;
try {
int solver_count = param_.phase() == TRAIN ? Caffe::solver_count() : ; // To ensure deterministic runs, only start running once all solvers
// are ready. But solvers need to peek on one item during initialization,
// so read one item, then wait for the next solver.
for (int i = ; i < solver_count; ++i) { //这个第一个数据是不是特别呢?,还是为了让cursor移动到first position?
shared_ptr<QueuePair> qp(new_queue_pairs_.pop()); //初始化为new_queue_pairs_队列里的第一个元素(里面放的是queuepair的指针;
read_one(cursor.get(), qp.get()); //不同的solver对应的数据在database里是连续存储的??这个solver_count到底是什么东西?
qps.push_back(qp); //在vector的尾部追加一个数据;
}
// Main loop
while (!must_stop()) { // 有点不明白什么时候退出循环;
for (int i = ; i < solver_count; ++i) {
read_one(cursor.get(), qps[i].get());
}
// Check no additional readers have been created. This can happen if
// more than one net is trained at a time per process, whether single
// or multi solver. It might also happen if two data layers have same
// name and same source.
CHECK_EQ(new_queue_pairs_.size(), );
}
} catch (boost::thread_interrupted&) {
// Interrupted exception is expected on shutdown
}
} // void DataReader::Body::read_one(db::Cursor* cursor, QueuePair* qp) {
Datum* datum = qp->free_.pop(); //可以看出free_与full_共用一组地址;
// TODO deserialize in-place instead of copy?
datum->ParseFromString(cursor->value()); //cursor的value函数返回string形式的data值;
qp->full_.push(datum); // go to the next iter
cursor->Next();
if (!cursor->valid()) { //意思就是,当valid_值(valid()函数返回的)为false,说明没有找到,从数据开始,重新找)
DLOG(INFO) << "Restarting data prefetching from start.";
cursor->SeekToFirst(); //把curso移动到first位置;
}
} } // namespace caffe
caffe的data_reader.cpp分析一下干了点什么的更多相关文章
- Recovery启动流程(3)--recovery.cpp分析
转载请注明来源:cuixiaolei的技术博客 这篇文章主要通过分析高通recovery目录下的recovery.cpp源码,对recovery启动流程有一个宏观的了解.MTK和高通的recovery ...
- Recovery启动流程--recovery.cpp分析
这篇文章主要通过分析高通recovery目录下的recovery.cpp源码,对recovery启动流程有一个宏观的了解. 当开机以后,在lk阶段,如果是recovery,会设置boot_into_r ...
- caffe layer层cpp、cu调试经验和相互关系
对于layer层的cpp文件,你可以用LOG和printf.cout进行调试,cu文件不能使用LOG,可以使用cout,printf. 对于softmaxloss的layer层,既有cpp文件又有cu ...
- Caffe 激励层(Activation)分析
Caffe_Activation 一般来说,激励层的输入输出尺寸一致,为非线性函数,完成非线性映射,从而能够拟合更为复杂的函数表达式激励层都派生于NeuronLayer: class XXXlayer ...
- Caffe 源碼閱讀(三) caffe.cpp
补:主要函数运行顺序: main>>GetBrewFunction>>train>>Solve 從main函數說起: 1.gflags庫中爲main函數設置usag ...
- 从零开始山寨Caffe·捌:IO系统(二)
生产者 双缓冲组与信号量机制 在第陆章中提到了,如何模拟,以及取代根本不存的Q.full()函数. 其本质是:除了为生产者提供一个成品缓冲队列,还提供一个零件缓冲队列. 当我们从外部给定了固定容量的零 ...
- caffe: fuck compile error again : error: a value of type "const float *" cannot be used to initialize an entity of type "float *"
wangxiao@wangxiao-GTX980:~/Downloads/caffe-master$ make -j8find: `wangxiao/bvlc_alexnet/spl': No suc ...
- caffe︱深度学习参数调优杂记+caffe训练时的问题+dropout/batch Normalization
一.深度学习中常用的调节参数 本节为笔者上课笔记(CDA深度学习实战课程第一期) 1.学习率 步长的选择:你走的距离长短,越短当然不会错过,但是耗时间.步长的选择比较麻烦.步长越小,越容易得到局部最优 ...
- ubuntu16.04 caffe(GPU模式)安装
历时5天终于完成了,配置中出现了各种各样的Error,这里记录一下,希望能为正在安装的人提供一点帮助. 配置中主要参考博客:http://blog.csdn.net/yhaolpz/article/d ...
随机推荐
- python 拷贝文件夹下所有的文件到指定文件夹(不包括目录)
1.随便简单些写了一下.直接粘结代码,只是简单的实现一下,还很多需要完善和扩展的地方,比如忽略掉后缀文件,删除文件 如果排除的某些的话可以用: sourceF.find('.后缀')>0 2.注 ...
- load-on-startup
在servlet的配置当中,<load-on-startup>1</load-on-startup>,一般出现在启动线程的servlet当中 含义是: 标记容器是否在启动的时候 ...
- 【转】SVN提示:由于目标机器积极拒绝,无法连接 的解决方法
转载地址:http://wxiaolei.blog.163.com/blog/static/1038760120133108180596/ 安装完TSVN之后,checkout时报错,并且后来在cmd ...
- PL/SQL注册码
code:j6stndb9tk72xfbhbqczcdqnjd8lyj466n number:882851 ps:xs374ca
- 关于Animation动画事件的几项测试
测试版本unity5.3.4 1.当帧率不足时,Animation会跳帧,假如跳帧超过动画事件的帧,动画事件也会执行. 2.当Animation混合时,混合中的动画不管哪个当前有动画事件,都会执行. ...
- python 数据加密以及生成token和token验证
代码如下: # -*- coding: utf-8 -*- from passlib.apps import custom_app_context as pwd_context import conf ...
- linux学习建议
给初学者的建议 注意事项: 1 严格区分大小写,包括命令和文件夹,windows和linux的系统不太一样 2 所有内容都是以文件保存,包括硬件,文件要永久生效,都要写入文件,所以文件命令很重要 3 ...
- zoj Abs Problem
Abs Problem Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge Alice and Bob is pl ...
- Undefined symbols for architectureIOS
IOS问题解决. 现在进行老项目的编译,发现不能编译. 经过各种盲目查询,找个几个方案. 1.builde setting修改编译方式. 2.Builde Phases(修改). 2.1.库. 2.1 ...
- context是什么意思
context上下文吗,可以解释为程序运行的某一区间之内,提供对这一区间之内操作的一种对象,而且往往这一区间之内得核心操作都需要这个对象来进行 把Context翻译成“上下文”只是不直观罢了,不过也没 ...