InternalThread
封装自boost::thread
的线程,主要用于多线程的数据获取(可以理解为solver
前向传播的同时,后台线程继续获取下一个batch
的数据集):
class InternalThread {
public:
InternalThread() : thread_() {}
virtual ~InternalThread();
//Caffe's thread local state will be initialized.
void StartInternalThread();
/** Will not return until the internal thread has exited. */
void StopInternalThread();
bool is_started() const;
protected:
virtual void InternalThreadEntry() {} // 子类实现这个方法.
/* Should be tested when running loops to exit when requested. */
bool must_stop();
private:
void entry(int device, Caffe::Brew mode, ....);
private:
shared_ptr<boost::thread> thread_;
};
下面看几个核心的函数:
void InternalThread::StartInternalThread() {
CHECK(!is_started()) << "Threads should persist and not be restarted.";
// init parameters ......
int device = 0;
int rand_seed = caffe_rng_rand();
// create new thread, and bind to method.
thread_.reset(new boost::thread(&InternalThread::entry, this, device));
//.....
}
void InternalThread::entry(int device, Caffe::Brew mode, int rand_seed,
int solver_count, bool root_solver) {
// set caffe parameter
Caffe::set_mode(mode);
Caffe::set_random_seed(rand_seed);
// 实际运行的函数, 子类根据需要去实现:
InternalThreadEntry();
}
析构函数:等待线程退出:
InternalThread::~InternalThread() {
StopInternalThread();
}
void InternalThread::StopInternalThread() {
if (is_started()) {
thread_->interrupt();
thread_->join();
}
}
使用示例如下:
template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::InternalThreadEntry() {
while (!must_stop()) {
Batch<Dtype> *batch = prefetch_free_.pop();
load_batch(batch);
prefetch_full_.push(batch);
}
}
void DataReader::Body::InternalThreadEntry() {
shared_ptr<db::DB> db(db::GetDB(param_.data_param().backend()));
db->Open(param_.data_param().source(), db::READ);
shared_ptr<db::Cursor> cursor(db->NewCursor());
vector<shared_ptr<QueuePair> > qps;
// Main loop
while (!must_stop()) {
for (int i = 0; i < solver_count; ++i) {
read_one(cursor.get(), qps[i].get());
}
CHECK_EQ(new_queue_pairs_.size(), 0);
}
}
上面的线程while循环中会根据,BlockingQueue队列的决定是否阻塞当前线程.
caffe
系列源码分析介绍本系列深度学习框架caffe
源码分析主要内容如下:
caffe源码分析-cmake 工程构建主要内容:
自己从头构建一遍工程,这样能让我更好的了解大型的项目的构建。当然原始的caffe的构建感觉还是比较复杂(主要是cmake),我这里仅仅使用cmake构建,而且简化点,当然最重要的是支持CLion直接运行调试(如果需要这个工程可以评论留下你的邮箱,我给你发送过去)。
SyncedMemory
, 以及类Blob
数据传输的媒介.主要内容:
其中Blob
分析给出了其直接与opencv的图片相互转化以及操作,可以使得我们更好的理解Blob
.
layer
的源码分析,包括从整体上说明了layer
类别以及其proto定义与核心函数.内容如下:
首先分析了最简单的layer
Relu
,然后在是inner_product_layer全连接层
, 最后是layer_factory
caffe中 以此工厂模式create各种Layer.
内容如下:
内容如下:
内容如下:
caffe c++示例(mnist 多层感知机c++训练,测试)
类似与caffe
一样按照layer、solver、loss、net
等模块构建的神经网络实现可以见下面这篇blog,相信看懂了这个python的代码理解caffe框架会更简单点.
最后如果需要**cmake
** + CLion
**直接运行调试**caffe
**的代码工程,可以评论留下你的邮箱,我给你发送过去.**