小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

深度學(xué)習(xí)利器: TensorFlow系統(tǒng)架構(gòu)及高性能程序設(shè)計(jì)

 loudf 2017-07-24

2015年11月9日谷歌開源了人工智能平臺(tái)TensorFlow,同時(shí)成為2015年最受關(guān)注的開源項(xiàng)目之一。經(jīng)歷了從v0.1到v0.12的12個(gè)版本迭代后,谷歌于2017年2月15日發(fā)布了TensorFlow 1.0 版本,并同時(shí)在美國加州山景城舉辦了首屆TensorFlow Dev Summit會(huì)議。

TensorFlow 1.0及Dev Summit(2017)回顧

和以往版本相比,TensorFlow 1.0 的特性改進(jìn)主要體現(xiàn)在以下幾個(gè)方面:

  • 速度更快:TensorFlow 1.0版本采用了XLA的編譯技術(shù),改進(jìn)了TensorFlow的運(yùn)行性能及內(nèi)存利用。從Benchmark問題的測(cè)試結(jié)果來看,對(duì)單機(jī)Inception v3模型,實(shí)現(xiàn)了在單機(jī)8 GPUs上7.3倍的運(yùn)算加速;對(duì)分布式Inception v3模型,實(shí)現(xiàn)了在多機(jī)64 GPUs上58倍的運(yùn)算加速。
  • 更加靈活:該版本除了支持tf.layers,tf.metrics及tf.losses模型的High-Level API外,實(shí)現(xiàn)了對(duì)keras(high-level neural networks library)API的全面兼容。
  • 更產(chǎn)品化:TensorFlow Python API在v1.0版本中趨于穩(wěn)定,為產(chǎn)品兼容性打下堅(jiān)實(shí)基礎(chǔ)。

在TensorFlow 1.0版本發(fā)布的當(dāng)天,谷歌公司還舉辦了TensorFlow 2017 DEV Summit。該日程主要包括以下幾個(gè)方面的主題演講:


TensorFlow系統(tǒng)架構(gòu)

TensorFlow作為分布式機(jī)器學(xué)習(xí)平臺(tái),主要架構(gòu)如下圖所示。RPC和RDMA為網(wǎng)絡(luò)層,主要負(fù)責(zé)傳遞神經(jīng)網(wǎng)絡(luò)算法參數(shù)。CPU和GPU為設(shè)備層,主要負(fù)責(zé)神經(jīng)網(wǎng)絡(luò)算法中具體的運(yùn)算操作。Kernel為TensorFlow中算法操作的具體實(shí)現(xiàn),如卷積操作,激活操作等。Distributed Master用于構(gòu)建子圖;切割子圖為多個(gè)分片,不同的子圖分片運(yùn)行在不同的設(shè)備上;Master還負(fù)責(zé)分發(fā)子圖分片到Executor/Work端。Executor/Work在設(shè)備(CPUs,GPUs,etc.)上,調(diào)度執(zhí)行子圖操作;并負(fù)責(zé)向其它Worker發(fā)送和接收?qǐng)D操作的運(yùn)行結(jié)果。C API把TensorFlow分割為前端和后端,前端(Python/C++/Java Client)基于C API觸發(fā)TensorFlow后端程序運(yùn)行。Training libraries和Inference libs是模型訓(xùn)練和推導(dǎo)的庫函數(shù),為用戶開發(fā)應(yīng)用模型使用。

下圖為Client、Master及Worker的內(nèi)部工作原理。"/job:worker/task:0" 和 "/job:ps/task:0" 表示worker中的執(zhí)行服務(wù)。"job:ps"表示參數(shù)服務(wù)器,用于存儲(chǔ)及更新模型參數(shù)。"job:worker"用于優(yōu)化模型參數(shù),并發(fā)參數(shù)發(fā)送到參數(shù)服務(wù)器上。Distributed Master和Worker Service只存在于分布式TensorFlow中。單機(jī)版本的TensorFlow實(shí)現(xiàn)了Local的Session,通過本地進(jìn)程的內(nèi)部通訊實(shí)現(xiàn)上述功能。

用戶編寫TensorFlow應(yīng)用程序生成計(jì)算圖,Client組件會(huì)創(chuàng)建Session,并通過序列化技術(shù),發(fā)送圖定義到Distributed Master組件。下圖中,Client創(chuàng)建了一個(gè) s+=w*x+b的圖計(jì)算模型。

當(dāng)Client觸發(fā)Session運(yùn)算的時(shí)候,Maser構(gòu)建將要運(yùn)行的子圖。并根據(jù)設(shè)備情況,切割子圖為多個(gè)分片。下面為Master構(gòu)建的運(yùn)行子圖:

接著切割子圖,把模型參數(shù)分組在參數(shù)服務(wù)器上,圖計(jì)算操作分組在運(yùn)算Worker上。下圖為一種可行的圖切割策略:

Distributed Master會(huì)根據(jù)模型參數(shù)的分區(qū)情況進(jìn)行切割邊,在Task間插入發(fā)送和接收Tensor信息的通信節(jié)點(diǎn),如下圖所示:

接著Distributed Master通過RegisterGraph方法發(fā)送子圖分片給Task,如下圖所示:

Master通過RunGraph觸發(fā)子圖運(yùn)算,Worker會(huì)使用GPU/CPU運(yùn)算設(shè)備執(zhí)行TensorFlow Kernel運(yùn)算。在本節(jié)點(diǎn)的CPU和GPU之間,使用cudaMemcpyAsync傳輸數(shù)據(jù);在本節(jié)點(diǎn)GPU和GPU之間,使用peer-to-peer DMA傳輸數(shù)據(jù),避免通過CPU復(fù)制數(shù)據(jù)。TensorFlow使用gRPC(TCP)和RDMA (Converged Ethernet)技術(shù),實(shí)現(xiàn)Worker間的數(shù)據(jù)通信及傳輸,如下圖所示:

高性能程序設(shè)計(jì)

TensorFlow內(nèi)核采用C/C++開發(fā),并提供了C++,Python,Java,Go語言的Client API。特別是Python API,是目前主流的TensorFlow模型開發(fā)接口。但為什么還需要采用C++ API去訓(xùn)練模型呢?本文基于如下兩點(diǎn)考慮,首先當(dāng)我們采用Python API去訓(xùn)練模型的時(shí)候,需要不斷地用Python API調(diào)用C/C++底層接口,重復(fù)的接口調(diào)用一定程度上影響了程序的執(zhí)行性能。更為重要的是,在GPU上訓(xùn)練模型的時(shí)候需要大量的內(nèi)存交換;如果采用C++ API去訓(xùn)練模型,可提供更好的運(yùn)算性能及更好地控制GPU內(nèi)存的分配。

下圖為Python API的運(yùn)算架構(gòu):在模型訓(xùn)練的每次迭代中,程序通過Python API讀取Batch Data,然后通過TensorFlow Session Run接口,傳遞數(shù)據(jù)給C++,并觸發(fā)神經(jīng)網(wǎng)絡(luò)訓(xùn)練。如下圖所示:

下圖為C++ API的運(yùn)算架構(gòu):在模型訓(xùn)練的每次迭代中,通過C++ API讀取Batch Data后,直接觸發(fā)模型訓(xùn)練。減少了不同語言間API接口的循環(huán)調(diào)用及數(shù)據(jù)傳輸。如下圖所示:

為了采用C++ API進(jìn)行模型訓(xùn)練,我們首先需要編寫訓(xùn)練模型,這個(gè)編寫過程可以采用Python語言來完成。我們首先采用Python API編寫訓(xùn)練模型,然后把圖模型轉(zhuǎn)換為Protobuf的序列化文件。接著通過C++ API加載該模型文件,創(chuàng)建TensorFlow Session,初始化模型變量,以及加載訓(xùn)練數(shù)據(jù)并執(zhí)行神經(jīng)網(wǎng)絡(luò)訓(xùn)練。程序架構(gòu)如下圖所示:

下面為使用Python API定義訓(xùn)練模型的示例:

with tf.Session() as sess:

#定義Placeholder Tensor接入訓(xùn)練數(shù)據(jù)
    x = tf.placeholder(tf.float32, [None, 32], name="x")
    y = tf.placeholder(tf.float32, [None, 8], name="y")

    #定義訓(xùn)練模型
    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')

    #把圖模型轉(zhuǎn)換為Protobuf文件
tf.train.write_graph(sess.graph_def, './', 'mlp.pb', as_text=False)

下面為使用C++ API加載Protobuf圖模型,并執(zhí)行訓(xùn)練的示例:

#include "tensorflow/core/public/session.h"
#include "tensorflow/core/graph/default_device.h"
using namespace tensorflow;

int main(int argc, char* argv[]) {
    //Protobuf模型文件名
    std::string graph_definition = "mlp.pb";
    //Tensorflow Sesssion
    Session* session;

    //定義圖模型對(duì)象
    GraphDef graph_def;
    SessionOptions opts;

    //存儲(chǔ)Session會(huì)話的運(yùn)行結(jié)果
    std::vector<Tensor> outputs; 

    #加載Protobuf模型文件到圖模型對(duì)象中
    TF_CHECK_OK(ReadBinaryProto(Env::Default(), graph_definition, &graph_def));

    // 默認(rèn)在gpu 0上執(zhí)行模型的訓(xùn)練操作
    graph::SetDefaultDevice("/gpu:0", &graph_def);

    //設(shè)定GPU顯存使用參數(shù)
    opts.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.5);
    opts.config.mutable_gpu_options()->set_allow_growth(true);

    //創(chuàng)建TensorFlow會(huì)話
    TF_CHECK_OK(NewSession(opts, &session));

    // 加載圖對(duì)象到會(huì)話中
    TF_CHECK_OK(session->Create(graph_def));

    // 執(zhí)行模型參數(shù)初始化操作
    TF_CHECK_OK(session->Run({}, {}, {"init_all_vars_op"}, nullptr));

    //定義模型輸入數(shù)據(jù),包括數(shù)據(jù)類型和維度信息
    Tensor x(DT_FLOAT, TensorShape({100, 32}));
    Tensor y(DT_FLOAT, TensorShape({100, 8}));

    //把Tensor轉(zhuǎn)換為矩陣,并初始化Tensor數(shù)據(jù)
    auto _XTensor = x.matrix<float>();
    auto _YTensor = y.matrix<float>();
    _XTensor.setRandom();
    _YTensor.setRandom();

    for (int i = 0; i < 10; ++i) {
        //執(zhí)行模型的訓(xùn)練操作,{{"x", x}, {"y", y}}表示輸入數(shù)據(jù)Tensor名稱和Tensor對(duì)象;{"cost"}表示要獲取輸出值的操作名稱;&outputs表示執(zhí)行"cost"操作后返回的Tensor對(duì)象
        TF_CHECK_OK(session->Run({{"x", x}, {"y", y}}, {"cost"}, {}, &outputs)); 

        //獲取執(zhí)行“cost“操作后的運(yùn)算結(jié)果
        float cost = outputs[0].scalar<float>()(0);
        std::cout << "Cost: " << cost << std::endl;

        //執(zhí)行"train"操作
        TF_CHECK_OK(session->Run({{"x", x}, {"y", y}}, {}, {"train"}, nullptr)); // Train
        outputs.clear();
    }

    //關(guān)閉Session及刪除Session對(duì)象
    session->Close();
    delete session;
    return 0;
}

當(dāng)C++程序?qū)懞煤螅幾g時(shí)候需要鏈接的頭文件,開源已經(jīng)幫我們整理好了,存放于目錄/usr/lib/python2.7/site-packages/tensorflow/include下。編譯和運(yùn)行的時(shí)候需要鏈接libtensorflow_cc.so,可以按照下面的方式編譯該庫文件:bazel build -c opt //tensorflow:libtensorflow_cc.so --copt=-m64 --linkopt=-m64 --spawn_strategy=standalone --genrule_strategy=standalone --verbose_failures。具體可參考TensorFlow源代碼的官方編譯文檔。

總結(jié)

本文首先回顧了TensorFlow 1.0主要新特性及TensorFlow 2017 Dev Summit的主要議程。到目前為止TensorFlow的GitHub Star排名為51000+, Fork排名已達(dá)24000+,有15000+ commits。并隨著TensorFlow新版本的不斷發(fā)布以及新特性的不斷增加,TensorFlow使用更加靈活,運(yùn)行速度更快,使用方式更產(chǎn)品化,已成為目前主流的深度學(xué)習(xí)平臺(tái)之一。

接著介紹了TensorFlow的系統(tǒng)架構(gòu),包括Client,Master,Worker,Kernel的相關(guān)概念及運(yùn)行方式,是一種適合大規(guī)模分布式訓(xùn)練的機(jī)器學(xué)習(xí)平臺(tái)。從上述系統(tǒng)架構(gòu)中可以看到,TensorFlow內(nèi)核采用C/C++開發(fā),當(dāng)采用Python API去訓(xùn)練模型的時(shí)候,需要不斷地用Python調(diào)用C/C++底層接口,重復(fù)的接口調(diào)用一定程度上影響了程序的執(zhí)行性能。如果有最求高性能運(yùn)算的朋友,可以嘗試用下本文高性能運(yùn)算章節(jié)推薦的方法。


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多