KNOWLEDGE - COLUMN ナレッジ - コラム

【エバンジェリスト・ボイス】Ninjaでビルドを高速化してみよう

先端技術部
エバンジェリスト 黒住 好忠   

こんにちは。先端技術部、エバンジェリストの黒住です。(2020年10月に、グローバルイノベーションセンターから先端技術部に部署異動しました)

皆さまは、オープンソースのプロジェクトを自分でビルドする機会はあるでしょうか?
私の場合は、独自環境に合わせてカスタマイズしたり、最新環境に対応させるために、独自にオープンソースプロジェクトをビルドする機会がよくあります。

ビルドや動作が保証されている環境ならまだしも、保証の無い最新環境でビルドする場合、1回でビルドが成功する確率は極めて低くなります。そのため、ビルドしてはエラー箇所を修正し、再びビルドしてエラー箇所を修正…という作業を、何回、何十回と繰り返すことも珍しくありません。

そのため、ビルド時間は短いほど良いのですが、実際のオープンソースプロジェクトはビルドに数十分から数時間を要するものもよく見られます。数時間待った上に、ビルドエラーが出ると心が折れてしまいそうですね。

まずはNinjaの実力を見てみよう


このようなビルド時間の問題を解決してくれるのがNinjaです!
Ninjaはビルドを高速化することに焦点を当てて開発されたツールなので、その効果には期待が持てそうですね。

どのくらい高速化できるかは利用している環境によっても異なるのですが、コア数の多いCPUを利用しているほど高速になる傾向があります。というわけで、まずはNinjaの凄さを見てみましょう。

今回は、C/C++で作成されたオープンソースのVTKとOpenCVを、一般的なVisual Studio 2019 (MSBuild)とNinjaでビルドしてみました。プラットフォームはWindows 10で、CPUはAMD Ryzen Threadripper 3960X(24core/48thread)を使っています。

まずはVTKのビルド結果です。

graph-vtk_927x322

デフォルト設定でVTKをVisual Studio 2019でビルドすると、25分29秒もかかりました。一方、Ninjaを使うと、わずか1分51秒でビルドできています。

VTKのデフォルトは、複数コアを利用しないビルド設定になっているため、CMAKE_CXX_MP_FLAGを指定し複数コアを使ってビルドした結果も載せています。(CMAKE_CXX_MP_FLAGを有効にすると/MPオプションが追加され、Visual Studioで複数コアを利用したビルドが行えるようになります)

とはいえ、Visual Studioで複数コアを利用した場合でも、5分20秒かかっており、Ninjaがどれだけ高速か分かっていただけると思います。

つづいて、OpenCVのビルド結果です。

graph-opencv_927x257

OpenCVの場合はデフォルトで/MPオプション(複数コアを使ったビルド)が有効になっていますが、それでもやはりNinjaの方が3倍ほど高速にビルドできています。

感動的ですね!

CPUの使われ方を見てみよう


Ninjaが高速な理由のひとつに、CPUの使われ方の違いがあります。
複数コアを使って同時にビルドした方が一般的には高速になるのですが、実際にはビルドの依存関係(Bをビルドするためには、先にAをビルドしておく必要がある…とか)があり、単純に並列化できない難しさがあります。Ninjaは依存関係の検出に特別なアプローチを採用し、効率的な並列処理が行えるように工夫されているように見えます。
そして、その結果がCPUの使われ方の違いとして現れているのだと思われます。

実際に、VTKをビルドしたときのCPUの使われ方を見てみましょう。

build-vs-sp_1357x683

上記のグラフは、VTKのデフォルト設定でVisual Studio 2019を使ってビルドした時のCPU使用率のグラフです。(タスクマネージャーのCPUパフォーマンスのグラフ)

見ての通り、一部のコアしか利用されておらず、大半が何も処理をしていない状態になっています。
これだと、複数のCPUコアがあったとしても、1コアしか使われないためビルド時間も大幅に伸びてしまいますね。

build-vs-mp_1357x683

続いて、/MPオプションを指定して、Visual Studio 2019で複数コアを利用できるようにしてビルドした時のグラフが上記になります。

複数コアが使われるようになっていますが、それでも各コアが常にフル稼働しているわけでは無く、全体的に空きがあります。

build-ninja_1357x683

最後にNinjaを使ってビルドした時のグラフです。
グラフを見ても分かるように、全コアが常に90%以上で稼働し続けており、搭載しているCPUのパワーを十分に活用できています。

このように、Ninjaを使うとCPUを効率的に利用したビルドが行えるようになるため、ビルド時間を大幅に短縮できるようになります。

Ninjaの導入方法


NinjaはApache-2.0 Licenseで公開されており、ビルド済みのバイナリファイルもGitHubで公開されています。

※外部サイト:Why GitHub?

利用しているプラットフォームによっても異なりますが、Windowsの場合は上記URLからWindows用のファイル(ninja-win.zip)をダウンロードし、zipファイルに含まれているninja.exeを任意のフォルダに展開します。

あとは、展開したフォルダにパスを通す(環境変数PATHに展開したフォルダを登録する)だけで利用できるようになります。

ninja.exeにパスが通っているかどうかは、コマンドラインから「 where ninja 」と入力すれば確認できます。きちんとパスが通っていれば、ninja.exeのパスが表示されます。また、「 ninja --version 」と入力すれば、Ninjaのバージョンを確認できます。

CMakeでNinja用のビルドファイルを作成する方法


Ninjaはmakeのようなビルドシステムの一種なので、makeのmakefileと同じように、Ninja用のビルドファイル(build.ninja)を作成する必要があります。構文は簡単なので、自分で作成するプロジェクトであれば、最初からbuild.ninjaを作成するのも良いでしょう。

しかし、一般的にオープンソースで公開してあるC/C++を使ったプロジェクトはCMakeが前提になっているケースが大半であり、Ninja用のビルドファイルは、ほぼ確実に用意されていません!

・・・途方に暮れてしまった方、ご安心ください!最近のCMakeは、CMake用の設定からNinja用のビルドファイルを自動で生成できるようになっています。つまり、CMake用に構成されているプロジェクトであれば、そのままNinjaが利用できることになります。

それでは、早速CMakeでNinja用のビルドファイルを作成する方法を見ていきましょう。 CMakeはCUI版(コンソール版)とGUI版が存在するので、CUI/GUIそれぞれでの使い方を紹介します。

まずは、見て分かりやすいGUI版からの説明です。
Ninjaを利用する場合は、下図の右側のように、CMake-GUIのGenerate時に利用環境を選択する部分で「Ninja」を選択します。(Ninjaではなく、Visual Studio 2019を使う場合は左側)

これだけで、Ninjaを使ったビルドが行えるようになります。簡単ですね。

cmake-setting_1119x505

続いて、CUI版(cmake.exe)での使い方です。CUIを利用する場合は、Generatorの指定を -G オプションで指定すればOKです。具体的には、次のようなコマンドになります。(比較のためにVisual Studio 2019を使う場合のコマンドも合わせて載せておきます)

下記コマンドの # から始まる行はコメントとして捉えてください。また の部分に、他のオプションやソースフォルダのパスを追加で指定してください。

        
        
      
Ninja_Command_CUI_904x157
        
        
      


余談ですが、CMakeのCUI/GUI版は次のような手順で、2つを組み合わせて使うと効率的に作業できて、おすすめです。普段GUI版しか使わない人は、是非CUI版も組み合わせて使ってみてくださいね。(特に設定項目が数百以上になる場合は便利)

1. 基本的な設定はCUI版でパラメータ指定
2. その後細かいパラメータの調整をGUI版で行う


Ninjaビルドファイルからのビルド方法


GeneratorにVisual Studio 2019を指定した場合は、ソリューションファイル(*.sln)が生成されるので、Visual Studioでソリューションファイルを直接開いてビルドする方も多いかもしれません。

しかし、GeneratorにNinjaを選択した場合は、Ninja用のビルドファイル(build.ninja)が生成されるだけなので、この先どうすれば良いか迷ってしまう人も多いかもしれません。

Ninjaの場合は、生成したbuild.ninjaと同じフォルダで以下のコマンドを実行すればビルドできます。(CMake-GUI版を使ってGenerateした場合も、最終的なビルドはコマンドプロンプトから実行する必要があります)

Ninja_Command_BuildFile_900x109

        
        
      
        
        
      

※要注意:コマンドプロンプトから操作する場合は、ninja.exeやビルドで利用するコンパイラの環境変数が正しく設定されている必要があるため「x64 Native Tools Command Prompt for VS 2019」経由などで開いたコンソール画面を利用すると良いでしょう。

最後に


今回はビルドを高速化する方法について紹介してきましたが、いかがでしたでしょうか。CMakeを使うケースであれば、そのままNinjaが使えるケースが大半ですので、ぜひお試しいただければと思います。
…そしてNinjaの魅力が分かると、よりコア数の多いCPUが欲しくなってしまいますよね!?

それでは、今回はこのあたりで、また次回のコラムでお会いしましょう。

リンク集


本記事で紹介してきたNinjaや、VTK、OpenCVのリンクを載せておきます。
※以下外部サイト
・Ninja
・Ninja(リリース版の公開先)
・CMake
・VTK OpenCV


当サイトの内容、テキスト、画像等の転載・転記・使用する場合は問い合わせよりご連絡下さい。

コラムの感想やリクエスト、セキュリティに関するお悩みも、問い合わせより受付中です!
問い合わせボタン_230x43


黒住 好忠

株式会社インフォメーション・ディベロプメント 先端技術部 エバンジェリスト

この執筆者の記事一覧

関連するナレッジ・コラム

【エバンジェリスト・ボイス】Pythonで実現!顔認識プログラムでWeb会議中の集中力が判明?

【エバンジェリスト・ボイス】動画活用のすすめ!在宅勤務でも伝わるコミュニケーション

【エバンジェリスト・ボイス】Blazorと、Microsoft Graphの巻