概要: Rustコンパイラはすでに部分的に並列に動作していますが、本命であるフロントエンドの並列化の実用化が進んでいます。エンドユーザーが気軽に試せる状況になったようなので紹介します。

12月7日のアドベントカレンダーの枠が空いていたので、かわりに書きました。(執筆日は12月21日です)

端的に言うと

internalsのアナウンス記事に全てがまとまっています。以下のようにして「並列化対応版」と「並列化未対応版」の両方でコンパイルして、その結果を比較することができます。

$ rustup update nightly-2019-12-18
$ rustup update nightly-2019-12-17
$ cargo +nightly-2019-12-18 build
$ cargo +nightly-2019-12-17 build

コンパイル結果がおかしくないか、またコンパイル時のパフォーマンスなどを調べてほしいようなので、上記のコマンドを実行したらスレッドに投稿すると大変な貢献になると思います。

はじめに

Rustコンパイラは現在、部分的に並列に動作しています。具体的には以下のようになっています。

    • パッケージマネージャ Cargo は、依存関係のないクレート (ライブラリ) を並列にコンパイルしようと試みます。

 

    • Rustコンパイラ (Rustc) のフロントエンド (Rust特有の部分) はシングルスレッドで動作します。

 

    RustコンパイラのバックエンドであるLLVMは並列に動作します。

この真ん中のボトルネックを解消するため、2017年12月にマージされたこのコミットを皮切りにRustコンパイラフロントエンドの並列化対応が進められてきました。

しかし、この並列化対応はまだ通常配布されているRustコンパイラでは(nightlyも含め)利用できません。この理由は以下の通りです:

    • Rustはゼロコスト抽象のために、同じ機能を実現するために「シングルスレッド専用の仕組み」と「同期コストがかかるが、マルチスレッドで利用できる仕組み」を両方用意しています。

 

    • Rustコンパイラも例に漏れず、シングルスレッド専用の仕組み (Rc, RefCell など) を使っていたため、これをマルチスレッドで使える仕組み (Arc, RwLock など) に置き換える必要がありました。

 

    とはいえ、まだ並列化が実験段階なのに、そのために全てのユーザーが同期コストを支払う決断はできません。そこで、コンパイラ自体のコンパイルフラグとして parallel_compiler (旧称: parallel_queries) を追加し、この有無によって内部実装が切り替わるラッパー型 (Lrc, Lock, RwLock, LockCell) を独自に用意することになりました。

並列コンパイラを試してもらうために

実験的な並列コンパイラの実用化が近づいてきたということで、以下のようにして並列コンパイラを一時的に提供することになりました。

parallel_compiler = true にするパッチをマージする。
一日待ち、その日のnightlyがリリースされたのを確認する。

parallel_compiler = false にするパッチをマージする。

こうしてできたのが nightly-2019-12-18 で、その前のnightlyが nightly-2019-12-17 です。 (なお、ビルドパイプラインの都合上 rustc –version の表示はrustupが管理する日付より1日前になります。)

まとめ

    • Rustコンパイラは部分的に並列化されているが、肝心のコンパイラフロントエンドは並列化されていない。

 

    • 並列化機能はあるが、まだコンパイラをビルドし直すことでしか入手できない状態にある。

 

    一時的に並列化機能を有効にしたnightlyコンパイラが提供されたので、その前の日のnightlyと比較してみてほしい。