HPC/並列プログラミングポータルでは、HPC(High Performance Computing)プログラミングや並列プログラミングに関する情報を集積・発信しています。

新着トピックス

インテル コンパイラーでオープンソースソフトウェアをコンパイルしよう

 インテルの「インテル C++ コンパイラー」は高速なバイナリを生成するということで知られている。いっぽうWindowsの世界ではマイクロソフトのVisual C++が、LinuxではオープンソースのGCCが事実上標準のコンパイラになっており、多くのオープンソースソフトウェアはこれらのコンパイラでコンパイルされている。そのため、利用したいソフトウェアがインテル コンパイラーでコンパイルできるのか興味のある人も多いだろう。また、Visual C++やGCCでコンパイルされたものと比べ、どのくらいパフォーマンスが違うのかも気になるところだ。

 インテル C++ コンパイラーはVisual C++やGCCとの互換性を備えているものの、完全に同一というわけではない。そこで、有名なオープンソースソフトウェアについてインテル C++ コンパイラーでのコンパイルを行い、どの程度の修正でコンパイルが可能なのか、またそのパフォーマンスはどうなのか、調査してみよう。

 なお、今回の記事ではインテル C++コンパイラー 11.0の無償体験版を使用している。この体験版はインテル コンパイラーの国内代理店であるエクセルソフトのWebサイトからダウンロード可能だ。ぜひ読者の皆さんも手元でインテル コンパイラーを試してほしい。

オープンソースソフトウェアでも実績が多いインテル コンパイラー

 実際の作業を説明する前に、まずはインテル コンパイラーでのコンパイルを利用するにあたって役に立つであろう資料を紹介しておこう。

 まず、インテル コンパイラーのもっとも貴重な情報源となるのが、開発元であるインテルのWebサイトである。インテルのWebサイトでは、LinuxカーネルやSTLport、POV-rayなどのソフトウェアについて、インテル コンパイラーでのコンパイル方法を解説したドキュメントが公開されている(表1)。

 用意されているドキュメントは数値演算系や画像処理系のソフトウェア/ライブラリが多いが、これらはインテル コンパイラーが得意とする領域であり、高速化が期待できる。もしこれらのソフトウェア/ライブラリを利用しているなら、インテル コンパイラーを試してみる価値があるだろう。

表1 インテルのWebサイトで公開されているオープンソースソフトウェアのコンパイル解説ドキュメント
ソフトウェア説明
LinuxカーネルOS
PGPLOTプロット画像作成ライブラリ
NCARドロー画像ライブラリ
WRF気象モデリングシステム
HDF5クラスタライブラリ
UPC並列言語処理系
FFTW高速フーリエ変換ライブラリ
stlportC++標準ライブラリ
POV-Ray3D画像レンダラー
NetCDF科学用データフォーマットライブラリ
Open MPI並列化ライブラリ
HPCC bnechmarkベンチマークツール
ACE+TAO分散コンポーネント
XercesXML処理ライブラリ
Quantlib金融/財務処理ライブラリ

 また、ソフトウェアによってはVisual C++やGCCでコンパイルしたバイナリだけでなく、インテル コンパイラーでコンパイルしたバイナリも配布されている場合がある(表2)。このようなバイナリは有志がコンパイルして配布していることが多く、公式版と比べてパフォーマンスが高いものが多いようだ。ただし、公開されているバージョンが古い場合もあるので注意してほしい。

表2 インテル コンパイラーでコンパイルされたバイナリが配布されているソフトウェア例
ソフトウェア配布先/配布者
MySQL公式ダウンロードページ
BlenderWoogieWorks Animation Studio
FFTWFranz Franchetti
x264seraphyのプログラム公開所(「x264 詰め合わせ」の「おまけ」以下)
lameRAREWARES

 例えば、上記で配布されているBlenderのインテル コンパイラー版バイナリを使い、Core 2 Duo E6550(2.33GHz)を搭載したマシンでBlender Render Benchmarkで配布されているテストファイルをレンダリングしたところ、公式版よりも1.5倍程度高速であった(表3)。

表3 Blenderでテストファイル(test.blend)のレンダリングにかかった時間(3回の平均)
バイナリレンダリング時間
公式版(Visual C++ 2008 SP2)3:13:18
インテル コンパイラー版(SSE3対応)2:01:06

 また、「インテル コンパイラーの実力を測る――インテル コンパイラー版MySQLは本当に速いのか?」記事では、インテル コンパイラーによるMySQLの高速化についても調査しているので、そちらも参照してほしい。

インテル コンパイラーでコンパイルを行う際の注意点

 インテル コンパイラーでオープンソースソフトウェアをコンパイルする場合、基本的にはコンパイル設定ファイル(Visual Studioのプロジェクトファイル、もしくはMakefile)を書き換え、コンパイラとしてicl.exe(Windows版インテル コンパイラー)もしくはicc(Linux/Mac OS X版インテル コンパイラ-)を使用するように設定してやればよい。

Windows環境の場合

 Windows向けのオープンソースソフトウェアの場合、コンパイルにVisual Studioを使用するものと、makeコマンドを使用するものがある。Visual Studioを使用する場合、インテル コンパイラーに含まれるVisual Studio用プラグインを導入し、追加されるツールバーで「インテル C++を使用」ボタンをクリックすれば、自動的にコンパイルにインテル コンパイラーを使用する設定になる(図1)。また、プロジェクトの設定に「インテル固有」項目が追加されてインテル C++ コンパイラーのコンパイルオプションが設定できるようになるので、最適化の設定などはこちらで行う(図2)。

 コンパイルにmakeコマンド(GNU makefile、もしくはVisual C++に付属するnmake)を利用するソフトウェアの場合はmakefileを手動で編集する必要があるため、若干の手間が必要だ。といっても、基本的にはMakefileなどの「cl」もしくは「cl.exe」を「icl.exe」に変更するだけのパターンが多い。そのほか、設定にconfigureスクリプトを利用するものについては後述のLinux環境でのコンパイル設定と同様のやり方で設定が行える。ただし、インテル コンパイラーのコンパイルオプションはWindows版とLinux/Mac OS X版とで異なるので、その点には注意が必要だ。Windows版インテル コンパイラーはVisual C++との互換性があるため、基本的にはVisual C++でのコンパイルと同様の方法でコンパイルできることが多い。

Linux環境の場合

 Linux環境の場合、ほとんどのソフトウェアはconfigureスクリプトを使用してコンパイル設定を行う。configureスクリプトには使用するコンパイラなどを指定する機能があるので、それを使用して「icc」をコンパイラとして利用するよう指定すればよい。多くのconfigureスクリプトでは、下記のように「CC=icc CXX=icpc CFLAGS="<Cソースコードのコンパイルオプション>" CXXFLAGS="<C++ソースコードのコンパイルオプション>"」を追加してconfigureスクリプトを実行すれば良いだろう。

$ ./configure CC=icc CXX=icpc CFLAGS="-O2 -ip"" CXXFLAGS="-O2 -ip"

 なお、それぞれの環境で利用できる最適化オプションについては、エクセルソフトの製品紹介ページで公開されている「11.0 コンパイラー最適化ガイド」という資料が参考になる。この資料には、インテル コンパイラーを使用した最適化の手順や、利用できる最適化オプションがまとめられている。このなかでも、特にパフォーマンスの向上に有効と見られるオプションを表4にまとめた。ただし、これらのオプションを闇雲に指定すると、逆にパフォーマンスが悪化する場合もあるようだ。コンパイラー最適化ガイドによると、これらのコンパイルオプションを使用する場合まずはO2オプションを使用してコンパイルを行い、続いてO3やip、ipo、parallelなどを指定してパフォーマンスを比較するのが好ましいとのことだ。

表4 パフォーマンス向上に有効と見られるコンパイルオプション
オプション説明
WindowsLinux/Mac OS X
/O1、/O2、/O3-O1、-O2、-O3最適化レベルを指定する。O1がコードサイズ最小化、O2が標準的な最適化となる。O3はより複雑な最適化が実行される
/Qparallel-parallel自動並列化を実行する
/Qpar-threshold-par-threshold自動並列化を行うかどうか判断するしきい値を指定する。0を指定すると常に並列化が行われ、100を指定すると確実に有効な場合のみ並列化が行われる
/QxSSE3-xSSE3Core 2シリーズなどに搭載されているSSE 3命令を使用する。このオプションを指定して作成したバイナリは、SSE 3命令を備えたCPUでのみ実行可能となる
/Qip-ip単一オブジェクト内にある関数間での最適化を実行する
/Qipo-ipo複数のファイルに対して、オブジェクトのリンク時に関数/オブジェクト間での最適化を実行する

Linux版の場合

 Linux版の場合、公式に動作確認が行われているディストリビューションは次の7つである。

  • Asianux 3.0
  • Debian GNU/Linux 4.0
  • Fedora 9
  • Red Hat Enterprise Linux 3~5
  • SUSE LINUX Enterprise Server 9、10
  • TurboLinux 11
  • Ubuntu 8.04

 これ以外の環境ではインストール時に警告が表示されるので注意してほしい。なお、今回は検証用の環境としてDebian GNU/Linux 5.0を使用したが、特に問題は発生していないようだ。

 また、動作にはlibstdc++.so.5が必要である。たとえばDebian GNU/Linuxでは、次のようにしてlibstdc++.so.5をインストールできる。

# apt-get install libstdc++5

 なお、インテル C++ コンパイラーはデフォルトでは/opt/intel/Compiler/11.0/<リビジョン番号>/以下にインストールされる。そのため、コンパイルを行う前にはコンパイラ本体やライブラリがあるディレクトリにパスを通しておく必要がある。インストールディレクトリ内の「bin/」ディレクトリ以下にある「iccvars.sh」という環境設定用シェルスクリプトを読み込むことで必要な環境変数の設定が行われるので、コンパイルやconfigureスクリプトの実行前にこのシェルスクリプトを読み込んでおこう。ホームディレクトリにこのスクリプトのシンボリックリンクを作っておくと便利だ。

$ ln -s /opt/intel/Compiler/11.0/074/bin/iccvars.sh ~/
$ . ~/iccvars ia32

Linux環境でのコンパイル――bzip2

 まずは小手調べとして、さまざまなプラットフォームで動作するコマンドラインのファイル圧縮ツール「bzip2」をLinux版のインテル コンパイラーでコンパイルしてみよう。Windowsユーザーにはあまりなじみが無いかもしれないが、bzip2は主にUNIX/Linux環境で多く利用されている、高圧縮を誇る圧縮ツールである。記事執筆時点での最新版は2008年3月にリリースされている1.0.5だ。

 bzip2のソースコードは、Webサイトのダウンロードページからダウンロードできる。コンパイル方法はシンプルで、含まれるMakefileを環境に応じて編集し、makeを実行するだけである。今回編集する個所は下記のとおりだ。

CC=gcc
AR=ar
RANLIB=ranlib
LDFLAGS=

BIGFILES=-D_FILE_OFFSET_BITS=64
CFLAGS=-Wall -Winline -O2 -g $(BIGFILES)

を以下のように変更

CC=icc
AR=xiar
RANLIB=ranlib
LDFLAGS=

BIGFILES=-D_FILE_OFFSET_BITS=64
CFLAGS=-Wall -Winline <最適化オプション> $(BIGFILES)

 また、コンパイルオプションについては、表4のようにインテル コンパイラー(ICC)9通りと、GCC(-O2オプション)1通りの合計10通りを用意し、それぞれの設定でコンパイルしたバイナリのパフォーマンスの違いを計測する。

表4 比較に使用した最適化オプション
名称コンパイラ最適化オプション
icc:O1ICC-O1
icc:O2ICC-O2
icc:O3ICC-O3
icc:O2/ipICC-O2 -ip
icc:O3/ipICC-O3 -ip
icc:O2/ipoICC-O2 -ipo
icc:O3/ipoICC-O3 -ipo
icc:O3/ip/paraICC-O3 -ip -parallel -par-threshold90
icc:O3/ip/SSSE3ICC-O3 -ip -xSSSE3
gccgcc-O2

 なお、bzip2はWindows環境でもコンパイル可能だ。Window版インテル C++ コンパイラーでコンパイルする場合は、付属しているWindows環境向けのmakefile(makefile.msc)を下記のように修正し、これを「nmake -f makefile.msc」のようにVisual C++付属のnmakeコマンドの引数として指定すればよい。

CC=cl
CFLAGS= -DWIN32 -MD -Ox -D_FILE_OFFSET_BITS=64 -nologo

を以下のように変更

CC=icl
CFLAGS= -DWIN32 -MD <最適化オプション> -D_FILE_OFFSET_BITS=64 -nologo

実行結果を比較する

 パフォーマンスの比較には、Firefox 3.1b2のソースアーカイブ(firefox-3.1b2-source.tar.bz2、約40MB)を利用した。このファイルを展開するのにかかった時間と、展開したファイルを再度圧縮するのにかかった時間を3回測定し、その平均を結果としている。展開および圧縮は、次のようなコマンドラインオプションで実行した。なお、HDDアクセスのオーバーヘッドが結果に影響しないよう、出力先として/dev/nullデバイスを指定してファイルへの書き込みを行わないようにしている。

展開:
$ ./bzip2 -c -k -d firefox-3.1b2-source.tar.bz2  /dev/null

圧縮:
$ ./bzip2 -k -z --best firefox-3.1b2-source.tar  /dev/null

 また、テストに使用したPC環境は表5のようなCore 2 Duoマシンだ。

表5 ベンチマークテストに使用したPCのスペック
構成要素スペック
CPUCore 2 Duo E6550(2.33GHz)
OSDebian GNU/Linux 5.0
メモリ2GB
HDD(OS)Seagate Barracuda 7200.10(250GB)

 さて、それではベンチマーク結果を見てみよう。図4が圧縮にかかった時間、図5が展開にかかった時間をまとめたものだ。まず、圧縮の場合について見てみると、インテル コンパイラーでコンパイルしたものはGCCでコンパイルしたものに比べ、6割強の時間で作業が完了している。また、「-ip」オプションを付けてコンパイルしたものがもっとも速かったものの、コンパイルオプションを変えた場合でも実行時間には大幅な変化は見られなかった。

 また、圧縮ファイルを展開する作業については、インテル コンパイラーでコンパイルすることでGCCと比べ1割程度の高速化が可能だった。こちらの場合は、もっとも高速だったのは「-O2 -ipo」オプション付きでコンパイルしたバイナリであった。

Windows環境でのコンパイル――ImageMagick

 続いて、Windows環境でコンパイルできるオープンソースソフトウェアの例として、画像のバッチ処理ツール「ImageMagick」をコンパイルしてみよう。ImageMagickは画像のリサイズやフォーマット変換、結合など、さまざまな処理をバッチ処理できるコマンドラインツールだ。

 Windows環境でのImageMagickのコンパイルはInstall from Sourceページで解説されているが、まず設定ツールをビルドして実行することでVisual Studio用のプロジェクトファイルが作成され、次にそのプロジェクトファイルをVisual Studioで開いてビルドする、という手順となる。Windows向けの設定ツールはWindows向けソースパッケージにのみ含まれているので、こちらをダウンロードしよう。

 ZIPアーカイブを展開すると、「VisualMagick\configure」ディレクトリ以下に「configure.vcproj」というプロジェクトファイルが含まれているので、これをVisual Studioで開き、まずデフォルト設定のままでコンパイルを行う。すると、同じディレクトリ内に「configure.exe」という実行ファイルができるので、続けてこれを実行する。

 このconfigure.exeは、Windows環境向けのコンパイル設定ツールで、ウィザードに従って出力ディレクトリや共有ライブラリ/静的ライブラリのどちらを使うかなどを指定することで、Visual Studio用のプロジェクトファイルを生成できる(図6)。これで作成されたプロジェクトファイルをVisual Studioで開き、コンパイルオプションなどを設定後、プロジェクトのビルドを実行するとImageMagickがビルドされる。

 configure.exeでは共有ライブラリ(DLL)の使用/不使用や中間ファイルおよび出力ファイルの保存先などを指定できるが、今回はすべてデフォルトのまま、共有ライブラリを使用する設定を使用した。なお、出力されるプロジェクトファイルはVisual Studio 7(Visual Studio .NET)形式であるが、Visual Studio 2005/2008でも問題なく開くことができた。

 コンパイルオプションについては、表6のようにインテル コンパイラー(ICC)7通りと、Visual C++(VC++)1通りの合計8通りを用意し、それぞれの設定でコンパイルしたバイナリのパフォーマンスの違いを計測する。それ以外のコンパイルオプションについては、表7図7のように設定した。

表6 使用したコンパイルオプション
設定名コンパイラコンパイルオプション
ICC:O2ICC/O2
ICC:O2/ipICC/O2 /Qip
ICC:O2/ipoICC/O2 /Qipo
ICC:O3ICC/O3
ICC:O3/ipICC/O3 /Qip
ICC:O3/ipoICC/O3 /Qipo
ICC:O3/parallelICC/O3 /Qparallel /Qpar-threshold:90
ICC:O3/SSSE3ICC/O3 /QxSSSE3
VC++VC++/O2
表7 そのほかのコンパイルオプション設定(抜粋)
設定項目設定値
グローバルな最適化はい(/Og)
Windowsアプリケーションの最適化はい(/GA)
インライン関数の展開拡張可能な関数すべて(/Ob2)
組み込み関数を使用するはい(/Oi)
フレームポインターなしはい(/Oy)

実行結果

 ImageMagickには画像形式の変換や加工を行う「convert」や比較を行う「compare」、合成を行う「composite」などのコマンドが含まれているが、今回のベンチマークテストではこのうちconvertコマンドを使った3つの操作を行い、それぞれの処理にかかった時間を測定した(表8)。なお、ファイルアクセスによるオーバーヘッドが実行時間に影響しないよう、出力ファイルには「nul」を指定して実際のファイル出力は行わないようにしている。使用したPCの環境は表9のとおりだ。

表8 ベンチマークの詳細
処理名処理の内容実行するコマンドライン
resize4000×3000のJPEG画像を8000×6000に拡大convert.exe -resize 8000x6000 sample.JPG nul
blur4000×3000のJPEG画像に半径100のぼかしフィルタを適用するconvert.exe -blur 100 sample.JPG nul
monochrome4000×3000のJPEG画像をモノクロ化するconvert.exe -monochrome sample.JPG nul
表9 ベンチマークテストに使用したPCのスペック
構成要素スペック
CPUCore 2 Duo E6550(2.33GHz)
OSWindows Vista Business SP1
メモリ2GB
HDD(OS)Seagate Barracuda 7200.10(250GB)

 以上の3つの処理を、8種類のバイナリに対して3回ずつ行い、その実行時間の平均を取ったものを今回のベンチマーク結果とした。それぞれの結果をまとめたものが図8~10である。

 どのテストでももっとも高速だったのはインテル コンパイラーを使ってコンパイルしたものだったが、特に興味深いのはblur処理の結果であろう。blur処理の場合、自動並列化をオンにしてコンパイルしたバイナリはVisual C++でコンパイルしたバイナリよりも高速だったものの、並列化を利用しなかった場合はインテル コンパイラーでコンパイルしたバイナリのほうが遅くなる、という結果になってしまった。

 実はこのパフォーマンス低下はCPUのキャッシュミスが原因なのであるが、このようなソフトウェアのパフォーマンスなどに関わる問題はその原因がどこにあるか、またなぜ問題が発生しているのかを突き止めることが非常に難しい。このImageMagickでの問題の分析とパフォーマンス改善については『パフォーマンス解析ツール「VTune」でアプリケーションを高速化』で紹介しているので、詳細はこちらの記事を参照していただsきたい。

さまざまなソフトウェアで高速化の恩恵が期待できる

 インテル コンパイラーは科学技術計算や統計処理などの分野での採用例が多いため、一般的なアプリケーションでの効果を疑問視する方もいるのでは無いだろうか。しかし、今回試したbzip2やImageMagickなど、一般的なアプリケーションであってもインテル コンパイラーの効果を確認することができた。また、コンパイルの際は大規模なソフトウェアでは多少の修正が必要だったり、設定にコツがあったりするものの、おおむねGCCやVisual C++との互換性は高い。

 特にI/OよりもCPUのボトルネックがパフォーマンスに効いてくる暗号化や圧縮/展開、画像/動画/音声処理などについては、十分にインテル コンパイラーを利用するメリットがあるのではないだろうか。