PyTorch, Chainer and Forking

Episode 13 の雑談で “PyTorch は Chainer のフォークである” というニュース記事の主張について議論しましたが、その後調べ直したところいくつか森田の勘違いがあったので現状の理解を改めて書いておきます。

まず PyTorch のソースコードや Git レポジトリの log を見るかぎり, ライセンスやコメント、コミットログや明らかなコードの重複など、はっきりとしたフォークの証拠はありません。(API の模倣については当事者による論文のドラフトなど何箇所かで言及されています。)

ウェブを検索してみると、以下のツイートが証言としてリンクされていました。

他の関係者の発言は見つかりませんでした。唯一の証言であるこの J 氏のツイートを信じるなら、フォークされたのはどうも autograd だけのようです。一方で、そもそもフォークではないと主張する証言もみつかります。

どちらの主張が正しいのでしょうか。

フォークを主張する J 氏は PyTorch への数個のコミット履歴をもつ、コードレベルでは比較的カジュアルなコントリビュータです。一方フォークでないと主張する A 氏は継続的なコミットを続ける top contributor件の autograd コードを最初にコミットとしたのもこの A 氏です。発言者の credibility という点では、フォークでないと主張する A 氏に軍配があがるのではないでしょうか。

はっきりとしたコードの類似性がないと書きましたが、実物を比べてみましょう。PyTorch での最初の Autodiff 実装はこのコミットです。一方、同時期の Chainer (1.13.0) の実装はこれ。グラフのトラバース先をキューにつめながら反復的に gradient を解決していく基本のアプローチは同じですが、表層的なコードの様子は随分違うのがわかると思います。

これは無理もない話です。Autograd のコードはどうしてもベースとなる Tensor 計算用の API に引きずられます。Chainer はその計算に CuPy というライブラリを使っています。(先に登場したバージョン 1.13.0 の時点ではまだ Chainer の一部でした。) 一方の PyTorch は Lua Torch 由来の C ライブラリをラップして使っています。

どちらも NumPy を模している点では似ていますが、drop in の互換性があるとは思えません。特に初期の PyTorch に含まれる Tensor 実装は極めて制限されたものでした。PyTorch にチェックインされた時点の autograd はごく短い単純な実装でしたから、互換性の低い CuPy を Torch に入れ替えて使えるようにするよりは Torch 向けに自分で書いてしまった方が簡単に見えます。

フォークというのはソフトウェアとして切り出しやすい単位で行わないと有り難みがなく、Autograd はその単位としてやや筋悪なのです。そういう意味でも “Autograd のコードがフォークである” とする J 氏の証言は疑わしく思えます。なお J 氏は同じツイートで “のちにコードは pure C の高速バージョンに書き直された” と言っていますが、これも厳密には間違いです。現状の PyTorch の autograd は C++ で書かれており、かつ演算単位では Python にフォールバックする可能性もある “pure C” とは程遠いものだからです。

というわけで PyTorch の Chainer フォーク説はよく似せられた API とひとつのツイートが生み出した都市伝説であるというのが自分の結論です。

フォークかどうかはさておき、API のようなソフトウェアデザインの重要な部分で PyTorch が Chainer を真似しているのは事実です。これはサンプルで引き合いにだされる NN モジュールだけでなく、 Variable や Function といったクラス、forward, backward メソッドの在処など autograd のレイヤについても言えます。ただしこれらが純粋に Chainer 由来なのか、Harvard の NumPy Autograd のような他の実装にも共通するパターンなのかについては、もう少し調査しないとわからないですね。


追記

記事を書かれた中田さんからお返事をいただきました。論拠となったのは先のツイートではなく、Facebook AI の中の人の Reddit 上の発言とのことです。