caffe源码分析-InternalThread

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 源码分析主要内容如下:

1. caffe源码分析-cmake 工程构建:

caffe源码分析-cmake 工程构建主要内容:

自己从头构建一遍工程,这样能让我更好的了解大型的项目的构建。当然原始的caffe的构建感觉还是比较复杂(主要是cmake),我这里仅仅使用cmake构建,而且简化点,当然最重要的是支持CLion直接运行调试(如果需要这个工程可以评论留下你的邮箱,我给你发送过去)。

这里写图片描述

2. caffe的数据内存分配类SyncedMemory, 以及类Blob数据传输的媒介.

主要内容:
caffe源码分析-SyncedMemory
caffe源码分析-Blob
其中Blob分析给出了其直接与opencv的图片相互转化以及操作,可以使得我们更好的理解Blob.

3. caffe layer的源码分析,包括从整体上说明了layer类别以及其proto定义与核心函数.

内容如下:
caffe源码分析-layer
caffe源码分析-ReLULayer
caffe源码分析-inner_product_layer
caffe源码分析-layer_factory

首先分析了最简单的layer Relu,然后在是inner_product_layer全连接层, 最后是layer_factorycaffe中 以此工厂模式create各种Layer.

4. 数据输入层,主要是多线程+BlockingQueue的方式读取数据训练:

内容如下:
caffe源码分析-BlockingQueue
caffe源码分析-InternalThread
caffe源码分析-DataReader

5. IO处理例如读取proto文件转化为网络,以及网络参数的序列化

内容如下:
caffe源码分析-DataTransformer
caffe源码分析-db, io

6. 最后给出了使用纯C++结合多层感知机网络训练mnist的示例

内容如下:

caffe c++示例(mnist 多层感知机c++训练,测试)

类似与caffe一样按照layer、solver、loss、net等模块构建的神经网络实现可以见下面这篇blog,相信看懂了这个python的代码理解caffe框架会更简单点.

神经网络python实现


最后如果需要cmake + CLion直接运行调试caffe的代码工程,可以评论留下你的邮箱,我给你发送过去.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值