> [!abstract] 概要(arXiv abstract の日本語訳) > TensorFlow は、大規模かつヘテロジニアスな環境で動作する機械学習システムである。TensorFlow はデータフローグラフを用いて計算・共有状態・その状態を変更する演算を表現する。TensorFlow はデータフローグラフの頂点を、クラスタ内の多数のマシンにまたがって、そしてマシン内では複数の計算デバイス——マルチコア CPU、汎用 GPU、Tensor Processing Unit(TPU)と呼ばれる専用設計の ASIC を含む——にまたがってマッピングする。このアーキテクチャはアプリケーション開発者に柔軟性を与える。従来の「parameter server」設計では共有状態の管理がシステムに組み込まれていたのに対し、TensorFlow は開発者が新しい最適化手法や学習アルゴリズムを実験できるようにする。TensorFlow は多様なアプリケーションをサポートし、特にディープニューラルネットワークの学習と推論に対して強力な支援を提供する。複数の Google サービスが本番で TensorFlow を利用しており、我々はこれをオープンソースプロジェクトとして公開し、機械学習研究において広く使われるようになった。本論文では、既存システムと対比しながら TensorFlow のデータフローモデルを説明し、いくつかの実世界アプリケーションで TensorFlow が達成する説得力のある性能を示す。 ## 論文情報 - タイトル: TensorFlow: A System for Large-Scale Machine Learning - 著者: Martín Abadi, Paul Barham, Jianmin Chen, Zhifeng Chen, Andy Davis, Jeffrey Dean, Matthieu Devin, Sanjay Ghemawat, Geoffrey Irving, Michael Isard, Manjunath Kudlur, Josh Levenberg, Rajat Monga, Sherry Moore, Derek G. Murray, Benoit Steiner, Paul Tucker, Vijay Vasudevan, Pete Warden, Martin Wicke, Yuan Yu, Xiaoqiang Zheng(全員 [[Google Brain]] 所属) - 媒体: OSDI 2016(12th USENIX Symposium on Operating Systems Design and Implementation) - arXiv ID: 1605.08695v2(初版投稿 2016-05-27、v2 2016-05-31) - コード: https://github.com/tensorflow/tensorflow ## 概要 TensorFlow は、Google の第一世代システム [[DistBelief]] の経験を踏まえて設計された、大規模かつヘテロジニアスな環境向けの機械学習システムである。計算とミュータブルな共有状態を単一のデータフローグラフで統一的に表現することで、従来 parameter server アーキテクチャがシステム内部に組み込んでいた機能(パラメータの保持・更新)を、ユーザー空間のグラフ上の演算として表現できるようにした。これにより研究者は、システム内部の C++ 実装を変更せずに新しい最適化アルゴリズムや並列化戦略を実験できる。 ## 問題設定 前提として、大規模機械学習システムには次の要件がある。 - **分散実行**: より多くのデータとより大きなモデルを、クラスタ全体で効率的に扱えること。ImageNet(136 GB)や One Billion Word Benchmark(80 万語の語彙、10.4 億パラメータのモデル)のような大規模データセット・モデルは、データ並列(ミニバッチ勾配降下法)とモデル並列の両方を要求する。 - **アクセラレータ対応**: 汎用 GPU(例: NVIDIA Titan X で 6 TFLOPS)や、Google が構築した Tensor Processing Unit(TPU)のような専用アクセラレータを、移植可能なプログラミングモデルの下で活用できること。 - **学習と推論の両対応**: モデル定義コードを学習・推論の双方で共有し、データセンターから携帯端末までの多様な実行環境をサポートすること。 - **拡張性**: Caffe・Theano・Torch のような単一マシン向けフレームワークが持つ実験のしやすさを保ちつつ、分散実行と本番運用へのスケールアップを両立すること。 入力は、演算・変数・入力前処理を含む機械学習アルゴリズム全体を表現したデータフローグラフと、実行対象の部分グラフを指定するステップ定義である。出力は、指定した出力エッジのテンソル値である。 ## 提案手法 - **アーキテクチャ**: TensorFlow は単一のデータフローグラフで計算・状態・状態変更演算を表現する。従来のバッチデータフローシステム(不変データ上の関数的計算)と異なり、頂点はミュータブルな状態を保持・更新する演算を表現できる。グラフの各頂点は演算(operation)、各辺はテンソル(多次元配列)を表す。 **Figure 1: 学習パイプラインのデータフローグラフ** ![[_attachments/arxiv-1605.08695/fig01-dataflow-training-pipeline.png]] (Figure 1. 入力データの読み込み・前処理・学習・チェックポイント保存という 4 つのサブグラフが並行実行される様子を示す模式図。パラメータの読み込みと勾配の適用が学習サブグラフを構成し、定期的なチェックポイントが分散ファイルシステムへ書き出される。) - **テンソルと演算**: すべてのデータを int32・float32・string などの型を持つ密な n 次元配列(テンソル)として扱う。疎テンソルは可変長文字列への符号化、またはインデックス行列と値ベクトルの組で表現する。演算は m 個の入力テンソルから n 個の出力テンソルを生成し、コンパイル時属性(`Const` の `T`・`Value`、`AddN` の `T`・`N` 等)で挙動を決める。 - **ステートフルな演算**: `Variable` 演算はミュータブルなバッファを保持し参照ハンドルを返す。`Read` はそのハンドルから現在値を読み、`AssignAdd` のような演算がバッファを in-place で更新する(`State'[r] ← State[r] + x`)。`FIFOQueue` などのキュー演算も参照ハンドルを介した状態を持ち、`Enqueue`/`Dequeue` によるブロッキングで入力パイプラインのバックプレッシャーと同期を実現する。 - **部分実行と並行実行**: クライアントは feed する入力エッジと fetch する出力エッジを宣言的に指定し(1 回の呼び出しを「ステップ」と呼ぶ)、ランタイムは必要な演算だけを含むよう部分グラフを刈り込む(pruning)。同一グラフ上で複数ステップを並行実行でき、ステートフルな演算がステップ間の協調を担う。 - **分散実行**: 各演算は特定タスクの特定デバイス(CPU/GPU)に配置される。配置アルゴリズムは各演算に実行可能なデバイス集合を計算し、コロケーション制約(ステートフルな演算とその状態は同一デバイスに置く)を満たしつつデバイスを選ぶ。配置後、デバイス境界を跨ぐ辺は `Send`/`Recv` 演算に置き換えられ、`Send` はランデブーキーを付けて即時送信、`Recv` は該当キーの値が到着するまでブロックする。ステップのサブグラフはデバイスごとにキャッシュされ、再利用によって低レイテンシを実現する。 - **動的制御フロー**: 再帰ニューラルネットワークの効率的な学習など非厳格な評価を要する処理のために、Arvind and Culler の動的データフローアーキテクチャに基づく `Switch`/`Merge` プリミティブで条件分岐とループを実装する。 **Figure 2: Switch と Merge を用いた条件分岐グラフ** ![[_attachments/arxiv-1605.08695/fig02-conditional-switch-merge.png]] (Figure 2. `Switch` は制御入力に基づき 2 つの出力の一方にデータを渡し、選ばれなかった側には dead value を伝播する。`Merge` は dead でない入力を 1 つだけ出力へ転送する。この 2 つを組み合わせて非厳格な条件分岐サブグラフを構築する。) - **新規最適化・アルゴリズムのユーザー空間実装(拡張性のケーススタディ)**: TensorFlow は次の 4 つの拡張を、ランタイム本体を変更せず「ユーザーレベル」コードとして実装した。 - **微分と最適化**: ユーザーレベルの自動微分ライブラリが、損失関数から各パラメータへの逆方向パスを幅優先探索で特定し、各パスの部分勾定を合算して逆伝播を導出する。DistBelief では Momentum のようなアルゴリズムを実装するのに parameter server の C++ コードを直接改変する必要があったが、TensorFlow では `Variable` と基本的な数学演算の組み合わせだけで Momentum・Adagrad・Adadelta・RMSProp・Adam・L-BFGS などを実装できる。 - **疎な埋め込み層への対応**: 語彙数 n と埋め込み次元 d の埋め込み行列(数十億パラメータ、モデルによっては数テラバイトに達する)を複数の parameter server タスクにシャーディングし、`Gather`(疎な行の抜き出し)・`Part`(インデックスの動的パーティション分割)・`Stitch`(部分結果の再結合)という基本演算の合成で疎な埋め込みルックアップを表現する。 **Figure 3: 疎な埋め込み層のデータフローグラフ** ![[_attachments/arxiv-1605.08695/fig03-sparse-embedding-layer.png]] (Figure 3. 2 つの parameter server タスクに分割された埋め込み行列に対する疎な埋め込み層の模式図。`Gather` は変数と同じデバイスに配置され、`Part`/`Stitch` によって各シャードの部分結果が結合される。この構成は自動微分にも対応する疎な更新演算を生成する。) - **耐障害性**: `Save`/`Restore` というグラフ上の基本演算でユーザーレベルのチェックポイントを実装する。各タスクの `Variable` を 1 つの `Save` にまとめ分散ファイルシステムへの I/O 帯域を最大化する。チェックポイントは一貫性を保証しないが、非同期勾配降下法で学習する多くのモデルではこれが問題にならない。 - **同期レプリカ協調**: SGD は非同期でも頑健だが、GPU の登場で数百台規模のマシンで同期学習が可能になったことを踏まえ、キュー(§3.1)を用いた 3 種類のパラメータ同期方式を実装した。 **Figure 4: 3 つのパラメータ同期方式** ![[_attachments/arxiv-1605.08695/fig04-parameter-sync-schemes.png]] (Figure 4. データ並列学習における単一パラメータの同期方式。(a) 非同期レプリケーション: 各ワーカーがステップ開始時に現在値を読み、終了時に勾定を適用するため高スループットだが情報が古い。(b) 同期レプリケーション: 全ワーカーの更新をブロッキングキューで蓄積してから一括適用するため遅いワーカーがスループットを制限する。(c) バックアップワーカー付き同期レプリケーション: n 人中最初の m 人の更新を採用し、ストラグラーの影響を緩和する。) - **実装**: システムは C++ で実装されたコアライブラリと、それを薄い C API で覆う多言語クライアント(Python・C++ を優先)から構成される。分散マスタが与えられたグラフとステップ定義を刈り込み・配置・分割し(共通部分式除去や定数畳み込みも行う)、各タスクのデータフローエグゼキュータがカーネルのスケジューリングと実行を担う。現在の実装では 1 秒あたり約 200 万個の null 演算をディスパッチできる。ランタイムは 200 種類超の標準演算を持ち、多くのカーネルは `Eigen::Tensor` で実装されるが、性能が重要な演算(cuDNN・gemmlowp 等)には専用ライブラリを利用する。デバイス間転送は `cudaMemcpyAsync()`(CPU↔GPU)、DMA(GPU↔GPU)、gRPC over TCP や RDMA over Converged Ethernet(タスク間)など、デバイス種別ごとに特化した実装を持つ。 **Figure 5: TensorFlow の階層アーキテクチャ** ![[_attachments/arxiv-1605.08695/fig05-layered-architecture.png]] (Figure 5. C API の上に Python/C++ クライアントと学習・推論ライブラリを配置し、C API の下に分散マスタとデータフローエグゼキュータ、その下にカーネル実装、さらにネットワーキング層(RPC・RDMA)とデバイス層(CPU・GPU)を配置する。) ## 新規性 DistBelief をはじめとする既存の parameter server アーキテクチャ(Project Adam、Li らの "Parameter Server")は、共有状態の管理(読み書き・整合性モデル・耐障害性)を「特権的」なシステム内部コードとして実装しており、新しい最適化アルゴリズムを試すには C++ 実装の改変が必要だった。MXNet も同様に parameter server を特権コードとして持つ。TensorFlow は、ミュータブルな状態を持つ頂点を許すデータフローグラフによって parameter server の機能そのものをユーザー空間のグラフ演算として再現し、パラメータを保持するマシン上へ任意の計算をオフロードできる柔軟性を追加した。これにより研究者は異なる最適化アルゴリズム・整合性スキーム・並列化戦略を、システム内部を変更せずに実験できる。単一マシン向けフレームワーク(Caffe・Theano・Torch)は分散実行の要件を満たさず、バッチデータフローシステム(MapReduce・DryadLINQ・Spark)は入力データの不変性と決定性を要求するため、モデル更新のような重い操作に不向きである。Naiad はミュータブルな状態と timely dataflow による反復をサポートするが GPU アクセラレーションを持たない。 ## 実験設定 - **実験環境**: 単一マシンベンチマーク(§6.1)は 6 コア Intel Core i7-5930K(3.5 GHz)と NVIDIA Titan X GPU を使用。分散ベンチマーク(§6.2–6.4)は共有の本番クラスタ上で実行し、図はすべて中央値と 10–90 パーセンタイルの誤差範囲を示す。Inception-v3 学習では 1 ワーカータスクあたり NVIDIA K40 GPU 1 基と IvyBridge コア 5 個、parameter server タスクあたり IvyBridge コア 8 個を使用し、17 個の PS タスクを配置した。 - **データセット/モデル**: 画像分類には Google の Inception-v3(ILSVRC 2012 で 78.8% の精度)を使用。言語モデリングには One Billion Word Benchmark を、40,000 語(全 80 万語のうち)に絞った語彙で LSTM-512-512 を学習した。 - **比較対象**: 単一マシンベンチマークでは Caffe・Neon・Torch と比較(§6.1)。 - **評価指標**: ステップ時間(ms/step)、スループット(images/sec、words/sec、batches/sec)、正規化スピードアップ `t(b)/t(0) × 50/(50+b)`(b はバックアップワーカー数)。 ## 実験結果 - **単一マシン性能**(§6.1、Table 1): 4 つの畳み込みモデル(AlexNet・Overfeat・OxfordNet・GoogleNet)のステップ時間を比較したところ、TensorFlow は Caffe より短いステップ時間を達成し、Torch とは 6% 以内の性能差だった。TensorFlow と Torch がほぼ同性能なのは両者が同じ cuDNN ライブラリを使うためで、Caffe はより簡素だが低効率な独自実装を使う。手作業でアセンブリ最適化した Neon は 3 モデルで TensorFlow を上回った。 **表1: 4種の畳み込みモデルの学習ステップ時間(ms)** | Library | AlexNet | Overfeat | OxfordNet | GoogleNet | |---|---|---|---|---| | Caffe [36] | 324 | 823 | 1068 | 1935 | | Neon [56] | 87 | **211** | **320** | **270** | | Torch [17] | **81** | 268 | 529 | 470 | | TensorFlow | **81** | 279 | 540 | 445 | (Table 1. NVIDIA Titan X GPU 1 基・32bit float 学習でのステップ時間。太字は各モデルで最速のライブラリ。) - **同期レプリカのマイクロベンチマーク**(§6.2、Figure 6): null 学習ステップ(実質的な計算をせず PS からパラメータを取得し更新を送るだけのステップ)のスループットを測定した。Scalar(4 バイト値 1 個のみ取得)のステップ時間は 1 ワーカーで 1.8 ms、100 ワーカーで 8.8 ms。Dense 100MB モデルは 1 ワーカー 147 ms から 100 ワーカー 613 ms、Dense 1GB モデルは 1 ワーカー 1.01 s から 100 ワーカー 7.16 s に増加。疎アクセス(Sparse 1GB/16GB)はモデルサイズに依存せず 5–20 ms の範囲に収まり、埋め込み行列のような大規模モデルを効率的に扱えることを示す。 **Figure 6: 同期レプリケーションの null モデルにおけるベースラインスループット** ![[_attachments/arxiv-1605.08695/fig06-synchronous-null-throughput.png]] (Figure 6. 疎アクセスはモデルサイズが 1GB でも 16GB でも同程度のスループットを維持し、TensorFlow が埋め込み行列のような大規模モデルを扱えることを示す。) - **画像分類**(§6.3、Figure 7–8): Inception-v3 の学習で、ワーカー数を 200 まで増やすとスループットは 2,300 images/sec まで向上するが、収穫は減少する。ワーカーを増やすとステップ時間も増加し、これは PS タスクへの競合(ネットワークインタフェースと更新集約の両方)によるもの。同期ステップは非同期ステップより中央値で約 10% 長いが、90 パーセンタイル以上ではストラグラーの影響で同期性能が急激に劣化する。 **Figure 7: Inception-v3 学習のスケーラビリティ** ![[_attachments/arxiv-1605.08695/fig07-inceptionv3-scaling.png]] (Figure 7. (a) ワーカー数 200 まで学習スループットが増加するが収穫は減少する。(b)(c) ワーカー数が増えるとステップ時間の分布が非同期・同期の両方で右にシフトする。) バックアップワーカーの追加効果として、50 ワーカーの Inception 学習に対しバックアップワーカーを 1〜4 人まで増やすとステップ時間が短縮する(4 人で最短の 1.93 s)。3 人のバックアップワーカーは正規化スピードアップが最大(9.5%)となり、追加リソース込みで最も効率的だった。5 人目のバックアップワーカーは、破棄される 51 番目のワーカーの結果がストラグラーである確率が下がりむしろ PS への流入トラフィックを増やすため、わずかに性能を悪化させる。 **Figure 8: バックアップワーカーによるステップ時間短縮** ![[_attachments/arxiv-1605.08695/fig08-backup-workers-steptime.png]] (Figure 8. 50 ワーカーの Inception-v3 学習において、バックアップワーカー 4 人で最短のステップ時間(1.93 s)、3 人で最大の正規化スピードアップ(9.5%)を得る。) - **言語モデリング**(§6.4、Figure 9): One Billion Word Benchmark を 40,000 語の語彙に絞った LSTM-512-512 の学習で、PS タスク数を増やすと softmax 計算の並列化によりスループットが向上する。フル softmax(重み行列 512×40,000 を PS 間でシャーディング)は PS タスクを 1 個から 2 個に増やす効果が、4→32 や 32→256 ワーカーへの増加より大きい。サンプル済み softmax(真のクラス + ランダムサンプルした偽クラスのみを対象とする疎な乗算)は、データ転送と計算量を 512/40,000 ≈ 1/78 に削減し、フル softmax よりスループットを向上させる。 **Figure 9: PS タスク数増加による言語モデル学習スループットの向上** ![[_attachments/arxiv-1605.08695/fig09-language-model-ps-scaling.png]] (Figure 9. PS タスク数を 1 から 32 に増やすとスループットが向上し、サンプル済み softmax はフル softmax より計算量を削減して高いスループットを達成する。ただし十分な PS タスク数では LSTM 自体の計算がスループットを支配し飽和する。) ## 考察 - 単一マシン性能は Torch と同水準であり、cuDNN のような共通ライブラリへの依存が性能差の主要因になっている。手作業アセンブリ最適化(Neon)には及ばないが、著者らはそうしたカーネルを将来的に TensorFlow へ実装可能だとしている。 - 同期レプリケーションは中央値では非同期に近い性能を出せるが、テール(90 パーセンタイル以上)でストラグラーの影響を強く受ける。バックアップワーカーはこのテール劣化を緩和する実用的な手段であり、MapReduce のバックアップタスクと異なり反応的でなく積極的(proactive)に起動する点が特徴である。 - 疎な埋め込みやサンプル済み softmax のような大規模モデル特有の最適化は、システム内部を変更せずグラフ上のユーザーレベル演算として実装できており、TensorFlow の拡張性設計の主張(§4)を実験的に裏付けている。 - 本評価はシステム性能指標(スループット・ステップ時間)に焦点を当てており、学習が目標精度へ到達するまでの時間(time-to-accuracy)のような学習効率の評価は他論文に委ねている。 ## 強み / 弱点・課題 **強み** - データフローグラフに状態変更演算を許すという単一の抽象化により、parameter server の機能をシステム内部の特権コードからユーザー空間へ移し、拡張性(新しい最適化アルゴリズム・並列化戦略の実験)と分散実行を同時に満たした。 - 60 チーム超が利用し、複数の Google 本番サービスに投入されているという実運用実績を持ち、オープンソース化によって研究コミュニティにも広く採用された。 - マルチコア CPU・GPU・TPU・モバイル端末まで、同一のプログラミングモデルで学習と推論の双方をカバーする移植性を持つ。 **弱点・課題** - 単一マシン性能では、手作業でアセンブリ最適化したカーネルを持つ Neon に 3 モデルで劣る(著者らも今後の実装課題として認めている)。 - チェックポイント機構は一貫性を保証しない設計であり、一貫したチェックポイントを取るには追加の同期が必要になる。 - 同期レプリケーションはストラグラーに対して脆弱であり、バックアップワーカーで緩和はできるものの完全には解消しない。 - 本論文は学習効率(収束速度・到達精度)の評価を目的の外に置いており、システム性能のみに焦点を当てている。 ## 関連 - [[TensorFlow]](本論文が一次ソース) - [[Parameter Server]](対比対象。DistBelief・Project Adam・Li らの Parameter Server を先行研究として引用) - [[Google TPU]](§2.1 でアクセラレータの一つとして言及) - [[DistBelief]](TensorFlow の前身システム) - [[Google Brain]] / [[Google]]