深度学习利器:TensorFlow系统架构及高性能程序设计

作者: 武维 2017-04-24 14:09:13

2015年11月9日谷歌开源了人工智能平台TensorFlow,同时成为2015年最受关注的开源项目之一。经历了从v0.1到v0.12的12个版本迭代后,谷歌于2017年2月15日发布了TensorFlow 1.0 版本,并同时在美国加州山景城举办了首届TensorFlow Dev Summit会议。

TensorFlow 1.0及Dev Summit(2017)回顾

和以往版本相比,TensorFlow 1.0 的特性改进主要体现在以下几个方面:

  • 速度更快 :TensorFlow 1.0版本采用了XLA的编译技术,改进了TensorFlow的运行性能及内存利用。从Benchmark问题的测试结果来看,对单机Inception v3模型,实现了在单机8 GPUs上7.3倍的运算加速;对分布式Inception v3模型,实现了在多机64 GPUs上58倍的运算加速。
  • 更加灵活 :该版本除了支持tf.layers,tf.metrics及tf.losses模型的High-Level API外,实现了对keras(high-level neural networks library)API的全面兼容。
  • 更产品化 :TensorFlow Python API在v1.0版本中趋于稳定,为产品兼容性打下坚实基础。

在TensorFlow 1.0版本发布的当天,谷歌公司还举办了TensorFlow 2017 DEV Summit。该 日程主要包括以下几个方面的主题演讲:

  • Hands-on TensorBoard可视化技术:介绍了如何使用TensorBoard,以及TensorFlow图模型、训练数据的可视化等。
  • TensorFlow High-Level API:介绍了使用Layers, Estimators, and Canned Estimators High-Level API定义训练模型。
  • Integrating Keras & TensorFlow: 介绍了如何在TensorFlow中使用Keras API进行模型定义及训练。
  • TensorFlow at DeepMind:介绍了在DeepMind中使用TensorFlow平台的典型案例,包括AlphaGo等应用。
  • Skin Cancer Image Classification:介绍了斯坦福医学院使用TensorFlow分类皮肤癌照片,用于医学诊断。
  • Mobile and Embedded TensorFlow:介绍了如何把TensorFlow模型运行在移动终端、嵌入式设备,包括安卓,iOS等系统。
  • Distributed TensorFlow:系统性地介绍了分布式TensorFlow的相关技术,以及如何应用于大规模模型训练。
  • TensorFlow Ecosystem:讲解了TensorFlow的生态系统,包括生成训练数据,分布式运行TensorFlow和serving models的产品化流程。
  • Serving Models in Production with TensorFlow Serving:系统性讲解了如何在生产环境中应用TensorFlow Serving模型。
  • ML Toolkit:介绍了TensorFlow的机器学习库,如线性回归,KMeans等算法模型的使用。
  • Sequence Models and the RNN API:介绍了如何构建高性能的sequence-to-sequence模型,以及相关API。
  • Wide & Deep Learning: 介绍了如何结合Wide模型和Deep模型构建综合训练模型。
  • Magenta,Music and Art Generation:使用增强型深度学习模型生成音乐声音和艺术图片。
  • Case Study,TensorFlow in Medicine – Retinal Imaging:使用TensorFlow机器学习平台对医学视网膜图片进行分类,辅助医学诊断。

TensorFlow系统架构

TensorFlow作为分布式机器学习平台,主要架构如下图所示。RPC和RDMA为网络层,主要负责传递神经网络算法参数。CPU和GPU为设备层,主要负责神经网络算法中具体的运算操作。Kernel为TensorFlow中算法操作的具体实现,如卷积操作,激活操作等。Distributed Master用于构建子图;切割子图为多个分片,不同的子图分片运行在不同的设备上;Master还负责分发子图分片到Executor/Work端。Executor/Work在设备(CPUs,GPUs,etc.)上,调度执行子图操作;并负责向其它Worker发送和接收图操作的运行结果。C API把TensorFlow分割为前端和后端,前端(Python/C++/Java Client)基于C API触发TensorFlow后端程序运行。Training libraries和Inference libs是模型训练和推导的库函数,为用户开发应用模型使用。

深度学习利器:TensorFlow系统架构及高性能程序设计

下图为Client、Master及Worker的内部工作原理。”/job:worker/task:0″ 和 “/job:ps/task:0” 表示worker中的执行服务。”job:ps”表示参数服务器,用于存储及更新模型参数。”job:worker”用于优化模型参数,并发参数发送到参数服务器上。Distributed Master和Worker Service只存在于分布式TensorFlow中。单机版本的TensorFlow实现了Local的Session,通过本地进程的内部通讯实现上述功能。

深度学习利器:TensorFlow系统架构及高性能程序设计

用户编写TensorFlow应用程序生成计算图,Client组件会创建Session,并通过序列化技术,发送图定义到Distributed Master组件。下图中,Client创建了一个 s+=w*x+b的图计算模型。

深度学习利器:TensorFlow系统架构及高性能程序设计

当Client触发Session运算的时候,Maser构建将要运行的子图。并根据设备情况,切割子图为多个分片。下面为Master构建的运行子图:

深度学习利器:TensorFlow系统架构及高性能程序设计

接着切割子图,把模型参数分组在参数服务器上,图计算操作分组在运算Worker上。下图为一种可行的图切割策略:

深度学习利器:TensorFlow系统架构及高性能程序设计

Distributed Master会根据模型参数的分区情况进行切割边,在Task间插入发送和接收Tensor信息的通信节点,如下图所示:

深度学习利器:TensorFlow系统架构及高性能程序设计

接着Distributed Master通过RegisterGraph方法发送子图分片给Task,如下图所示:

深度学习利器:TensorFlow系统架构及高性能程序设计

Master通过RunGraph触发子图运算,Worker会使用GPU/CPU运算设备执行TensorFlow Kernel运算。在本节点的CPU和GPU之间,使用cudaMemcpyAsync传输数据;在本节点GPU和GPU之间,使用peer-to-peer DMA传输数据,避免通过CPU复制数据。TensorFlow使用gRPC(TCP)和RDMA (Converged Ethernet)技术,实现Worker间的数据通信及传输,如下图所示:

深度学习利器:TensorFlow系统架构及高性能程序设计

高性能程序设计

TensorFlow内核采用C/C++开发,并提供了C++,Python,Java,Go语言的Client API。特别是Python API,是目前主流的TensorFlow模型开发接口。但为什么还需要采用C++ API去训练模型呢?本文基于如下 两点考虑 ,首先当我们采用Python API去训练模型的时候,需要不断地用Python API调用C/C++底层接口,重复的接口调用一定程度上影响了程序的执行性能。更为重要的是,在GPU上训练模型的时候需要大量的内存交换;如果采用C++ API去训练模型,可提供更好的运算性能及更好地控制GPU内存的分配。

下图为Python API的运算架构:在模型训练的每次迭代中,程序通过Python API读取Batch Data,然后通过TensorFlow Session Run接口,传递数据给C++,并触发神经网络训练。如下图所示:

深度学习利器:TensorFlow系统架构及高性能程序设计

下图为C++ API的运算架构:在模型训练的每次迭代中,通过C++ API读取Batch Data后,直接触发模型训练。减少了不同语言间API接口的循环调用及数据传输。如下图所示:

深度学习利器:TensorFlow系统架构及高性能程序设计

为了采用C++ API进行模型训练,我们首先需要编写训练模型,这个编写过程可以采用Python语言来完成。我们首先采用Python API编写训练模型,然后把图模型转换为Protobuf的序列化文件。接着通过C++ API加载该模型文件,创建TensorFlow Session,初始化模型变量,以及加载训练数据并执行神经网络训练。程序架构如下图所示:

深度学习利器:TensorFlow系统架构及高性能程序设计

下面为使用Python API定义训练模型的示例:

with tf.Session() as sess:

  1. #定义Placeholder Tensor接入训练数据 
  2.     x = tf.placeholder(tf.float32, [None, 32], name="x"
  3.     y = tf.placeholder(tf.float32, [None, 8], name="y"
  4.  
  5.     #定义训练模型 
  6.     w1 = tf.Variable(tf.truncated_normal([32, 16], stddev=0.1)) 
  7.     b1 = tf.Variable(tf.constant(0.0, shape=[16])) 
  8.     w2 = tf.Variable(tf.truncated_normal([16, 8], stddev=0.1)) 
  9.     b2 = tf.Variable(tf.constant(0.0, shape=[8])) 
  10.     a = tf.nn.tanh(tf.nn.bias_add(tf.matmul(x, w1), b1)) 
  11.     y_out = tf.nn.tanh(tf.nn.bias_add(tf.matmul(a, w2), b2), name="y_out"
  12.     cost = tf.reduce_sum(tf.square(y-y_out), name="cost"
  13.     optimizer = tf.train.AdamOptimizer().minimize(cost, name="train"
  14.  
  15.     #定义变量初始化操作 
  16.     init = tf.initialize_variables(tf.all_variables(), name='init_all_vars_op'
  17.  
  18.     #把图模型转换为Protobuf文件 
  19. tf.train.write_graph(sess.graph_def, './''mlp.pb', as_text=False

下面为使用C++ API加载Protobuf图模型,并执行训练的示例:

  1. #include "tensorflow/core/public/session.h" 
  2. #include "tensorflow/core/graph/default_device.h" 
  3. using namespace tensorflow; 
  4.  
  5. int main(int argc, char* argv[]) { 
  6.     //Protobuf模型文件名 
  7.     std::string graph_definition = "mlp.pb"
  8.     //Tensorflow Sesssion 
  9.     Session* session; 
  10.  
  11.     //定义图模型对象 
  12.     GraphDef graph_def; 
  13.     SessionOptions opts; 
  14.  
  15.     //存储Session会话的运行结果 
  16.     std::vector<Tensor> outputs;  
  17.  
  18.     #加载Protobuf模型文件到图模型对象中 
  19.     TF_CHECK_OK(ReadBinaryProto(Env::Default(), graph_definition, &graph_def)); 
  20.  
  21.     // 默认在gpu 0上执行模型的训练操作 
  22.     graph::SetDefaultDevice("/gpu:0", &graph_def); 
  23.  
  24.     //设定GPU显存使用参数 
  25.     opts.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.5); 
  26.     opts.config.mutable_gpu_options()->set_allow_growth(true); 
  27.  
  28.     //创建TensorFlow会话 
  29.     TF_CHECK_OK(NewSession(opts, &session)); 
  30.  
  31.     // 加载图对象到会话中 
  32.     TF_CHECK_OK(session->Create(graph_def)); 
  33.  
  34.     // 执行模型参数初始化操作 
  35.     TF_CHECK_OK(session->Run({}, {}, {"init_all_vars_op"}, nullptr)); 
  36.  
  37.     //定义模型输入数据,包括数据类型和维度信息 
  38.     Tensor x(DT_FLOAT, TensorShape({100, 32})); 
  39.     Tensor y(DT_FLOAT, TensorShape({100, 8})); 
  40.  
  41.     //把Tensor转换为矩阵,并初始化Tensor数据 
  42.     auto _XTensor = x.matrix<float>(); 
  43.     auto _YTensor = y.matrix<float>(); 
  44.     _XTensor.setRandom(); 
  45.     _YTensor.setRandom(); 
  46.  
  47.     for (int i = 0; i < 10; ++i) { 
  48.         //执行模型的训练操作,{{"x", x}, {"y", y}}表示输入数据Tensor名称和Tensor对象;{"cost"}表示要获取输出值的操作名称;&outputs表示执行"cost"操作后返回的Tensor对象 
  49.         TF_CHECK_OK(session->Run({{"x", x}, {"y", y}}, {"cost"}, {}, &outputs));  
  50.  
  51.         //获取执行“cost“操作后的运算结果 
  52.         float cost = outputs[0].scalar<float>()(0); 
  53.         std::cout << "Cost: " << cost << std::endl; 
  54.  
  55.         //执行"train"操作 
  56.         TF_CHECK_OK(session->Run({{"x", x}, {"y", y}}, {}, {"train"}, nullptr)); // Train 
  57.         outputs.clear(); 
  58.     } 
  59.  
  60.     //关闭Session及删除Session对象 
  61.     session->Close(); 
  62.     delete session; 
  63.     return 0; 

当C++程序写好后,编译时候需要链接的头文件,开源已经帮我们整理好了,存放于目录/usr/lib/python2.7/site-packages/tensorflow/include下。编译和运行的时候需要链接libtensorflow_cc.so,可以按照下面的方式编译该库文件:bazel build -c opt //tensorflow:libtensorflow_cc.so –copt=-m64 –linkopt=-m64 –spawn_strategy=standalone –genrule_strategy=standalone –verbose_failures。具体可参考TensorFlow源代码的官方编译文档。

总结

本文首先回顾了TensorFlow 1.0主要新特性及TensorFlow 2017 Dev Summit的主要议程。到目前为止TensorFlow的GitHub Star排名为51000+, Fork排名已达24000+,有15000+ commits。并随着TensorFlow新版本的不断发布以及新特性的不断增加,TensorFlow使用更加灵活,运行速度更快,使用方式更产品化,已成为目前主流的深度学习平台之一。

接着介绍了TensorFlow的系统架构,包括Client,Master,Worker,Kernel的相关概念及运行方式,是一种适合大规模分布式训练的机器学习平台。从上述系统架构中可以看到,TensorFlow内核采用C/C++开发,当采用Python API去训练模型的时候,需要不断地用Python调用C/C++底层接口,重复的接口调用一定程度上影响了程序的执行性能。如果有最求高性能运算的朋友,可以尝试用下本文高性能运算章节推荐的方法。

参考文献

  1. https://www.tensorflow.org
  2. 深度学习利器:分布式TensorFlow及实例分析
  3. 深度学习利器:TensorFlow使用实战

作者介绍

武维,博士,现为IBM Spectrum Computing 研发工程师。主要从事大数据,深度学习,云计算等领域的研发工作。

深度学习 TensorFlow
上一篇:深度卷积神经网络在目标检测中的进展 下一篇:美国购物平台Stitch Fix王建强:数据驱动的决策辅助与产品智能化
评论
取消
暂无评论,快去成为第一个评论的人吧

更多资讯推荐

机器学习算法集锦:从贝叶斯到深度学习及各自优缺点

本文筛选并简单介绍了一些最常见算法类别,还为每一个类别列出了一些实际的算法并简单介绍了它们的优缺点。

佚名 ·  3天前
用TFserving部署深度学习模型

本文介绍了TFserving部署线上推理服务,从模型的转换,部署启动和调用推理,欢迎交流,希望对你有帮助。

佚名 ·  3天前
520开发者的情人节 飞桨全平台35项升级大礼“示AI”

5月20日,由深度学习技术及应用国家工程实验室与百度联合主办的“WAVE SUMMIT 2020”深度学习开发者峰会以线上形式召开。本届峰会,飞桨公布最新全景图,带来多达35项全新发布和重磅升级,不仅进一步升级核心框架、完善从开发训练到部署的全流程工业级极致体验、深化企业端服务,更着眼未来,引领布局前沿技术,首发量子机器学习开发工具“量桨”,以及蓄力AI人才培养和开发者生态,发布青少年AI科普教育“晨曦计划”、“星辰计划”开发者探索基金等。

佚名 ·  4天前
百度CTO王海峰:飞桨深度学习平台是新基建的重要一环

5月20日,由深度学习技术及应用国家工程实验室与百度联合主办的“Wave Summit 2020”深度学习开发者峰会在线上召开。百度CTO王海峰在致辞中表示,时代契机为飞桨的发展提供了最好的机遇,作为中国首个开源开放、功能完备的产业级深度学习平台,飞桨将与产业紧密融合,与开发者并肩前行。

佚名 ·  2020-05-20 11:32:27
机器学习必备:TensorFlow的11个使用技巧整理

在本文中,我们将探索TF 2.0的10个功能,这些功能让TensorFlow的使用更加顺畅,减少了代码行并提高了效率,因为这些函数/类属于TensorFlow API。

为AI呐喊 ·  2020-05-19 09:00:26
PyTorch官方教程大更新:增加标签索引,更加新手友好

PyTorch官方教程,现已大幅更新,不必再面对一整页教学文章茫然无措,可以想学哪里就精准点哪里了。

鱼羊 ·  2020-05-18 09:44:08
机器学习:使用批归一化有哪些缺点?

批归一化(Batch Normalization)是深度学习领域的重大突破之一,也是近年来研究人员讨论的热门话题之一。批归一化是一种被广泛采用的技术,能够使训练更快、更稳定,并已成为深度学习领域最具影响力的方法之一。然而,它仍然存在一些要注意的问题。

不靠谱的猫 ·  2020-05-18 08:42:13
深度度量学习的这十三年,难道是错付了吗?

近日,Facebook AI 和 Cornell Tech 的研究者在论文预印本平台 arXiv 上公布了最新研究论文,声称这十三年来深度度量学习领域的研究进展「实际上并不存在」。

机器之心 ·  2020-05-17 15:57:28
Copyright©2005-2020 51CTO.COM 版权所有 未经许可 请勿转载