インテル® Xeon Phi™ コプロセッサー向けネイティブ・アプリケーションのビルド
この記事は、インテル® デベロッパー・ゾーンに掲載されている「Building a Native Application for Intel® Xeon Phi™ Coprocessors」の日本語参考訳です。
はじめに
アプリケーションによっては、ホストシステムからオフロードせずに、直接インテル® Xeon Phi™ コプロセッサー上で実行するほうが適している場合があります。これは、「ネイティブモード」実行 (ネイティブ実行) と呼ばれます。この記事では、インテル® Xeon Phi™ コプロセッサーの Linux* システム上で直接実行するネイティブ・アプリケーションのビルド方法について説明します。手順は以下のとおりです。
- アプリケーションがネイティブ実行に適しているかどうかを判断します。
- ネイティブ実行用にアプリケーションをコンパイルします。
- ネイティブ実行用に必要なライブラリーをビルドします。
- ランタイム・ライブラリーなどの実行ファイルや依存ファイルをターゲット・ハードウェアへコピーします。
- 入力データにアクセスしたり、出力データを保存するため、ファイルをターゲット・ハードウェアへマウントします。
- コンソール経由でターゲット・ハードウェアへ接続し、環境を設定してアプリケーションを実行します。
- ターゲット上のデバッグサーバーを利用して、ネイティブデバッガーからネイティブ・アプリケーションを起動しデバッグします。
基本的な Linux* サービスの使用方法についてはこの記事では説明していません。また、ここで紹介する一部のコマンドではルート権限が必要です。
ここでは、インテル® Composer XE 2013 Update 2 を使って説明しています。インテル® コンパイラーを購入済みの方 (製品を登録済みの方) は、インテル® ソフトウェア開発製品レジストレーション・センターから最新版をご利用になれます。インテル® コンパイラーの評価版は、インテル® Software Evaluation Center からダウンロードできます。
インテル® Xeon Phi™ コプロセッサーへの “root” 以外の SSH アクセス、SCP アクセスにはスーパーユーザー権限が必要です (詳細はここでは説明していません)。
ネイティブ実行の適性
ネイティブ実行とは、アプリケーション全体がインテル® Xeon Phi™ コプロセッサー上で実行される状態です。ネイティブ・アプリケーションのビルドは、最小限のコード変更で既存のソフトウェアを実行できる簡単な方法です。最初に、アプリケーションがネイティブ実行に適していることを確認してください。データ並列性、並列アルゴリズムの利用、アプリケーションのスケーラビリティーは、インテル® Xeon Phi™ コプロセッサーをターゲットにする条件ですが、オフロードかネイティブモードかを判断する条件ではありません。次の特性を持つアプリケーションは、多くのコア数を利用できるネイティブ実行のメリットが得られるでしょう。
- 物理メモリーより少ない、適度な量のメモリーを使用
- シリアル実行部分が非常に少ない
- 拡張 I/O を実行しない
- 大きなデータ転送のオーバーヘッドを伴わずにオフロードできる、ホットなカーネル領域のないコード構造
オフロードモードで優れたパフォーマンスを実現するには、さらなる最適化 (特にベクトル化) が必要です。
ネイティブ・アプリケーションのコンパイル
インテル® C++ コンパイラーおよびインテル® Fortran コンパイラーは、インテル® Xeon Phi™ コプロセッサー向けのクロスコンパイルをサポートしています。–mmic コンパイラー・オプションはクロスコンパイルを行い、インテル® Xeon Phi™ コプロセッサー上でのみ実行されるオブジェクト・ファイル (デフォルト: a.out) を生成します。次の手順に従って、ネイティブ実行用にアプリケーションをコンパイルします。
1. インテル® コンパイラーが適切に動作するには、環境変数の設定が必要です。まず、セットアップ・スクリプトを実行して、Linux* ランタイム環境を設定します。C シェルには compilervars.csh ファイル、bash シェルには compilervars.sh ファイルを使用してください。次の例は、デフォルトのインストール場所にある compilervars.sh スクリプトを実行しています (bash シェル)。
$ source /opt/intel/composer_xe_2013/bin/compilervars.sh intel64
2. icc –V (C コンパイラー)、icpc –V (C++ コンパイラー)、または ifort –V (Fortran コンパイラー) を実行して、環境変数が適切に設定されていることを確認します。
$ icc –V インテル(R) 64 C コンパイラー XE (インテル(R) 64 対応アプリケーション用)、バージョン 13.1.0.146 ビルド 20130121 (C) 1985-2013 Intel Corporation. 無断での引用、転載を禁じます。
3. –mmic オプションを指定してビルドします。
$ icc –mmic mycode.c (C ソースの場合) $ icpc –mmic mycode.cpp (C++ ソースの場合) $ ifort –mmic mycode.f90 (Fortran ソースの場合)
注: –O 最適化レベルオプションが指定されていない場合のデフォルトの最適化レベルは –O2 です。 コンパイラー・オプションの詳細については、/opt/intel/composer_xe_2013/Documentation/ja_JP/ 以下にある『インテル® コンパイラー XE 13.0 ユーザー・リファレンス・ガイド』を参照してください。
ライブラリーのビルド
インテル® Xeon Phi™ コプロセッサー上でネイティブ実行するコードをビルドする場合、ネイティブ実行用にライブラリーをビルドしてから、アプリケーションをビルドする際にそのライブラリーをリンクしなければいけないことがあるでしょう。Linux* 共有ライブラリーおよびスタティック・ライブラリーは標準的な方法で作成できますが、–mmic オプションを指定してインテル® Xeon Phi™ コプロセッサー向けにバイナリーを生成します。
共有ライブラリー
インテル® コンパイラーで、ネイティブ実行用に Linux* 共有オブジェクトを作成する方法を次に示します。
1. ライブラリーのソースコードをコンパイルします。デフォルトで mylib.o が作成されます。
$ icc -mmic -c -fpic mylib.c $ icpc –mmic –c –fpic mylib.cpp $ ifort –mmic –c –fpic mylib.f90
2. -shared オプションを指定して、オブジェクト・ファイルからライブラリー・ファイルを作成します。(ここでも –mmic オプションが必要であることを覚えておいてください。)
$ icc -mmic -shared -o libmylib.so mylib.o $ icpc –mmic –shared –o libmylib.so mylib.o $ ifort -mmic -shared -o libmylib.so mylib.o
3. ネイティブ・アプリケーションとネイティブ共有オブジェクトをコンパイルおよびリンクします。(ここでも –mmic オプションが必要であることを覚えておいてください。)
$ icc -mmic main.c libmylib.so $ icpc –mmic main.cpp libmylib.so $ ifort -mmic main.f90 libmylib.so
ネイティブ・アプリケーションと共有オブジェクトに加えて、コンパイラーのランタイムシステムで必要な共有オブジェクトもコプロセッサーへ転送する必要があります。それらのファイルは、デフォルトでは /opt/intel/composer_xe_2013.2.146/compiler/lib/mic/ 以下にインストールされます。通常、ネイティブ・アプリケーションには次のライブラリーが必要です。アプリケーションの必須要件によって、その他の共有ライブラリーも必要になることがあります。
ライブラリー | 説明: |
libcilkrts.so.5 | インテル® Cilk™ Plus ランタイム・ライブラリー |
libifcoremt.so.5 | スレッドセーフなインテル固有の Fortran ランタイム・ライブラリー |
libifport.so.5 | 移植性、POSIX* サポート・ライブラリー |
libimf.so | 算術ライブラリー |
libintlc.so.5 | CPU ディスパッチ、intel_fast_*、traceback サポートルーチン用のインテルのサポート・ライブラリー |
libiomp5.so | 互換性のある OpenMP* ダイナミック・ランタイム・ライブラリー |
libsvml.so | SVML (Short Vector Mathematical Library) |
libirng.so | 乱数ジェネレーター・ライブラリー |
libmpi.so.4.0, libmpigf.so.4.0, libmpigc4.so.4.0 |
インテル® MPI ランタイム・ライブラリー |
アップロードする必要があるインテルのランタイム・オブジェクトを確認するには、次のコマンドを実行します。
$ readelf -d libmylib.so | grep -i NEED 0x0000000000000001 (NEEDED) Shared library: [libimf.so] 0x0000000000000001 (NEEDED) Shared library: [libsvml.so] 0x0000000000000001 (NEEDED) Shared library: [libirng.so] 0x0000000000000001 (NEEDED) Shared library: [libm.so.6] 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libintlc.so.5] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x0000000000000001 (NEEDED) Shared library: [libdl.so.2] 0x000000006ffffffe (VERNEED) 0x3a8 0x000000006fffffff (VERNEEDNUM) 1
上記のリストには、GNU C ライブラリー、GLIBC、そして、libm.so、libstdc++.so、libgcc_s.so、libpthread.so、libc.so、libdl.so を含むランタイム・ライブラリーが含まれます。GLIBC ライブラリーはコプロセッサーにあるので、アップロードする必要はありません。
スタティック・ライブラリー
開発者は xiar を使って、ネイティブ・スタティック・ライブラリーを作成することができます。
スタティック・ライブラリーをビルドする手順を次に示します。
1. ライブラリーのソースコードをコンパイルします。デフォルトで mylib.o が生成されます。
$ icc -mmic -c mylib.c $ icpc –mmic –c mylib.cpp $ ifort –mmic –c mylib.f90
2. xiar ユーティリティーを使って、オブジェクト・ファイルからライブラリー・ファイルを作成します。
$ xiar crs libmylib.a mylib.o
3. ネイティブ・アプリケーションとネイティブ・スタティック・ライブラリーをコンパイルおよびリンクします。
$ icc -mmic main.c libmylib.a $ icpc –mmic main.cpp libmylib.a $ ifort -mmic main.f90 libmylib.a
ファイルの転送
インテル® Xeon Phi™ コプロセッサー上で動作する Linux* オペレーティング・システムは、標準のネットワーク・ツールによってホストとの通信をサポートします。インテル® Xeon Phi™ コプロセッサー上でアプリケーションを直接実行するには、SSH および SCP を使ってアプリケーションと依存ファイルを転送します。
デフォルトでは、ドライバーのインストール時に、各インテル® Xeon Phi™ コプロセッサーごとにネットワーク・インターフェイスとエイリアスが設定されます。例えば、デフォルトの設定では “mic0” という名前が最初のカードに、“mic1” が 2 番目のカードに、というように割り当てられます。
システムの最初のカード、mic0 へファイルを転送する方法を次に示します。
1. ssh を使ってカードに接続し、/tmp ディレクトリー以下にフォルダーを作成します。
$ ssh mic0 ‘mkdir /tmp/myname'
2. 依存ファイル (OpenMP* やインテル® Cilk™ SDK ランタイム・ライブラリーなど) とカスタム共有オブジェクトをそのフォルダーにコピーします。
$ scp ./a.out mic0:/tmp/myname $ scp /opt/intel/composer_xe_2013.2.146/compiler/lib/mic/libiomp5.so mic0:/tmp/myname
インテル® Xeon Phi™ コプロセッサーへのアクセスに必要な IP アドレスは、プライベート・ネットワーク内でデフォルト値にプリセットされます。
入出力の処理
インテル® Xeon Phi™ コプロセッサー上のローカル・ファイル・システムは、GDDR5 メモリーの RAM ディスクです。つまり、ローカル・ファイル・システムにファイルを保存すると、ネイティブ・アプリケーションからメモリーを奪うことになります。大きなデータの入出力を適切に処理する方法は、ホストのファイルシステムのフォルダーをコプロセッサーにマウントして、そのデータにアクセスすることです。Linux* NFS (Network File System) 経由でホストからエクスポートしたフォルダーをマウントするには、スーパーユーザー権限が必要です。次の例では、/mydir からシステムの 1 番目のコプロセッサーへアクセスできます。
1. エクスポートするホストのディレクトリーを作成するか選択します。そのディレクトリーに読み取り権と書き込み権を設定します。
$ chmod –R 777 /mydir
2. ホスト上の /etc/exports ファイルに、カード 0 への /mydir のエクスポート許可を追加します。/etc/exports ファイルに次の行を追加します。
/mydir 172.31.1.1/24(rw,no_root_squash)
3. ホスト上の /etc/hosts.allow ファイルに、カード 0 のホストへのアクセス権を設定します。/etc/hosts.allow ファイルに次の行を追加します。
ALL: 172.31.1.1
4. ホストで exportfs を実行して、ファイルの変更を反映します。
$ /usr/sbin/exportfs -a –vexporting 172.31.1.1/24:/mydir
5. ホストの NFS サービスを再起動します。
$ chkconfig nfs on $ service nfs restart
6. ssh 経由でコプロセッサーにログインし、エクスポートされるファイルシステムを認識するため、vi で /etc/fstab ファイルを編集します。次の行を /etc/fstab ファイルに追加します。
host:/mydir /mydir nfs rsize=8192,wsize=8192,nolock,intr 0 0
7. カード 0 で /mydir ディレクトリーを作成し、mount コマンドを実行します。
# mkdir /mydir # mount –a
8. カード 0 でフォルダーが利用可能なことを確認します。
# df –h Filesystem Size Used Available Use% Mounted on tmpfs 3.8G 0 3.8G 0% /dev/shm host:/mydir 217.4G 25.2G 181.2G 12% /mydir
アプリケーションの実行
ネイティブ・アプリケーションを実行するには、次の 2 つの方法があります。
- アプリケーションと依存ファイルを手動でコプロセッサーにコピーし、ログインしてからプログラムを起動します。
- micnativeloadex ユーティリティーを使って自動で依存ファイルをコピーし、コプロセッサー上でプログラムを実行します。
アプリケーションの手動実行
アプリケーションと依存ファイルをコプロセッサーにコピーした後、コンソール経由でカードに直接ログインし、必要な環境変数を設定してからアプリケーションを実行します。ssh を使ってログインすることができます。次の手順に従って、システムの 1 番目のコプロセッサー (カード 0) へ接続します。
1. コンソールから ssh 経由で mic0 に接続します。
$ ssh mic0 # ls / bin etc lib linuxrc proc sbin tmp var dev home lib64 oldroot root sys usr #
2. ネイティブ・アプリケーションのあるディレクトリーに移動します。
# cd /tmp/myname
3. ファイルの実行権とランタイム環境を設定します。
# chmod +x * # export LD_LIBRARY_PATH=/tmp/myname:$LD_LIBRARY_PATH
4. アプリケーションを実行します。
# ./a.out
micnativeloadex の使用
micnativeloadex ユーティリティーは、ネイティブ・バイナリー・ファイルとライブラリー依存ファイルをコプロセッサーへコピーして実行します。このユーティリティーは、SINK_LD_LIBRARY_PATH 環境変数に定義されたパスを使って依存ファイルを検索します。デフォルトでは、micnativeloadex はコプロセッサーで実行するアプリケーションからの出力結果をローカルコンソールに表示します。
1. コンソールから、SINK_LD_LIBRARY_PATH をインテル® コンパイラーのランタイム・ライブラリーの場所に設定します。
$ export SINK_LD_LIBRARY_PATH=/opt/intel/composer_xe_2013.2.146/compiler/lib/mic/
2. アプリケーションを実行します。
$ /opt/intel/mic/bin/micnativeloadex a.out
デバッグ
インテル® デバッガーは、インテル® Xeon Phi™ コプロセッサー上でネイティブに実行するアプリケーション向けにコマンドライン・デバッグをサポートしています。デバッグプロセスは、コプロセッサー上でネイティブ・アプリケーションを実行するのに似ています。
- –g オプションを指定してネイティブ・アプリケーションのデバッグビルドをコンパイルします。
- デバッグビルドをコプロセッサーにアップロードします。
- デバッグホストでターゲットデバッガーを起動し、カードに接続してアプリケーションのデバッグを開始します。デバッグ通信を行うデバッグ・エージェントはコプロセッサーへ自動でダウンロードされます。あるいは、インテル® デバッガーから直接ネイティブ・アプリケーションを起動することもできます。
このデバッグ方法の詳細については、「コマンドラインでのインテル® MIC アーキテクチャー向けアプリケーションのデバッグ」(英語) を参照してください。
GDB* (ネイティブのみ) デバッガープレビューのインストール・ファイルは、http://software.intel.com/en-us/forums/showthread.php?t=105443 からダウンロードできます。
簡単なサンプル
http://software.intel.com/sites/default/files/cube_charge.tar から cube_charge.tar というサンプルをダウンロードして展開します。
このサンプル・アプリケーションは、データファイルから読み込まれる一連の空間ポイントを繋いだ立方体の一様電荷分布を基に、静電ポテンシャルを計算する 3 次元積分を実行します。マクロ NP を使用して、計算するデータポイントの数を指定します。
サンプルのプロジェクト・ディレクトリーに移動します。
1. 端末を開いて、コンパイラーの環境変数を設定します。
$ source /opt/intel/composer_xe_2013/bin/compilervars.sh intel64
2. 環境変数が設定されていることを確認します。
$ ifort -V インテル(R) 64 Fortran コンパイラー XE (インテル(R) 64 対応アプリケーション用)、バージョン 13.1.0.146 ビルド 20120121(C) 1985-2013 Intel Corporation. 無断での引用、転載を禁じます。
3. サンプルをビルドします。–mmic と –openmp オプションを指定していることに注意してください。
$ ifort -DNP=120 -mmic -openmp -openmp-report1 -ipo -vec-report1 -fpp cube_charge.f90 threed_int.f90 twod_int.f90 trap_int.f90 func.f90
出力は次のようになります。
ipo: リマーク #11000: 複数ファイル最適化を実行しています。 ipo: リマーク #11006: オブジェクト・ファイル /tmp/ipo_ifortqS9Myh.o を生成しています。 cube_charge.f90(118): (col. 7) リマーク: OpenMP 定義ループが並列化されました。 cube_charge.f90(110): (col. 7) リマーク: OpenMP 定義領域が並列化されました。 trap_int.f90(35): (col. 22) リマーク: ループがベクトル化されました。
4. ホストからコプロセッサーへプログラムと依存ファイルを転送します。
$ ssh mic0 ‘mkdir /tmp/myname’ $ scp ./a.out mic0:/tmp/myname $ scp /opt/intel/composer_xe_2013.2.146/compiler/lib/mic/libiomp5.so mic0:/tmp/myname
5. SSH を使ってコプロセッサーへ接続します。ファイルが実行可能なことを確認し、環境変数を設定して、ファイルを実行します。
# export LD_LIBRARY_PATH=/tmp/myname:$LD_LIBRARY_PATH # ./a.out
6. 上記の 4 と 5 を行う代わりに、前述した micnativeloadex ユーティリティーを使ってホストからコプロセッサーへ依存ファイルを転送および実行することもできます。
$ export SINK_LD_LIBRARY_PATH=/opt/intel/composer_xe_2013.1.117/compiler/lib/mic/ $ /opt/intel/mic/bin/micnativeloadex a.out
著者紹介
Amanda Sharp は、ソフトウェアの最適化に取り組むインテル® コンパイラー・チームのテクニカル・コンサルティング・エンジニアです。HPC (ハイパフォーマンス・コンピューティング) ソフトウェア開発者のテクニカルサポートとトレーニングを担当しています。Amanda はポートランド州立大学でコンピューター・サイエンスの学士号を取得しています。
関連情報
- インテル® C++ コンパイラー XE 2013 Linux* 版ユーザー・リファレンス・ガイド
- インテル® Fortran コンパイラー XE 2013 Linux* 版ユーザー・リファレンス・ガイド
- インテル® Xeon Phi™ コプロセッサーでのデバッグ: 使用例
著作権と商標について
本資料に掲載されている情報は、インテル製品の概要説明を目的としたものです。本資料は、明示されているか否かにかかわらず、また禁反言によるとよらずにかかわらず、いかなる知的財産権のライセンスも許諾するものではありません。製品に付属の売買契約書『Intel’s Terms and Conditions of Sale』に規定されている場合を除き、インテルはいかなる責任を負うものではなく、またインテル製品の販売や使用に関する明示または黙示の保証 (特定目的への適合性、商品適格性、あらゆる特許権、著作権、その他知的財産権の非侵害性への保証を含む) に関してもいかなる責任も負いません。
インテルによる書面での合意がない限り、インテル製品は、その欠陥や故障によって人身事故が発生するようなアプリケーションでの使用を想定した設計は行われていません。
インテル製品は、予告なく仕様や説明が変更される場合があります。機能または命令の一覧で「留保」または「未定義」と記されているものがありますが、その「機能が存在しない」あるいは「性質が留保付である」という状態を設計の前提にしないでください。これらの項目は、インテルが将来のために留保しているものです。インテルが将来これらの項目を定義したことにより、衝突が生じたり互換性が失われたりしても、インテルは一切責任を負いません。この情報は予告なく変更されることがあります。この情報だけに基づいて設計を最終的なものとしないでください。
本資料で説明されている製品には、エラッタと呼ばれる設計上の不具合が含まれている可能性があり、公表されている仕様とは異なる動作をする場合があります。現在確認済みのエラッタについては、インテルまでお問い合わせください。
最新の仕様をご希望の場合や製品をご注文の場合は、お近くのインテルの営業所または販売代理店にお問い合わせください。
本資料で紹介されている資料番号付きのドキュメントや、インテルのその他の資料を入手するには、1-800-548-4725 (アメリカ合衆国) までご連絡いただくか、インテルの Web サイトを参照してください。
Intel、インテル、Intel ロゴは、アメリカ合衆国およびその他の国における Intel Corporation の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。
© 2012 Intel Corporation.無断での引用、転載を禁じます。
コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。