windows编译tensorflow tensorflow单机多卡程序的框架 tensorflow的操作 tensorflow的变量初始化和scope 人体姿态检测 segmentation标注工具 tensorflow模型恢复与inference的模型简化 利用多线程读取数据加快网络训练 tensorflow使用LSTM pytorch examples 利用tensorboard调参 深度学习中的loss函数汇总 纯C++代码实现的faster rcnn tensorflow使用记录 windows下配置caffe_ssd use ubuntu caffe as libs use windows caffe like opencv windows caffe implement caffe model convert to keras model flappyBird DQN Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Neural Networks Fast-style-transfer tensorflow安装 tensorflow DQN Fully Convolutional Models for Semantic Segmentation Transposed Convolution, Fractionally Strided Convolution or Deconvolution 基于tensorflow的分布式部署 用python实现mlp bp算法 用tensorflow和tflearn搭建经典网络结构 Data Augmentation Tensorflow examples Training Faster RCNN with Online Hard Example Mining 使用Tensorflow做Prisma图像风格迁移 RNN(循环神经网络)推导 深度学习中的稀疏编码思想 利用caffe与lmdb读写图像数据 分析voc2007检测数据 用python写caffe网络配置 ssd开发 将KITTI的数据格式转换为VOC Pascal的xml格式 Faster RCNN 源码分析 在Caffe中建立Python layer 在Caffe中建立C++ layer 为什么CNN反向传播计算梯度时需要将权重旋转180度 Caffe使用教程(下) Caffe使用教程(上) CNN反向传播 Softmax回归 Caffe Ubuntu下环境配置

tensorflow C++ deploy

2019年10月25日

记录一次tensorflow模型的C++部署,将推理速度提升10倍。由于涉及到项目,这里只记录部署的思想并只展示部分代码。

首先需要做模型解密,我们参考TFSecured根据之前的密钥解码模型。

static std::unique_ptr<tensorflow::Session> session;

void CreateSession(const std::string &model_path)
{
	session.reset(tensorflow::NewSession(tensorflow::SessionOptions()));
	tensorflow::GraphDef graph_def;

	const std::string key = "CCCC88QM8IPZDAJDBD6Y2816V0CCCC"; //解析加密模型
	TF_CHECK_OK(tfsecured::GraphDefDecryptAES(model_path, &graph_def, key));

	//TF_CHECK_OK(tensorflow::ReadBinaryProto(tensorflow::Env::Default(), model_path, &graph_def));//解析普通模型
	TF_CHECK_OK(session->Create(graph_def));
}

正常inference时一般是先处理数据然后再输入模型,这是个串行的过程,时间是处理数据和模型推理相加。我们可以优化这个过程,并行化数据处理和模型推理。我们使用Provider-Consumer方式。我们首先建立一个线程安全的队列用于存储数据,起一个或多个线程来处理数据放入线程安全的队列中。然后另起一个或多个线程将队列中的数据取出喂给模型预测。

线程安全的队列

template <typename T>
class Queue
{
public:

	T pop()
	{
		std::unique_lock<std::mutex> mlock(mutex_);
		while (queue_.empty())
		{
			cond_.wait(mlock);
		}
		auto val = queue_.front();
		queue_.pop();
		return val;
	}

	void pop(T& item)
	{
		std::unique_lock<std::mutex> mlock(mutex_);
		while (queue_.empty())
		{
			cond_.wait(mlock);
		}
		item = queue_.front();
		queue_.pop();
	}

	void push(const T& item)
	{
		std::unique_lock<std::mutex> mlock(mutex_);
		queue_.push(item);
		mlock.unlock();
		cond_.notify_one();
	}

	int size()
	{
		std::unique_lock<std::mutex> mlock(mutex_);
		return queue_.size();
	}

	bool empty()
	{
		std::unique_lock<std::mutex> mlock(mutex_);
		return queue_.empty();
	}

	Queue() = default;
	Queue(const Queue&) = delete;            // disable copying
	Queue& operator=(const Queue&) = delete; // disable assignment

private:
	mutable std::queue<T> queue_;
	std::mutex mutex_;
	std::condition_variable cond_;
};

调用tensorflow模型

tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({ batchsize, 256, 256, 3 }));

float *pTensor = input_tensor.flat<float>().data();
memcpy(pTensor, tmp_atom.data, batchsize * count * sizeof(float));

std::vector<std::pair<std::string, tensorflow::Tensor>> inputs = { { input_name, input_tensor }, };

std::vector<tensorflow::Tensor> outputs;

TF_CHECK_OK(session->Run(inputs, { output_name }, {}, &outputs));

至于Consumer和Provider函数涉及到项目不方便贴代码。

只能说相比于使用python的tensorflow,C++下的部署实在快太多了,如果对于时间瓶颈在数据处理的任务,加上一些优化技巧提升5-10倍很容易。

看我写的辛苦求打赏啊!!!有学术讨论和指点请加微信manutdzou,注明

20


blog comments powered by Disqus