PyTorch 1.0 へのロード : プロダクション・レディ PyTorch (翻訳)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 12/07/2018
作成日時 : 05/03/2018
* 本ページは PyTorch サイトの PyTorch 1.0 の アナウンスメントに相当する、
“The road to 1.0: production ready PyTorch” by The PyTorch Team (May 2, 2018) を翻訳したものです:
私達は PyTorch の次期リリース, PyTorch 1.0 のためのロードマップのプレビューを提供することを望みます。過去数年間に渡り、0.2, 0.3, そして 0.4 により PyTorch を [Torch+Chainer]-ライクなインターフェイスから、よりクリーンなものへ、ダブル-backward、numpy-ライクな関数、より進んだインデキシングを追加し、Variable ボイラープレートを除去しました。現時点で、1.0 を自信を持ってリリースするために API は合理的でステーブルな状態にあることを確信しています。
けれども、1.0 はインターフェイスの安定性についてだけではありません。
PyTorch の最大の強みの一つはそのファーストクラスの Python 統合、命令型スタイル、API とオプションの単純さです。これらは PyTorch を研究とハックしやすさ (= hackability) を良いものにする局面です。
その最大の欠点の一つはプロダクション・サポートでした。プロダクション・サポートにより私達が意味するところは、大規模なスケールでモデルを効率的に実行するために行わなければならない無数の事です :
- より巨大なプロジェクトでの利用のために C++-only ランタイムにエクスポートする。
- iPhone, Android, Qualcomm そして他のシステム上のモバイル・システムを最適化する。
- より効率的なデータレイアウトを使用してより高速な推論を行なうためにカーネル・フュージョンを遂行する (より大きなスケールでスピードとメモリを 10 % 節約することは大きな勝利です)。
- 量子化された推論 (8-bit 推論のような)
スタートアップ、巨大な会社そして PyTorch まわりの製品を構築することを望む誰でもプロダクション・サポートを求めてきました。Facebook (PyTorch についての最大のステークホルダー) では Caffe2 を持ち、これはプロダクション・レディ・プラットフォームであり、私達のデータセンターで動作し、そして 8 世代の iPhone と Android CPU アーキテクチャの 6 世代に及ぶ 10 億以上のスマホに出荷しています。PyTorch チームが極めて密接にワークするプラットフォームに閉じ込められたこれら総ての価値を考慮して、PyTorch と Caffe2 を結合する (= marry) ことを決定しました、これは PyTorch にプロダクション・レベルの準備を与えます。
研究者とエンドユーザのためにユーザビリティを追加することなしにプロダクション特徴をサポートすることは創造的なソリューションを必要とします。
研究者に対して Production != Pain
プロダクション機能を追加することは API の複雑さとモデルのための構成可能なオプションの数を増やすことを伴います。メモリ・レイアウト (NCHW vs NHWC vs N,C/32,H,W,32, 各々は異なるパフォーマンス特性を提供します)、量子化 (8-bit? 3-bit?)、低位カーネルのフュージョン (貴方は Conv + BatchNorm + ReLU を使用しました、それらを単一のカーネルに融合しましょう)、別々のバックエンド・オプション (少数の層のためには MKLDNN バックエンドそして他の層のためにはNNPACK バックエンド) etc. を構成します。
PyTorch の中心的なゴールは研究とハックしやすさのための素晴らしいプラットフォームを提供することです。そのため、これらの総ての最適化を追加する間に、ユーザビリティに対してこれらを決してトレードオフしないように困難なデザイン制約とともに作業してきました。
これをもぎ取るために、torch.jit, just-in-time (JIT) コンパイラを導入しています、これは実行時に貴方の PyTorch モデルを取りそしてそれらをプロダクション効率で実行するために書き直します。JIT コンパイラはまた Caffe2 ビットに基づく C++-only ランタイムで実行するために貴方のモデルをエクスポートできます。
1.0 では、貴方のコードは as-is で動作し続けます、既存の API にどのような大きな変更も行ないません。
貴方のモデルをプロダクション・レディにすることは opt-in アノテーションです、これは torch.jit を使用して貴方のモデルを Python-レス環境にエクスポートし、そのパフォーマンスを改善します。JIT コンパイラを詳細に通り抜けてみましょう。
torch.jit: 貴方のモデルのための JIT-コンパイラ
貴方のモデルを慣用的な Python コードとして直接的に指定することから得る生産性に匹敵することは困難であると私達は強く信じています。これは PyTorch を非常に柔軟にするものですが、それはまた PyTorch が貴方が次に実行する演算を決して全く知らないことを意味しています。けれどもこれはエクスポート/プロダクション化 (= productionization) そして重要な自動パフォーマンス最適化のための大きなブロッカーです、何故ならばそれらは計算が実行される前でさえどのように見えるかの前もった完全な知識を必要とするからです。
貴方のコードからこの情報をリカバーする2つの opt-in な方法を提供します、native python コードのトレースに基づく一つ、そして python-free な中間表現にアノテートされた python 言語のサブセットのコンパイルに基づく一つです。徹底的な議論の後それらは両者とも異なるコンテキストで有用となると私達は結論付けて、貴方はそのようなものとしてそれらを自由に混在して適合することができるでしょう。
Tracing モード
PyTorch tracer, torch.jit.trace, はコード領域で遂行される native PyTorch 演算の総てを記録する関数です、それらの間のデータ依存と一緒にです。実際には、PyTorch は 0.3 から tracer を持っていました、これは ONNX を通してモデルをエクスポートするために使用されてきました。今変わったことは trace を取りそれを他の場所で実行する必要がないことです – PyTorch は注意深く設計された高パフォーマンス C++ ランタイムを使用してそれを貴方のために再実行できます。PyTorch 1.0 を開発するとき、このランタイムは Caffe2 が提供する総ての最適化とハードウェア統合を統合します。
このアプローチの最大の利益はそれは貴方の Python コードがどのように構造化されているか実際にはケアしないことです — generator またはコルーチン, モジュールまたは純粋な関数を通して trace 可能です。native PyTorch 演算子を記録するだけですので、これらの詳細は記録される trace 上への作用は持ちません。この挙動は、けれども、諸刃の剣です。例えば、貴方のモデル内でループを持つ場合、それは trace で展開され、ループが実行された回数の間ループ本体のコピーが挿入されます。これはゼロコスト抽象のための機会を切り開きます (e.g. モジュールに渡りループ可能で、実際の trace はループ・オーバヘッド・フリーです!)、しかしその一方でこれはまたデータ依存ループに影響するでしょう (e.g. 様々な長さのシーケンス処理を考えてください)、効果的に単一の長さを trace にハード・コーディングするでしょう。
ループや if ステートメントを含まないネットワークのためには、tracing は非侵略的 (= non-invasive) で広い範囲のコーディングスタイルを処理するために十分に堅固です。このコードサンプルは tracing がどのように見えるかを示します :
# This will run your nn.Module or regular Python function with the example # input that you provided. The returned callable can be used to re-execute # all operations that happened during the example run, but it will no longer # use the Python interpreter. from torch.jit import trace traced_model = trace(model, example_input=input) traced_fn = trace(fn, example_input=input) # The training loop doesn't change. Traced model behaves exactly like an # nn.Module, except that you can't edit what it does or change its attributes. # Think of it as a "frozen module". for input, target in data_loader: loss = loss_fn(traced_model(input), target)
Script モード
Tracing モードは貴方のコードへのインパクトを最小化する素晴らしい方法ですが、RNN のような制御フローを根本的に利用するモデルについてもまた非常にエキサイトしています。これについての私達の解法は scripting モードです。
この場合貴方は標準的な Python 関数を書き出します、貴方はもはやある程度のより複雑な言語特徴を使用できないことを除いて。ひとたび望まれる機能を分離したら、コンパイルしたい関数を @script デコレータでそれを修飾することにより貴方は私達に知らせます。このアノテーションは貴方の Python 関数を高パフォーマンス C++ ランタイムに直接変換するでしょう。これはループと条件と一緒に PyTorch 演算子総てを私達にリカバーさせます。それらはこの関数の中間表現に埋め込まれて、この関数が実行されるたびに構成されます。
from torch.jit import script @script def rnn_loop(x): hidden = None for x_t in x.split(1): x, hidden = model(x, hidden) return x
最適化とエクスポート
tracing あるいは @script を使用するかにかかわらず、結果は貴方のモデルの python-free な表現で、これはプロダクション環境での使用のためにモデルを最適化してモデルを python からエクスポートするために使用できます。
モデルのより大きなセグメントの中間表現への抽出は、プログラム全体の洗練された最適化を行なって計算を (計算グラフ上で動作する) 特殊な AI アクセラレータにオフロードすることを可能にします。より小さい RNN モデルのパフォーマンスを改善するために GPU 演算を一緒に融合するパスを含む、これらの最適化の最初を既に開発してきています。
それはまた、モデルを効率的に実行する今日 Caffe2 で利用可能な既存の高パフォーマンスなバックエンドを利用することも可能にします。更に、@script 関数 (そしてモジュール!) はそれらの動的性質を保持する方法で完全に ONNX にエクスポート可能です、Caffe2 からのモデル executor を使用するかあるいは ONNX をサポートする任意の他のフレームワークにモデルを転送してそれらを Python-free 環境で容易に実行できるようにです。
ユーザビリティ
私達はユーザビリティの現在のレベルを維持することを深くケアしてそして Python 直接ではないコードの実行がより困難なデバッギングにつながることを知っています、しかしこれは私達が大変に考えたもので、そして完全に異なるプログラミング言語にロックインされないことを確信しています。
最初に、貴方が利用するための支払い (= pay) の原則をフォローします — もし貴方が貴方のモデルを最適化あるいはエクスポートする必要がないのであれば、これらの新しい特徴を使用しなければないということはなくどのような欠点も見ないでしょう。更に、trace されたあるいは @script モジュール/関数の使用は徐々に行なうことができます。例えば、これら総ての挙動が許されます : 貴方のモデルの一部を trace してより巨大な non-traced モデルでその trace を使用できます。貴方のモデルの 90% のために tracing を使用して、ある制御フローを内部に実際に持つ一つのサブモジュールのために @script を使用することができます。@script を使用して関数を書いてそれに native python 関数を呼び出させることができます。@script 関数で何か不正に現れた場合、アノテーションを除去することができてコードは native python で実行されます、そこでは貴方のお気に入りのツールとメソッドを使用してデバッグすることが簡単です。tracing と @script を MyPy や TypeScript を使用する型アノテーションのように考えてください — 各追加のアノテーションは徐々にテストすることが可能で、最適化やプロダクション化することを望むまでは何も要求されません。
最も重要なことに、これらのモードは PyTorch のコアに組み込まれますので貴方の既存のコードと一緒にそれらを混在して適合させることはシームレスに起こり得ます。
Note: これらのコンポーネントのための名前 JIT は少し不適切な名前で歴史的な理由に由来しています。PyTorch の tracing/関数実行は、融合された CUDA カーネルを生成する最適化する JIT コンパイラとして始まりましたが、それから最適化、@script, そしてエクスポートを包含するように成長しました。それがリリースの準備ができたときにはこの昨日をハイブリッド・フロントエンドとしておそらく名前変更するでしょう、しかしここではそれをコード内で名前付けられたように紹介することを望みます。結果として貴方はそれを私達が開発するときに追随できるでしょう。
他の変更と改良
プロダクション・サポートは 1.0 のための大きな特徴ですが、標準的なリリース・プロセスのコースのように PyTorch の他のパートも最適化して修正し続けます。
物事のバックエンド側では、PyTorch は幾つかの変更を見ます、これは user-written C と C++ 拡張に影響を与えるかもしれません。Caffe2 からの特徴や最適化を組み込むためにバックエンド ATen ライブラリを置き換えて (or リファクタリングして) います。
最後に
1.0 を夏のいつかにリリースすることを目指しています。Pull リクエスト・ページで進捗を追随できます。
以下で Caffe2 プロジェクトの展望からこれを読むことができます :
以上