使用nGraph的Intel®Xeon®上的高性能TensorFlow
High-performance TensorFlow* on Intel® Xeon® Using nGraph
最近宣佈了nGraph的開源版本™一個C++庫、編譯器和運行時套件,用於在各種設備上運行深度神經網絡。基於Tensraph的優化項目,能公佈優化後的項目或反向代碼。與我們最初的TensorFlow集成相比,橋接代碼實現提供了高達10倍的性能。
設置很簡單(我們在bridge代碼庫中提供了說明):像平常一樣構建TensorFlow並選擇nGraph作爲TensorFlow設備,然後在現有的基於TensorFlow的DL模型中修改幾行Python代碼以針對nGraph。目前,nGraph支持Intel x86處理器上的工作負載,並將支持Intel®Nervana™ 神經網絡處理器(Intel®Nervana™ NNPs)可用時。未來對NVIDIA GPU的支持也在進行中。
英特爾至強處理器上的nGraph性能
新的nGraph TensorFlow橋比上個月開源的初始版本提供了顯著的改進。如圖1所示,與XLACPU編譯器相比,使用nGraph可以顯著提高訓練性能。雖然需要注意的是,XLA CPU的實現仍然是實驗性的,並且有很大的改進空間,但是我們的測量結果表明,nGraph與TensorFlow的IA優化的最新技術相比也非常好。圖2比較了MKL DNN優化的TensorFlow實現,它直接在TensorFlow的本地計算引擎中實現MKL-DNN優化,與nGraph TensorFlow橋代碼實現進行了比較。在使用ImageNet數據集的ResNet50等模型上,結合nGraph可以獲得更好的訓練性能(nGraph上爲68.9個圖像/秒,而TF-MKL-DNN上爲64個圖像/秒,提高了約7個百分點1)。結果還表明CIFAR10
ResNet模型的性能有了顯著的改進。然而,我們注意到,這個差距是由一個已知的問題造成的,這個問題與基線TF-MKL-DNN實現中MKL-DNN原語初始化的開銷有關。該問題的解決方案正在向上遊的TensorFlow進行。綜上所述,這些結果表明nGraph-TensorFlow集成所產生的開銷很小,並且可以實現TensorFlow最先進的IA性能。
Figure 1: Training speed using TensorFlow-XLA (2S Intel® Xeon® Platinum 8180 CPU) yields 68.9 img/sec at peak performance on
ResNet50-I1k with nGraph and 6.5 img/sec without.
Figure 2: Training speed of ResNet50-I1k using TensorFlow-XLA-nGraph (2S Intel® Xeon® Platinum 8180 CPU) yields 68.9 img/sec at peak performance with nGraph compared to 64 img/sec using MKL-DNN-optimized TensorFlow
How we did it
Performance optimizations in the nGraph CPU backend
nGraph CPU後端(有時稱爲“IA transformer”)實現了許多優化,在英特爾CPU平臺上爲給定型號提供了最優化的性能:
與框架無關的優化:
我們利用優化的內核庫,如MKL-DNN和Eigen來實現快速DNN內核。此外,我們還加入了圖優化過程,這些過程爲這些內核實現選擇了最佳的數據佈局,並減少了圖形級別的總體數據佈局轉換。我們還融合了BatchNorm和ReLu等操作,以更好地利用具有較低內存需求的融合內核實現。
TF/XLA特定的優化:
TensorFlow有一些API級別的缺陷,導致在模型中添加額外的Pad操作。這些操作可能導致不必要的數據佈局轉換,並且可以通過MKL-DNN提供的填充卷積核來避免。我們利用這一點將這些pad操作融合到現有的卷積算子中,相對於基本的TensorFlow模型,它提供了更好的性能提升。此外,XLA還添加了一些標識操作符,比如從Float32到Float32的類型轉換,這些操作符可以從圖中刪除而不影響正確性。
基於模式匹配的圖操作融合
nGraph-IR包含許多常見深度學習原語的內置原語,包括卷積、填充和批處理規範化。之所以選擇這些原語,是因爲它們可以相對容易地映射到後端庫(如“英特爾MKL-DNN”)提供的高度優化的計算內核上。
TensorFlow的tf2xla轉換器將一些高級TensorFlow操作分解爲根據低級張量操作定義的圖。一個經常發生的情況是TensorFlow的平均池操作。如果填充輸入張量,則由tf2xla將操作重寫爲包含以下內容的子圖:
a reduce-window operation to sum sliding windows of the graph;
a second reduce-window operation to compute the divisors to apply to each summed window; and
an element-wise division operation.
對圖的滑動窗口求和的減窗運算;
第二個reduce window操作,用於計算要應用於每個求和窗口的除數;以及
元素除法運算。
雖然這些操作中的每一個都直接在nGraph中得到支持,但它們的性能將不及nGraph的AvgPool原語,後者直接映射到MKL-DNN提供的優化實現。對於最大池、卷積反向傳播和其他一些重要的原語,也會出現類似的情況。
爲了解決這個問題,我們在TensorFlow到nGraph橋內部實現了一個HLO融合過程。這個融合過程,如下面的圖3所示,補充了nGraph CPU後端本身實現的許多與框架無關的優化。當HLO融合被納入時,從HLO到nGraph的轉換分三步進行。首先,搜索由tf2xla生成的原始圖形(圖3a),以查找與高級操作對應的模式(在圖3b中由橙色節點表示)。第二,每個識別出要融合的子圖被包裝在一個HLO融合指令中(圖3c)。最後,將融合後的HLO圖轉換爲nGraph圖(圖3d),並將融合指令映射到高級nGraph操作。
Figure 3: Illustration of nGraph graph generation.
fusion pass目前識別卷積反向傳播、平均和最大池的正向和反向傳播、ReLU的正向和反向傳播以及sum、product和max等縮減操作(請注意,其他一些高級操作,包括批處理規範化,在HLO中已被視爲原始操作,因此,沒有必要將它們熔合。)
它是如何工作的?
TensorFlow的XLA框架爲“後端”設備提供了一種機制,用於註冊接收以HLO格式表示的計算圖,並提供一個能夠在運行時執行計算的可執行對象。我們開發了一個XLA插件,它註冊爲“NGRAPH”設備,遵從並執行HLO計算。
一個動態加載的插件框架
目前,XLA插件設備源代碼需要駐留在TensorFlow樹中,並且必須與TensorFlow源代碼樹的其餘部分一起構建。添加一個新設備需要理解TensorFlow代碼和構建系統,這兩者都相當複雜。此外,上游和維護新代碼是困難的,有時是不可取的,因爲插件實現中的每一個更改都需要經過TensorFlow團隊的審覈,即使它可能與TensorFlow無關。
我們開發的動態可加載的XLA插件,其中實際的XLA插件源代碼位於TensorFlow源代碼樹之外,它內置於一個動態共享對象(DSO)庫中,具有許多nGraph固有的優化。在XLA方面,我們創建了一個插件適配器,該適配器加載插件DSO並使用插件DSO提供的屬性註冊XLA設備。
Graph compilation and execution
From TensorFlow* computation graph to nGraph
TensorFlow*使用XLA創建HLO計算圖。HLO的中間表示(IR)隨後被移交給nGraph插件DSO。nGraph橋的源代碼位於一個名爲nGraph tensorflow bridge的單獨GitHub存儲庫中。
當工作負載部署到目標nGraph設備時,nGraph tensorflow bridge可以將HLO-IR轉換爲nGraph-IR,然後對其進行編譯以生成特定設備的可執行代碼。然後,該可執行文件返回到TensorFlow,以便後續執行計算。
Figure 4: Transformation of TensorFlow graph to nGraph IR.
Configuration details
Hardware configuration: 2S Intel® Xeon® Platinum 8180 CPU @ 2.50GHz (28 cores), HT enabled, turbo enabled, scaling governor set to “performance” via intel_pstate driver, 384GB (12 * 32GB) DDR4 ECC SDRAM RDIMM @ 2666MHz (Micron* part no. 36ASF4G72PZ-2G6D1),800GB SSD 2.5in SATA 3.0 6Gb/s Intel Downieville
SSDSC2BB800G701 DC S3520, client ethernet adapter: Intel PCH Integrated 10 Gigabit Ethernet Controller
Software configuration: Ubuntu 16.04.3 LTS (GNU/Linux
4.4.0-109-generic x86_64). Datasets were hosted on NFS storage.
Software Release Versions:
- ngraph-tensorflow, Commit- c2cc26b
- ngraph-tensorflow-bridge, Commit- f9b9e5a
- ngraph, Commit- eec1922
Scripts:https://github.com/NervanaSystems/ngraph-tensorflow bridge/tree/master/test/resnet
Command lines
Resnet cifar10: KMP_BLOCKTIME=1 OMP_NUM_THREADS=56 KMP_AFFINITY=granularity=fine,compact,1,0 python cifar10_main.py --data_dir /path/to/dataset --model_dir /path/to/saved_model/ --batch_size 128 --resnet_size $RESNET_SIZE --data_format channels_first --inter_op 2 --select_device NGRAPH
# (RESNET_SIZE was tested at 8, 20, 56)
Resnet Imagenet(I1k): KMP_BLOCKTIME=0 OMP_NUM_THREADS=56
KMP_AFFINITY=granularity=fine,compact,1,0 python imagenet_main.py --data_dir /path/to/dataset --model_dir /path/to/saved_model/ --batch_size 128 --resnet_size 50 --data_format channels_first --inter_op 2 - select_device NGRAPH