当前位置: 首页 > 科技观察

深度学习利器:TensorFlow系统架构与高性能编程

时间:2023-03-22 12:00:19 科技观察

2015年11月9日,谷歌开源人工智能平台TensorFlow,成为2015年最受关注的开源项目之一。从v0.1开始经过12个版本迭代。从1到v0.12,谷歌于2017年2月15日发布了TensorFlow1.0版本,并同时在加州山景城举办了首届TensorFlowDevSummit。TensorFlow1.0和DevSummit(2017)回顾与之前的版本相比,TensorFlow1.0的特性改进主要体现在以下几个方面:更快:TensorFlow1.0版本使用了XLA编译技术,提高了TensorFlow的运行性能和内存占用。从Benchmark问题的测试结果来看,对于单机Inceptionv3模型,在单机8GPU上实现了7.3倍的运算加速;对于分布式Inceptionv3模型,在多机64GPU上实现了58倍的运算加速。更灵活:除了支持tf.layers、tf.metrics和tf.losses模型的High-LevelAPI外,该版本还完全兼容keras(高级神经网络库)API。更面向产品:TensorFlowPythonAPI在v1.0版本趋于稳定,为产品兼容打下了坚实的基础。在TensorFlow1.0发布的当天,谷歌还举办了TensorFlow2017DEVSummit。议程主要包括以下几个方面的主题演讲:Hands-onTensorBoard可视化技术:介绍如何使用TensorBoard,以及TensorFlow图模型、训练数据的可视化等TensorFlowHigh-LevelAPI:介绍Layers的使用,Estimators和CannedEstimators用于定义训练模型的高级API。IntegratingKeras&TensorFlow:介绍如何在TensorFlow中使用KerasAPI进行模型定义和训练。TensorFlowatDeepMind:介绍在DeepMind中使用TensorFlow平台的典型案例,包括AlphaGo等应用。皮肤癌图像分类:介绍斯坦福医学院使用TensorFlow对皮肤癌照片进行分类以进行医学诊断。MobileandEmbeddedTensorFlow:介绍如何在移动终端和嵌入式设备上运行TensorFlow模型,包括Android、iOS等系统。DistributedTensorFlow:系统介绍了分布式TensorFlow的相关技术,以及如何将其应用于大规模模型训练。TensorFlow生态系统:解释了TensorFlow生态系统,包括生成训练数据、运行TensorFlow和以分布式方式服务模型的生产过程。ServingModelsinProductionwithTensorFlowServing:系统地解释了如何在生产环境中应用TensorFlowServing模型。MLToolkit:介绍TensorFlow的机器学习库,比如线性回归、KMeans等算法模型的使用。SequenceModelsandtheRNNAPI:介绍如何构建高性能的sequence-to-sequence模型和相关API。Wide&DeepLearning:介绍如何结合Wide模型和Deep模型构建综合训练模型。洋红色、音乐和艺术生成:使用增强的深度学习模型生成音乐声音和艺术图片。案例研究,TensorFlowinMedicine–RetinalImaging:使用TensorFlow机器学习平台对医学视网膜图像进行分类以辅助医学诊断。TensorFlow系统架构TensorFlow是一个分布式机器学习平台,主要架构如下图所示。RPC和RDMA是网络层,主要负责传输神经网络算法参数。CPU和GPU是设备层,主要负责神经网络算法中的具体计算操作。Kernel是TensorFlow中算法运算的具体实现,比如卷积运算、激活运算等,DistributedMaster用于构建子图;将子图切割成多个切片,不同的子图切片运行在不同的设备上;Master还负责将子图切片分发给Executor/Work。Executor/Work在设备(CPU、GPU等)上调度和执行子图操作;并负责向其他Worker发送和接收图形操作的结果。CAPI将TensorFlow分为前端和后端。前端(Python/C++/JavaClient)基于CAPI触发TensorFlow后端程序运行。Traininglibraries和Inferencelibs是用于模型训练和推导的库函数,供用户开发应用模型。下图展示了Client、Master和Worker的内部工作原理。“/job:worker/task:0”和“/job:ps/task:0”代表worker中的执行服务。“job:ps”表示参数服务器,用于存储和更新模型参数。“job:worker”用于优化模型参数,并发参数发送到参数服务器。分布式Master和WorkerService只存在于分布式TensorFlow中。单机版的TensorFlow实现了LocalSession,通过本地进程内部通信实现上述功能。用户编写TensorFlow应用生成计算图,Client组件创建Session并将图定义通过序列化技术发送给DistributedMaster组件。下图中,Client创建了一个s+=w*x+b的图计算模型。当Client触发Session操作时,Maser构造要执行的子图。并根据设备情况,将子图切割成多个切片。下面是Master搭建的runningsubgraph:然后切割子图,在parameterserver上对模型参数进行分组,在computingworker上对图计算操作进行分组。下图展示了一种可行的切图策略:DistributedMaster会根据模型参数的划分进行切边,并在Task之间插入用于发送和接收Tensor信息的通信节点,如下图所示:然后DistributedMaster发送孩子通过RegisterGraph方法。Graph分为Tasks,如下图所示:Master通过RunGraph触发子图运算,Worker使用GPU/CPU计算设备执行TensorFlowKernel运算。本节点CPU和GPU之间,使用cudaMemcpyAsync传输数据;本节点GPU与GPU之间,使用点对点DMA传输数据,避免通过CPU拷贝数据。TensorFlow使用gRPC(TCP)和RDMA(ConvergedEthernet)技术实现Worker之间的数据通信和传输,如下图所示:高性能编程TensorFlow内核采用C/C++开发,提供C++、Python、Java,Go语言客户端API。特别是PythonAPI是目前主流的TensorFlow模型开发接口。但是为什么我们仍然需要使用C++API来训练模型呢?这篇文章是基于以下两个考虑。首先,当我们使用PythonAPI训练模型时,需要不断地使用PythonAPI调用C/C++底层接口。重复的接口调用在一定程度上影响了程序的执行性能。更重要的是,在GPU上训练模型时需要大量的内存交换;如果使用C++API来训练模型,可以提供更好的计算性能,更好地控制GPU内存的分配。下图展示了PythonAPI的计算架构:在模型训练的每一次迭代中,程序通过PythonAPI读取BatchData,然后通过TensorFlowSessionRun接口传递给C++,触发神经网络训练。如下图所示:下图展示了C++API的计算架构:在模型训练的每一次迭代中,通过C++API读取批量数据后直接触发模型训练。减少不同语言之间API接口的循环调用和数据传输。如下图所示:为了使用C++API进行模型训练,我们首先需要编写训练模型。这个编写过程可以用Python语言来完成。我们首先使用PythonAPI编写训练模型,然后将图模型转换成Protobuf序列化文件。然后通过C++API加载模型文件,创建TensorFlowSession,初始化模型变量,加载训练数据,进行神经网络训练。程序架构如下图所示:下面是使用PythonAPI定义训练模型的例子:withtf.Session()assess:#DefinePlaceholderTensortoaccesstrainingdatax=tf.placeholder(tf.float32,[None,32],name="x")y=tf.placeholder(tf.float32,[None,8],name="y")#定义训练模型w1=tf.Variable(tf.truncated_normal([32,16],stddev=0.1))b1=tf.Variable(tf.constant(0.0,shape=[16]))w2=tf.Variable(tf.truncated_normal([16,8],stddev=0.1))b2=tf.Variable(tf.constant(0.0,shape=[8]))a=tf.nn.tanh(tf.nn.bias_add(tf.matmul(x,w1),b1))y_out=tf.nn.tanh(tf.nn.bias_add(tf.matmul(a,w2),b2),name="y_out")cost=tf.reduce_sum(tf.square(y-y_out),name="cost")optimizer=tf.train.AdamOptimizer().minimize(cost,name="train")#定义变量初始化操作init=tf.initialize_variables(tf.all_variables(),name='init_all_vars_op')#将图模型转换成一个Protobuf文件tf.train.write_graph(sess.graph_def,'./','mlp.pb',as_text=False)如下是使用C++API加载Protobuf图模型并执行训练的示例:#include"tensorflow/core/public/session.h"#include"tensorflow/core/graph/default_device.h"usingnamespacetensorflow;intmain(intargc,char*argv[]){//Protobuf模型文件名std::stringgraph_definition="mlp.pb";//TensorflowSessionSession*session;//定义图模型对象GraphDefgraph_def;SessionOptions;//存储Session会话的运行结果std::vectoroutputs;#加载Protobuf模型文件到图模型对象中TF_CHECK_OK(ReadBinaryProto(Env::Default(),graph_definition,&graph_def));//默认在gpu0上执行模型训练操作graph::SetDefaultDevice("/gpu:0",&graph_def);//设置GPU显存使用参数opts.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.5);opts.config.mutable_gpu_options()->set_allow_growth(true);//创建TensorFlow会话TF_CHECK_OK(NewSession(opts,&session));//加载图对象到session中TF_CHECK_OK(session->Create(graph_def));//执行模型参数初始化操作TF_CHECK_OK(session->Run({},{},{"init_all_vars_op"},nullptr));//定义模型输入数据,包括数据类型和维度信息Tensorx(DT_FLOAT,TensorShape({100,32}));Tensory(DT_FLOAT,TensorShape({100,8}));//将Tensor转化为矩阵,并初始化Tensor数据auto_XTensor=x.matrix();auto_YTensor=y.matrix();_XTensor.setRandom();_YTensor.setRandom();for(inti=0;i<10;++i){//执行模型的训练操作,{{"x",x},{"y",y}}表示输入数据Tensor名称和Tensor对象;{"cost"}表示获取输出值的操作名称;&outputs表示执行“cost”操作后返回的Tensor对象TF_CHECK_OK(session->Run({{"x",x},{"y",y}},{"cost"},{},&outputs));//执行“cost”运算后得到运算结果floatcost=outputs[0].scalar()(0);std::cout<<"Cost:"<Run({{"x",x},{"y",y}},{},{"train"},nullptr));//Trainoutputs.clear();}//关闭Session,删除Session对象session->Close();deletesession;return0;}C++程序写完后,编译时需要链接的头文件已经整理好了开源存放在目录/usr/lib/python2.7/site-packages/tensorflow/include下编译运行时需要链接libtensorflow_cc.so。您可以通过以下方式编译库文件:bazelbuild-copt//tensorflow:libtensorflow_cc.so–copt=-m64–linkopt=-m64–spawn_strategy=standalone–genrule_strategy=standalone–verbose_failures。具体可以参考TensorFlow源码官方编译文档。总结本文首先回顾了TensorFlow1.0的主要新特性和TensorFlow2017DevSummit的主要议程。目前TensorFlow的GitHubStarrank为51000+,Forkrank达到24000+,有15000+commits。并且随着TensorFlow新版本的不断发布和新特性的不断增加,TensorFlow使用起来更加灵活,运行速度更快,使用起来更加产品化。已经成为目前主流的深度学习平台之一。然后介绍了TensorFlow的系统架构,包括Client、Master、Worker、Kernel的相关概念和运行方式。是一个适合大规模分布式训练的机器学习平台。从上面的系统架构可以看出,TensorFlow内核是使用C/C++开发的。使用PythonAPI训练模型时,需要不断使用Python调用C/C++底层接口。重复的接口调用在一定程度上影响了程序。执行性能。如果有追求高性能计算的朋友,可以试试本文高性能计算部分推荐的方法。参考资料http://www.tensorflow.org深度学习工具:分布式TensorFlow和实例分析深度学习工具:TensorFlowinpractice作者介绍吴伟,博士,现为IBMSpectrumComputing研发工程师。主要从事大数据、深度学习、云计算等领域的研发工作。