caffe里的blocking_queue.hpp与.cpp干了点什么呢???

我看的一下午才明白的,因为吧,我之前都是不知道与boost::thread相关的任何知识,然后开始看各种资料啊。。。

妈的,我就是一个小白,没一点基础的。。

总的来说:blocking_queue实现一个阻塞队列,它利用了生成者与消费者的设计模式,怎么说呢?、

首先吧,你要有一个queue(队列,c++里的一种容器),对它的操作有push与pop。 push即向队列里压入数据,相当于一个生产者,然后呢,pop把数据弹出队列,相当于一个消费者。。但是呢,生产者与消费者的速度可能不一样(即push与pop的速度)啊,那怎么办呢??所以呢,要想办法让它们同步啊,方法即把这样queue变为一个阻塞队列啊。。。

下面看一下怎么实现的:

它的构造函数 :

template<typename T>
BlockingQueue<T>::BlockingQueue()
    : sync_(new sync()) {
}

在blockingqueue的头文件中包括:成员变量有:queue_(这是一个队列,类型为std::queue)

sync_(这是一个sync类,里面只有有两个成员变量:mutex_与condition_)

blockingqueue的成员函数:

void push(参数为一个要push进去的数据)

bool try_pop(参数为一个用于存放要pop出来的数据的指针),如果有数据可以pop出来,则返回true,否则为false

type pop(参数为一个用于存放要pop出来的数据的指针),它与上面的区别在于,如果queue为空时,它会等待。

bool try_peek(参数为一个用于存放队列最前端的数据的指针),它的作用就是试着返回一下queue最前端的数据;有数据写入,则true.

type peek(参数为一个用于存放队列最前端的数据的指针),与上面的区别在于没有数据,它会等待。

size_t size() ,它干的事情就是返回队列中数据的个数;

另外,对于blocking_queueg来说,它只会在pop与peek的时候进行相应的等待(如果队列为空就等啊),在push的时候不用等待的(应该队列不会满吧,它可以自动增加吧,应有可能取的速度较快吧,不会造成队列不断增加吧);

补充一下sync的类:

// 这个类是在BlockingQueue类中定义的
template<typename T>
class BlockingQueue<T>::sync {
 public:
  mutable boost::mutex mutex_;
  boost::condition_variable condition_;
};

还是在这里写一下实现代码吧:

#include <boost/thread.hpp>
#include <string>

#include "caffe/data_reader.hpp"
#include "caffe/layers/base_data_layer.hpp"
#include "caffe/parallel.hpp"
#include "caffe/util/blocking_queue.hpp"

namespace caffe {

template<typename T>
class BlockingQueue<T>::sync {
 public:
  mutable boost::mutex mutex_;             //实现了一个mutex对象;
  boost::condition_variable condition_;   //也是实现了一个对象;
};

template<typename T>
BlockingQueue<T>::BlockingQueue()
    : sync_(new sync()) {
}

template<typename T>
void BlockingQueue<T>::push(const T& t) {
  // 在push操作过程中,创建一个scoped_lock的对象lock,利用它的构造函数来对
  // mutex_进行加锁;
  boost::mutex::scoped_lock lock(sync_->mutex_);
  queue_.push(t);
  lock.unlock();   //对互斥体解锁;
  sync_->condition_.notify_one(); //给相应的wait中的线程发出通知;
}

template<typename T>
bool BlockingQueue<T>::try_pop(T* t) {
  boost::mutex::scoped_lock lock(sync_->mutex_);

  if (queue_.empty()) {
    return false;
  }

  *t = queue_.front();
  queue_.pop();
  return true;
}

template<typename T>
T BlockingQueue<T>::pop(const string& log_on_wait) {
  boost::mutex::scoped_lock lock(sync_->mutex_);

  while (queue_.empty()) {
    if (!log_on_wait.empty()) {
      LOG_EVERY_N(INFO, 1000)<< log_on_wait; //当空的时候,输入相应的等待信息;
    }
    sync_->condition_.wait(lock);           //线程进入wait的过程;等相应的通知;
}

  T t = queue_.front();
  queue_.pop();
  return t;
}

template<typename T>
bool BlockingQueue<T>::try_peek(T* t) {
  boost::mutex::scoped_lock lock(sync_->mutex_);

  if (queue_.empty()) {
    return false;
  }

  *t = queue_.front();
  return true;
}

template<typename T>
T BlockingQueue<T>::peek() {
  boost::mutex::scoped_lock lock(sync_->mutex_);

  while (queue_.empty()) {
    sync_->condition_.wait(lock);
  }

  return queue_.front();
}

template<typename T>
size_t BlockingQueue<T>::size() const {
  boost::mutex::scoped_lock lock(sync_->mutex_);
  return queue_.size();
}

template class BlockingQueue<Batch<float>*>;
template class BlockingQueue<Batch<double>*>;
template class BlockingQueue<Datum*>;
template class BlockingQueue<shared_ptr<DataReader::QueuePair> >;
template class BlockingQueue<P2PSync<float>*>;
template class BlockingQueue<P2PSync<double>*>;

}  // namespace caffe
时间: 2024-07-29 17:36:36

caffe里的blocking_queue.hpp与.cpp干了点什么呢???的相关文章

神经网络caffe框架源码解析--softmax_layer.cpp类代码研究

// Copyright 2013 Yangqing Jia // #include <algorithm> #include <vector> #include "caffe/layer.hpp" #include "caffe/vision_layers.hpp" #include "caffe/util/math_functions.hpp" using std::max; namespace caffe { /**

神经网络caffe框架源码解析--data_layer.cpp类代码研究

dataLayer作为整个网络的输入层, 数据从leveldb中取.leveldb的数据是通过图片转换过来的. 网络建立的时候, datalayer主要是负责设置一些参数,比如batchsize,channels,height,width等. 这次会通过读leveldb一个数据块来获取这些信息. 然后启动一个线程来预先从leveldb拉取一批数据,这些数据是图像数据和图像标签. 正向传播的时候, datalayer就把预先拉取好数据拷贝到指定的cpu或者gpu的内存. 然后启动新线程再预先拉取数

Stored Procedure 里的 WITH RECOMPILE 到底是干麻的?

原文:Stored Procedure 里的 WITH RECOMPILE 到底是干麻的? 在 SQL Server 创建或修改「存储过程(stored procedure)」时,可加上 WITH RECOMPILE 选项,但多数文档或书籍都写得语焉不详,或只解释为「每次执行此存储过程时,都要重新编译」.事实上,是指执行此一存储过程时,要强制重新产生「执行计划(execution plan)」,而不要从「缓存(cache)」去取得旧的「执行计划」. SQL Server 在评估与产生「执行计划」

caffe编译报错 cudnn.hpp:127:41: error: too few arguments to function ‘cudnnStatus_t cudnnSetPooling2dDescriptor

转载自: https://blog.csdn.net/u011070171/article/details/52292680 这是因为当前版本的caffe的cudnn实现与系统所安装的cudnn的版本不一致引起的. 解决办法: 1.将./include/caffe/util/cudnn.hpp 换成最新版的caffe里的cudnn的实现,即相应的cudnn.hpp. 2. 将./include/caffe/layers里的,所有以cudnn开头的文件,例如cudnn_conv_layer.hpp

c++ cpp和hpp的关系

首先,我们可以将所有东西都放在一个.cpp文件内,编译器会将这个.cpp编译成.obj,即编译单元.一个程序可以由一个编译单元组成,也可以由多个编译单元组成.一个.cpp对应一个.obj,然后将所有的.obj链接起来(通过一个叫链接器的程序),组成一个.exe,即程序.如果一个.cpp要用到另一个.cpp定义的函数怎么办,只需在这个.cpp中写上它的函数声明. 链接器将所有的obj链接起来,但是如果碰巧有相同的函数或外部变量怎么办?C++可以通过一种叫做链接属性的关键字来限定,某个函数是属于整个

从零开始山寨Caffe&#183;肆:线程系统

不精通多线程优化的程序员,不是好程序员,连码农都不是. ——并行计算时代掌握多线程的重要性 线程与操作系统 用户线程与内核线程 广义上线程分为用户线程和内核线程. 前者已经绝迹,它一般只存在于早期不支持多线程的系统中. 它用模拟的方式实现一个模拟的多线程系统,不支持异步. 即,一个线程被阻塞了,其它线程也会被阻塞. 当今的操作系统几乎都默认提供了内核线程API,底层由操作系统实现. 内核线程的好处在于,它们之间支持异步,是"真"多线程. 操作系统的流氓软件 不过,内核线程也给线程的使用

caffe中权值初始化方法

首先说明:在caffe/include/caffe中的 filer.hpp文件中有它的源文件,如果想看,可以看看哦,反正我是不想看,代码细节吧,现在不想知道太多,有个宏观的idea就可以啦,如果想看代码的具体的话,可以看:http://blog.csdn.net/xizero00/article/details/50921692,写的还是很不错的(不过有的地方的备注不对,不知道改过来了没). 文件 filler.hpp提供了7种权值初始化的方法,分别为:常量初始化(constant).高斯分布初

caffe学习(1):多平台下安装配置caffe

caffe学习(1):多平台下安装配置caffe 提到deep learning, caffe的大名自然是如雷贯耳,当然,除了caffe之外,还有很多其他的框架,如torch,mxnet...但是,就我自己这一个月的实验以及师兄的结论都是,caffe得出的实验performance要高于别的框架,可能是C++的威力吧~笑 OK,接下来准备在这个系列分享我使用和学习caffe的一些经验,首先自然是框架的配置了.这里我们分享一下在windows10和ubuntu14.04虚拟机下的Caffe配置(:

梳理caffe代码common(八)

因为想梳理data_layer的过程.整理一半发现有几个很重要的头文件就是题目列出的这几个: 追本溯源,先从根基開始学起.这里面都是些什么鬼呢? common类 命名空间的使用:google.cv.caffe{boost.std}. 然后在项目中就能够任意使用google.opencv.c++的标准库.以及c++高级库boost. caffe採用单例模式封装boost的智能指针(caffe的灵魂).std一些标准的使用方法.重要的初始化内容(随机数生成器的内容以及google的gflags和gl