目次


Linux on x86 から Linux on Power へのアプリケーション移植ガイド

Comments

はじめに

ほとんどの場合、Linux アプリケーションを x86 プラットフォームから Linux on Power に移植するのは、難しい作業ではありません。それは、これらのプラットフォームがベースとする Novell SUSE Linux または Red Hat Linux のバージョンは、共通しているためです。コンパイラー/リンカー・スイッチにマイナーな変更を加え、GCC (GNU Compiler Collection) で再コンパイルするだけで、移植が完了することも珍しくありません。

しかしながら、移植を成功させるには、不意に出現する未知の問題に対処できるよう備えておくことが、重要な強みになります。まずは移植にフォーカスし、移植が完了してから最適化にフォーカスを移すのであれば、この記事で紹介するガイドライン、手法、そしてツールによって、通常は、Linux on Power へ移植するのに伴う難題を完全に排除するとまではいかなくても、大幅に削減することができます。

場合によっては、アプリケーションが x86 などの特定のハードウェア・アーキテクチャー専用に設計されていて、追加の変更が必要になることもあります。この記事では、x86 システム上で Linux アプリケーションを実行する場合と、IBM POWER プロセッサー・ベースのシステムへ移植して実行する場合の違いを明らかにして、x86 コードを Linux on Power に移植できる状態にするためのアドバイスを提供します。具体的には、以下の違いに焦点を当てます。

  • アプリケーションのエンディアン方式 (バイト・オーダー)
  • 32 ビットと64 ビットのデータ型 (長さとアライメント)
  • 選択可能なコンパイラーのオプション ― GCC (ディストリビューションおよび Advance Toolchain) と IBM XL C/C++ コンパイラー
  • IBM SDK for Linux および IBM Rational Developer for Power Systems の使用 ― GNU C/C++ コンパイラーを使用した、サイズの大きいプログラムのビルド

Power Linux では、アプリケーション開発者が、高度なツールとテクノロジーを利用することができます。その一例は、IBM SDK (Software Development Kit) for PowerLinux という、無料で利用できる Eclipse ベースの統合開発環境 (IDE) です。この SDK によって、Advance Toolchain、ポストリンク最適化ツール、従来の Linux パフォーマンス分析ツール (OProfile、Perf、Valgrind など) が、C/C++ ソース開発環境に統合されます。

移植に向けたプランニング

アプリケーションを新しいプラットフォームに移植する場合には、適切なプランニングが不可欠です。移植に向けて十分に準備をするには、以下の作業を行ってください。

  1. 型の不一致が検出される可能性がある代入演算、ビット操作、ビット比較に特に注意しながら、コード全体に目を通します。
  2. IBM Power プラットフォーム・アーキテクチャーの特徴と併せ、x86 プロセッサーと IBM POWER プロセッサーのアーキテクチャーの違い (特に、アプリケーションのエンディアン方式) を理解します。
  3. 使用する Linux on Power ディストリビューションを決めます。Red Hat Enterprise Linux、Novell SUSE Linux、CentOS、Ubuntu という選択肢があります。
  4. GNU Make ビルド・システムの使用を検討します。
  5. 使用するコンパイラーを決定します。GCC、IBM XL C/C++ for Linux という選択肢があります。
  6. 開発用の IBM Power サーバーを入手します。選択肢は、いくつかあります。
  7. 以下のプログラムを調べ、移植作業を迅速化して移植の成功に役立てるプログラムがあるかどうかを判断します。

Power Development Cloud
完全に自動化された IBM Power Development Cloud は、IBM プラットフォームでのソフトウェア・ソリューションの開発およびデモンストレーションに使用できる、無償の PaaS (Platform as a Service) です。x86 から Linux on Power に移行することを目的として事前に構成されてインストールされた開発ツールを備えた IBM Linux on Power 開発スタックを利用することができます。

IBM Hardware Mall ― リースおよび割引
Hardware Mall は、独立系ソフトウェア・ベンダー (ISV) に対し、IBM プラットフォームでのソフトウェア・ソリューションの開発を奨励する目的で、Systems のハードウェアおよび Systems に適用可能なソフトウェアの大幅な購入割引や手頃なリース料金を設定しています。

IBM Systems Application Advantage for Linux (Chiphopper)
IBM Chiphopper オファリングは、アプリケーションを移植または再ホストするためのプログラムです。このオファリングの目的は、IBM ビジネス・パートナーが、競合他社のプラットフォームで実行されている既存の Linux アプリケーションを、Linux およびミドルウェア・プラットフォームを実行する IBM Power Systems に移行して実行、テスト、サポートできるようにすることです。しかも、これは無償のオファリングとなっています。

IBM イノベーション・センター
IBM イノベーション・センターでは、ソリューションの構築から、マーケティング、販売に至るまで、それぞれに関するトレーニングと 1 対 1 のガイダンスを提供しています。また IBM イノベーション・センター・チームによって、それぞれの開発目標に合わせた支援が用意されています。

Web サイト「Hardware for solution development」では、以上のサービスを調べて利用することができます。

Power プラットフォームの違いを理解する

移植先の Power ハードウェア・プラットフォームによって、アプリケーションをコンパイルするときに使用する最適化オプションが決まるので、どのプロセッサー・バージョン (例えば、IBM POWER5、IBM POWER6、IBM POWER7、または IBM POWER8) がベースであるかを考慮する必要があります。移植後の作業が容易になるのは、POWER プロセッサー・ベースのシステム全般に適用可能なコードを開発しておくことです。このようにすれば、作成されるアプリケーションは、これらのどのシステムにおいても正常に実行されるようになります。ターゲットとするアプリケーションのベースを、最初は IBM の比較的新しい POWER 世代にしておくのも、同じく移植後の作業を容易にする方法です。ここで重要な選択となるのは、GCC コンパイラーと XL C/C++ コンパイラーのどちらを使用するかです。詳細については、この記事で追って説明します。

コンパイラー:

ここ何年かの間に、GCC テクノロジーは飛躍的に改善され、IBM POWER7 および IBM POWER8 プロセッサー・ベースのサーバーに合わせて調整されたアプリケーションを提供できるようになっています。しかも、パフォーマンスが究極的な目標である場合、IBM XL コンパイラーでは、さらにパフォーマンスを向上させることも可能です。

  • Linux on x86 で GCC を使用している場合は、GCC を使用して初期移植を行うことをおすすめします。Linux on Power での GCC テクノロジーは大幅に改善されています。GCC について十分に理解していれば、GCC をベースとして簡単に移植を開始することができます。
  • 必要に応じて、IBM XL C/C++ コンパイラーも利用できます。
  • Linux on x86 で Java を使用している場合は、IBM Web サイトから、該当する IBM Java ツールキットをダウンロードして使用することをおすすめします。

Power Systems での仮想化について詳しくは、「Linux on Power: An overview for developers」(developerWorks、2011年 7月更新) を読むか、Power Systems とのサーバー統合の可能性に関するエグゼクティブ・ブリーフィングを参照してください。

コンパイラー・フラグ:

移植先が POWER プロセッサー・ベースのサーバーの場合、アプリケーションを最適化するために XL C/C++ コンパイラーでは -qarch-qtune を、GCC コンパイラーでは -mcpu-mtune というフラグを指定することができます。ただし、初期移植での難題を最小限に抑える上で一番望ましいのは、最も一般的に使われている Power ベースのフラグである、-qtune=ppc-mcpu=power を指定することです。具体的なフラグと、どのような場合にそれぞれのフラグを使用するかについては、この記事で追って説明します。

使用する Linux on Power ディストリビューションを決定する

(この記事が公開される時点での) Novell と Red Hat の最新オペレーティング・システム・オファリングには、エンタープライズ・レベルのデプロイメントに必要なテクノロジー、サポート、信頼性が備わっています。多くの場合、以下のどちらのオファリングを選択するかは、企業や組織の内部での検討事項となります。

  • SLES (SUSE Linux Enterprise Server)。SLES の詳細については、「参考文献」セクションを参照してください。
  • RHEL (Red Hat Enterprise Linux)。RHEL または CentOS の詳細については、「参考文献」セクションを参照してください。

SLES と RHEL のどちらを使用するかの決定は、移植プロセスに直接影響を与えません。ただし、SUSE と Red Hat のリリース・サイクルと更新サイクルは異なり、バイナリー互換性に関するポリシーも異なるため、長い目でみると、これらの違いによって、アプリケーションの更新についての決定に影響が及ぶ可能性があることに注意してください。しかも、Red Hat と SUSE のディストリビューションは、同じスケジュールで Intel および Power サポートを同時リリースします。

GNU Make へ移行する

現在、アプリケーションのビルドに GNU Make を使用していないとしたら、GNU Make に移行することを検討してください。プログラミングのプラクティスとして望ましいのは、コンパイラーを直接呼び出したり、スクリプトを使用したりして実行可能ファイルを生成するのではなく、実行可能ファイルの生成を制御するツールを利用することです。そのようなツールとして、ほとんどの C および C++ プログラマーは、Make を使用しています。GNU Make に切り替えると、複数のプラットフォーム全体で makefile という共通のビルド制御ファイルを使用して、ビルドの操作に一貫性を持たせることができます。GNU Make は、SLES11 と RHEL6 の両方で配布されます。GNU Make の詳細については、「参考文献」セクションを参照してください。

Linux on x86 アプリケーションが GCC でビルドされている場合は、単純な手法として、Power での再コンパイルには、最初に GCC を使用することをおすすめします。その後のステップで、考慮すべき簡単なチューニングと最適化を加えます。必要であれば、その後のステップとして、IBM XL コンパイラーによって IBM Power Architecture の特定のレベルに合わせて、より高いパフォーマンスが発揮されるようにチューニングすることも考えられます。

x86 と Power Architecture のバリエーションとの違いを理解する

x86 Linux アプリケーションを Power Systems に移植する前に、認識しておかなければならないアーキテクチャー固有の違いがいくつかあります。以下に、特に注目に値するアーキテクチャー上の違いを記載します。その詳細については、以降のセクションで説明します。

  • エンディアン方式 (バイト・オーダー)
  • 32 ビット/64 ビット・アプリケーション環境でのデータ型の長さ
  • アーキテクチャーによるデータ・アライメントの違い

上記以外のいくつかの考慮事項については、後で、x86 と Power とでアプリケーションを比較する際に説明します。例えば、最適化についての考慮事項としては、複数スレッドによるスループットの最適化、単純なロック・スキームの使用法の評価などが挙げられます。

エンディアン方式 (バイト・オーダー)

POWER プロセッサーは、バイト・オーダー方式として、ビッグエンディアンとリトルエンディアンの両方をサポートすることができますが、これまでの実装では、ビッグエンディアン・アーキテクチャーが使用されてきました。一方、x86 プロセッサーが使用するのは、リトルエンディアン・アーキテクチャーです。このセクションでは、エンディアン方式 (バイト・オーダーとも呼ばれます) の問題を取り上げ、これらの問題に対処する手法を説明します。「下位レベル」で動作するアプリケーション、デバイス・ドライバー、またはデータ・ファイルを x86 アーキテクチャーから Power Architecture に移植するプロセスで、開発者がバイト・オーダーの問題に直面することはよくあることです。「上位レベル」で動作するアプリケーションでは、移植の際にエンディアン方式の問題に突き当たることはあまりありませんが、それでも x86 から Power に移植する場合は、この問題を評価しておく必要があります。

エンディアン・バイト・オーダーは、整数データと浮動小数点データに影響しますが、文字ストリングには影響しません。というのも、文字ストリングでは、ストリングの文字の順番は見たとおりに、そしてプログラマーが意図するとおりに維持されるからです。したがって、未加工の ASCII テキスト・ファイルは問題ありませんが、マシンに依存しないデータ・ファイルは、ハードウェアのエンディアン方式の問題による影響を受ける場合があります。例えば、JPEG ファイルはビッグエンディアン・フォーマットで保管される一方、GIF ファイルと BMP ファイルはリトルエンディアン・フォーマットで保管されるなどといった問題です。

ビッグエンディアンとリトルエンディアン

エンディアン方式とは、データ要素とその個々のバイトが、どのようにメモリーに保管されてアドレッシングされるのかを表しています。複数桁の数値では、上位の桁のほうが、重要であるとみなされます。例えば、4 桁の 8472 という数値の場合、4 は 7 よりも重要です。同様に、複数バイトの数値データでは、保持している値が大きいバイトほど、より重要なバイトになります。例えば、0x89ABCDEF という16 進値は、0x89、0xAB、0xCD、0xEF の 4 つのバイトに分割できます。これらのバイトに対応する算術値は、それぞれ 0x89000000、0xAB0000、0xCD00、0xEF です。明らかに、バイト 0x89 が最も大きな値であるため、これが最も重要なバイトであり、バイト 0xEF が最も小さいことから、これが最も重要でないバイトということになります。

メモリー内では、数値は最下位アドレスから配置されるため、理にかなった配置方法は 2 つしかありません。

  • 最も重要でないバイトを最初に配置する (リトルエンディアン)
  • 最も重要なバイトを最初に配置する (ビッグエンディアン)

以下の図に、例として 0x89ABCDEF という 32 ビットの 16 進値が、ビッグエンディアンのプロセッサーとリトルエンディアンのプロセッサーのそれぞれで、どのようにメモリーに配置されるかを示します。

図 1. ビッグエンディアンのプロセッサーとリトルエンディアンのプロセッサーでの 16 進値の格納方法

0x89 が最も重要なバイトで、0xEF が最も重要でないバイトです。ビッグエンディアン・システムでは、メモリー・アドレスの最下位に最も重要なバイトが配置されます。それとは逆に、リトルエンディアン・システムでは、メモリー・アドレスの最下位に最も重要でないバイトが配置されます。

プログラムによってメモリーに 1 ワードのデータを書き込み、その同じ場所を 1 ワードのデータとして読み取る場合、バイト・オーダーは問題になりません。それは、プログラムが変数を参照する際に一貫して同じ値を認識するためです。プログラムが (書き込みは 1 ワードで行われている場合に) この同じ値を一度に 1 バイトずつ読み取ろうとすると、プロセッサーがビッグエンディアンかリトルエンディアンかによって、結果が異なってくる可能性があります。

IBM POWER プロセッサー・ファミリーは、ビッグエンディアンのデータ・レイアウトを使用するシステムの一例であり、x86 プロセッサー・ファミリーは、リトルエンディアンのデータ・レイアウトを使用するシステムの一例です。したがって、x86 アプリケーションを Power プラットフォームに移植する際には、エンディアンに依存するコード・セグメントを識別して、ビッグエンディアンのコード・セグメントに変換することが重要になります。

エンディアン方式の対処方法

このセクションでは、コード内でエンディアンに依存する領域を識別する方法と、それらの領域を正しいエンディアン・フォーマットに変換する手法を説明します。

エンディアンに依存するコード
C 言語の長所は、データを参照する際の非一様性です。これを理由に、オペレーティング・システムやデバイス・ドライバーなどといったシステム・レベルのソフトウェアをプログラミングするときには、C 言語がよく使われています。この C 言語の長所には、型キャスト、ポインター操作、共用体、ビット・フィールド、構造体、そして柔軟な型チェックなども含まれます。ただし、これらの特徴は、エンディアン方式の移植性に関する問題の原因にもなります。例として、以下の 2 つのコード・リストについて検討してみましょう。

リスト 1. ポインターを使用した非一様なデータ参照
#include <stdio.h>
int main(void) {
  int val;
  unsigned char *ptr;

  ptr = (char*) &val;
  val = 0x89ABCDEF; /* four bytes constant */
  printf("%X.%X.%X.%X\n", ptr[0], ptr[1], ptr[2], ptr[3]);
  exit(0);
}
リスト 2. 共用体を使用した非一様なデータ参照
#include <stdio.h>
union {
  int val;
  unsigned char c[sizeof(int)];
} u;

int main(void) {
  u.val = 0x89ABCDEF; /* four bytes constant */
  printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
  exit(0);
}

x86 システムでは、以下の結果になります。

 EF.CD.AB.89

POWER プロセッサー・ベースのシステムでは、以下の結果になります。

 89.AB.CD.EF

このように、val が最も重要なバイトからバイト単位で読み取られると、エンディアン方式の問題が表面化します。

システムのエンディアン方式を判別する方法

Linux では、GNU_C プリプロセッサーが、共通の定義済みマクロのセットを自動的に提供するのが通常となっています。マクロの名前には、先頭と末尾にアンダーバーが 2 つ続けて付けられます。これらのマクロのうち、システムで使用しているエンディアン方式を判別するのに最も役立つのは、__BYTE_ORDER__、__ORDER_LITTLE_ENDIAN__、および __ORDER_BIG_ENDIAN__ です。

/* Test for a big-endian machine */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* Do big endian processing */
/* Test for a big-endian machine */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* Do big endian processing */

エンディアン・ニュートラルなコードの作成

プログラムのモジュールが、エンディアン方式の異なるプラットフォーム間で移植されても機能を維持する場合、そのモジュールはエンディアン・ニュートラルであるとみなされます。つまり、モジュールの機能と、モジュールが実行されるプラットフォームのエンディアン方式の間には、何の関係もないということです。以下に、そのようなエンディアン・ニュートラルなコードを作成するためのアドバイスを 2 つ記載します。

  • マクロとディレクティブを使用すること
    コードを移植可能にするには、リスト 3 とリスト 4 に示すように、マクロと条件付きコンパイル・ディレクティブを使用することができます。
リスト 3. ディレティブを使用してエンディアン方式の効果を中和する
#include <stdio.h>

#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0
#define BYTE_ORDER (( htonl(1)==1) )   //  returns 1 or 0 depending on platform


union {
  int val;
  unsigned char c[sizeof(int)];
}u;

int main(void) {
  u.val = 0x89ABCDEF;
  #if (BYTE_ORDER == BIG_ENDIAN)
  printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
  #else /*! BYTE_ORDER == BIG_ENDIAN*/
  printf("%X.%X.%X.%X\n", u.c[3], u.c[2], u.c[1], u.c[0]);
  #endif /*BYTE_ORDER == BIG_ENDIAN*/
  exit(0);
}
リスト 4. マクロを使用してバイトをスワップする (実行時にエンディアン方式を判別するのに役立ちます)
//  Useful Endian Neutral Macros

#include <endian.h>        

#if __BYTE_ORDER == __BIG_ENDIAN
// No translation needed for big endian system
#define sw2Bytes(val) val
#define sw4Bytes(val) val
#define sw8Bytes(val) val
#else
//  Little Endian:  Translate
// Swap 2 byte, 16 bit values:

#define sw2Bytes(val) \
 ( (((val) >> 8) & 0x00FF) | (((val) << 8) & 0xFF00) )

// Swap 4 byte, 32 bit values:

#define sw4Bytes(val) \
 ( (((val) >> 24) & 0x000000FF) | (((val) >>  8) & 0x0000FF00) | \
   (((val) <<  8) & 0x00FF0000) | (((val) << 24) & 0xFF000000) )

// Swap 8 byte, 64 bit values:

#define sw8Bytes(val) \
 ( (((val) >> 56) & 0x00000000000000FF) | (((val) >> 40) & 0x000000000000FF00) | \
   (((val) >> 24) & 0x0000000000FF0000) | (((val) >>  8) & 0x00000000FF000000) | \
   (((val) <<  8) & 0x000000FF00000000) | (((val) << 24) & 0x0000FF0000000000) | \
   (((val) << 40) & 0x00FF000000000000) | (((val) << 56) & 0xFF00000000000000) )
#endif
int main(void) {
  int a=0x11121314;
  int b;
  b = sw4Bytes(a);      // b is 0x12 in LE and BE
}
  • コンパイル時のオプションを使用すること
    エンディアン・ニュートラルなコードを実装するもう 1 つの方法は、コンパイラー・コマンド・ライン上で -DBYTE_ORDER の値を定義することです (例えば、-DBYTE_ORDER=BIG_ENDIAN)。これにより、異なるバイト・オーダーを使用する新しいプラットフォームでコンパイルする際に、デバイス・ドライバーやアプリケーションに含まれるあらゆるファイルを編集する必要がなくなり、ドライバーまたはアプリケーションをビルドするために使用する makefile を編集するだけで済みます。

Linux 固有のバイト・オーダー

Linux カーネルでは、16 ビット、32 ビット、64 ビットをリトルエンディアンからビッグエンディアンに、またはビッグエンディアンからリトルエンディアンに切り替える、固有のシステム・マクロのセットを使用できることがわかっています。これらのマクロは、Linux x86 から Linux on Power に移植する上でも、コードをエンディアン・ニュートラルにするのにも重宝し、かなりの数の条件付きコンパイル・ディレクティブ #ifdef __LITTLE_ENDIAN をコード全体にわたってコーディングすることをまったく気にする必要がなくなります。

例:

cpu_to_le32(u32); // CPU のエンディアン方式の 4 バイトをリトルエンディアンに変換

le32_to_cpu(u32); // リトルエンディアン方式の 4 バイトを CPU のエンディアン方式に変換

上記の 2 つのマクロは、CPU が使用しているエンディアン方式が何であろうと、そのエンディアン方式の値をリトルエンディアンの 32 ビット符号なしの値に変換するマクロと、その逆の変換を行うマクロです。例えば、Linux on Power システムでは、le32_to_cpu(u32) によってリトルエンディアンがビッグエンディアンに変換され、cpu_to_le32(u32) によってビッグエンディアンがリトルエンディアンに変換されます。使用するマクロ、そしてそのマクロを実行するシステムによっては、何も処理しなくてよい場合があります。その場合には、単に元の値が返されます。

上記のマクロとその他多数のマクロは、/usr/include/linux/byteorder/big_endian.h および /usr/include/linux/byteorder/little_endian.h にあります。

必要なマクロを見つけるには、これらのヘッダー・ファイルを調べてください。名前のパターンを見ることで、その用途を推測することができるはずです。

以下のように、定義済み GNU_C プリプロセッサー・ディレクティブを使用すると、簡単に正しいインクルード・ファイルをインクルードすることができます。

#include <endian.h>

#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   #include <linux/byteorder/big_endian.h>
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   #include <linux/byteorder/little_endian.h>
#else
   //  …user defined endian header
#endif

エンディアン方式に関するその他の考慮事項

外部のデータ・ファイルに依存せず、ANSI C の プログラミング標準に厳密に従っている上位レベルのアプリケーションは、x86 から Powerに移植しても、エンディアン関連の問題が 1 つも発生することなく、順調に Linux on Power へ移植できるはずです。しかしながら、エンディアン方式は理解しておくべき重要な概念であり、コードのエンディアン関連の脆弱性を認識することができれば、Linux on Power への移植が容易になります。

次のセクションでは、以上のことに加え、IBM Linux SDK 内で使用できる、その他のコード分析ツールに焦点を当てます。これらのツールが、エンディアン方式の問題を識別するのに役立つこともあります。

使用する移植ツールの選択

機械工と同じく、移植エンジニアは、手持ちの「テクニカル」ツールボックスに各種のツールを取り揃えて、移植に伴う難題を最小限に抑えるために、どのツールを使用すればよいのかを知っていなければなりません。IBM Linux on Power SDK と IBM Rational Developer for Power Systems は、どちらも Power サーバーでの移植と開発を容易にするオールインワンの統合開発環境 (IDE) であり、Linux on Power への移植に取り組む開発者にとって優れたテクニカル・ツールになっています。

Migration Advisor が統合された IBM SDK for PowerLinux

IBM SDK (Software Development Kit) for PowerLinux は、無料で入手できる Eclipse ベースの IDE です。IBM SDK for PowerLinux は、C/C++ ソース開発環境に Advance Toolchain、ポストリンク最適化ツール (FDPR など)、従来の Linux パフォーマンス分析ツール (OProfile、Perf、Valgrind など) を統合するだけでなく、この SDK には、Migration Advisor というツールも組み込まれています。Migration Advisor ツールの機能の 1 つに、コード・チェックとコード・フィックスを行う機能があります。Migration Advisor ツールではこの機能を使用することで、コードを分析して Linux/x86 の脆弱性を調べ、ユーザーに対して、コード内の脆弱性をすぐに修正するオプション、または手作業でコードを修正する方法に関する提案を提供します。例えば、以下のようなキャストは、x86 Linux から Linux on Power に移植する際にエンディアン方式の典型的な問題を引き起こします。このような脆弱性に対し、Migration Advisor は、メッセージ「Cast with endianness issue checker (エンディアン方式の問題を伴うキャストのチェッカー)」のフラグを立てます。

void foo() {
    short int val = 0xFF00;
    char *char_pointer = (char *) &val;     
    //This prints 0 in x86 (or x86_64) machines and ff in ppc (or ppc64) machines.
    printf("%x\n", *char_pointer);
}

Migration Advisor は、Eclipse CDT Code Analyzer (Codan) ソース・コード・アナライザーを使用して、C/C++ ソース・コードの移植に伴う潜在的な問題を突き止めます (例えば、x86 サーバーまたは POWER サーバーで実行すると異なる結果を生成する可能性があるコード・ブロックなど)。ソース・コード内の問題を見つけるために、Codan は C/C++ ソース・コードの抽象構文木 (AST) を分析し、Power Architecture に対応しない可能性がある部分を検出します。Migration Advisor は潜在的問題を検出すると、コードの問題の部分を保存して、ソース・コードのその特定の位置に、警告を追加します。現在、Migration Advisor が対応しているのは、C/C++ コードのみです。

以下に、IBM SDK for PowerLinux で使用されている Migration Advisor のスクリーン・キャプチャーを示します。

図 2. Migration Advisor の「エンディアン方式の問題がある共用体」チェッカーの実行

Migration Advisor: クイック・フィックス機能

Migration Advisor には、移植に関する一部の問題に対するクイック・フィックスも用意されていて、アーキテクチャーに依存するコード・ブロックを、POWER プロセッサーに対応する命令に置き換えることができます。クイック・フィックスを実行する方法は 2 通りあります。1 つはソース・コード内で警告を右クリックし、クイック・フィックス・オプションを選択する方法で、もう 1 つは Migration Advisor の Eclipse ビューを開き、特定の問題を右クリックして、クイック・フィックス・オプションを選択する方法です。

Migration Advisor のクイック・フィックス機能は、以下の場合に適用されます。

  • x86 固有の組み込みコンパイラーを使用している場合
  • インライン・アセンブリーを使用している場合
  • パフォーマンスが低下する場合

どのチェッカーを有効にして、どのチェッカーを無効にするかは、ユーザーが選択することができます。Migration Advisor は、ソース・コードが変更されるたびに、コードを再チェックして結果を更新するので、プロジェクトの完全なリビルドを行う前に、問題を迅速に特定して解決する機会が与えられるというわけです。図 3 に、すべてのチェッカーが有効になっている状態の Migration Advisor ウィンドウを示します。

図 3. すべてのチェッカーを有効にする

Migration Advisor チェッカーを有効にした後、プロジェクトを右クリックして、「Run Migration Advisor (Migration Advisor の実行)」をクリックします。すると、Migration Advisor は有効にされたチェッカーを使用してコードを分析し、その結果を Eclipse ビューに表示して、検出された潜在的な問題を明らかにします (図 4 を参照)。

図 4. Migration Advisor ビュー

図 5 に、Power プラットフォーム上でサポートされていない組み込みが原因で発生した、実際の移植に関する問題の例を示します。問題を修正する上で必要なのは、Migration Advisor Eclipse ビューでその問題をダブルクリックすることのみです。すると、ソース・コード・ビューが開き、問題の正確な場所が強調表示されて示されます。強調表示されたコードにマウス・カーソルを重ねて Ctrl+1 を押すと、別のポップアップ・ウィンドウが開きます (図 5 を参照)。

図 5. Migration Advisor のクイック・フィックスを使用する

最初の選択肢「Builtin quick fix (組み込みクイック・フィックス)」を選択します。図 6 に、クイック・フィックスが適用された後のコードを示します。

図 6. Migration Advisor クイック・フィックスが適用された後のコード

Migration Advisor には、他にも以下の有用なチェック機能があります。

  • x86 固有のアセンブリーに対するチェッカー
  • ビット・フィールドを使用した構造体に対するチェッカー
  • long double の使用に対するチェッカー
  • パフォーマンスの低下に対するチェッカー
  • 組み込まれた x86 固有のコンパイラーの使用法に対するチェッカー

便利なチェック機能を網羅したリストについては、IBM Knowledge Center を参照してください。

LCT (Linux Cross-platform Tool)
SDK for PowerLinux には、既存のどの Intel x86 システム上でも動作する便利なツールも組み込まれています。そのツールとは、アプリケーションの潜在的な移植性の問題を特定するコマンド・ライン・ツールです。この LCT を使用することで、ソースを Linux on Power に移植する前に、ソースに伴う潜在的な問題を迅速に把握することができます。IBM SDK for PowerLinux をインストールした後は、ツールの README セクションで、LCT に関するドキュメントを参照することができます。

IBM Rational Developer for Power Systems
IBM Rational Developer for Power Systems も、マルチプラットフォーム開発 (IBM i、AIX、または Linux on Power) に対応する、リッチなデスクトップ統合開発、移植、最適化環境を提供します。また、コード分析ツール、パフォーマンス・アドバイザー・ツールなど、多種多様な移植ツールも含まれています。移植ツールのなかでも、IBM SDK for PowerLinux と同様の Migration Assistant を使用すると、32 ビットから 64 ビットへ移行する際の問題、エンディアン方式の問題、そして移植性の妨げとなり得るその他のオペレーティング・システム関連の問題を検出することができます。

JVM
Java 仮想マシン (JVM) は、すべてのプラットフォームにおいてビッグエンディアン・モードで動作するため、通常は、プロセッサー・アーキテクチャーの影響を受けません。

データ型とアライメント

x86/x86_64 と Power Systems の間には、signed/unsigned char の ABI (Application Binary Interface: アプリケーション・バイナリー・インターフェース) に微妙ながらも重要な違いがあります。

x86/x86_64 では、char のデフォルトは signed char ですが、Power Systems でのデフォルトは unsigned char です。Power Systems で、このデフォルトを変更するには、GCC ディレクティブ -fsigned-char を使用します。IBM XL でこれに相当するディレクティブは、-qchars=signed です。

Linux オペレーティング・システムの GCC コンパイラーと XL C/C++ コンパイラーには、どちらも ILP32 と LP64 という 2 つの異なるプログラミング・モデルがあります。ILP32 (Integer Long Pointer 32) は、Linux のネイティブ 32 ビット・プログラミング環境です。ILP32 データ・モデルは、32 ビットのアドレス空間を提供し、理論上のメモリー制限は 4 GB となっています。LP64 (Long Pointer 64) は、Linux の 64 ビット・プログラミング環境です。

表 1 に、POWER および x86 での ILP32 モデルと LP64 モデルにおける基本データ型のビット幅を示します。

表 1. POWER および x86 での ILP32 と LP64 の基本データ型 (ビット幅)
基本データ型POWERx86
ILP32LP64ILP32LP64
char
デフォルト: x86 では signed、POWER では unsigned
8 8 8 8
short 16 16 16 16
int 32 32 32 32
float 32 32 32 32
long 32 64 32 64
long long 64 64 64 64
double 64 64 64 64
long double 64/128* 64/128* 96 128
ポインター 32 64 32 64

*現在、Linux on Power での long double のデフォルト・サイズは、128 ビットとなっています。XL C/C++ コンパイラーでコンパイラー・オプション -qnoldb128 を指定すると、サイズを 64 ビットに縮小することができます。

Power プラットフォームと x86 プラットフォームではどちらも、数値型のすべての定義が /usr/include/limits.h にあります。

レガシー Linux x86 アプリケーションの多くは、32 ビットの環境で実行されます。最新の x86 アーキテクチャーでは、64 ビットのアプリケーションをサポートし、これを使用するように奨励しているため、x86 アプリケーションは、64 ビットに更新されることや、最初から 64 ビットで作成されることが多くなっています。x86 アプリケーションを Power Systems に移植する演習では、Linux on Power 環境をターゲットにして、ソース環境と一致させることができます。つまり、初期移植を最初に完了してから、64 ビット・プログラミング・モデルに移行することをおすすめします。32 ビットの x86 アプリケーションを 64 ビットの Power Systems プログラミング・モデルに移植する場合は、移植を以下の 2 つのステップに分けて扱ってください。

  1. Linux on Power 32 ビット環境に移植する (テストと検証を含む)
  2. 64 ビット環境に移行する

アプリケーションが以下の条件に該当する場合には、エンジニアはアプリケーションを 64 ビットへ移植することを検討する必要があります。

  • 仮想アドレス空間が 4 GB より大きいとメリットがある場合
  • 物理メモリーが多い (4 GB を超える) とメリットがあり、ユーザーが 4 GB を超える物理メモリーを備えたシステムにアプリケーションをデプロイする可能性が高い場合
  • 64 ビットの長整数型を使用するメリットがある場合
  • 64 ビットのレジスターをフルに使用して効率的な 64 ビット演算を行うメリットがある場合
  • 2 GB より大きいファイルを使用する場合

64 ビットに移行することにメリットがあるアプリケーションには、以下の例があります。

  • データベース・アプリケーション (特に、データ・マイニングを行う場合)
  • Web キャッシュ、Web 検索エンジン
  • CAD (Computer-Aided Design)/CAE (Computer-Aided Engineering) シミュレーションおよびモデリング・ツールのコンポーネント
  • 科学・技術計算アプリケーション (計算流体力学、遺伝子シミュレーションなど)

アプリケーションを 32 ビットのまま、コードを変更せずに 64 ビットの Linux on Power カーネル上で実行することもできます。IBM Power プロセッサー・ベースのサーバーでは、32 ビットのアプリケーションと 64 ビットのアプリケーションを同時に 64 ビット・アーキテクチャーで実行できるようになっています。

アプリケーションを異なるプラットフォーム (x86 から Power) に移植する場合や、異なるプログラミング・モデル (ILP32 から LP64) に移植する場合は、パフォーマンスが低下したり、データが破損したりするおそれがあります。これを回避するために、環境が変わったことによる、使用可能なデータの幅とアライメントの設定の違いを考慮する必要があります。

表 1 からわかるように、x86 ILP32 から POWER ILP32 に、または x86 LP64 から POWER LP64 に移植しても、long double を除くすべての基本データ型の幅は変わりません。long double データ型は、IPL32 の場合は 96 ビットから 64/128 ビットに、LP64 の場合は 128 ビットから 64/128 ビットに変わります。したがって、コードのなかでおそらく調べる必要があるのは、long double データ型に関連する部分です。XL C/C++ コンパイラーを使用する予定の場合は、-qlongdouble コンパイル・フラグを指定すると、long double データ型の互換性を最大限にすることができます。

データのアライメント

プラットフォーム間、または 32 ビット・モデルと 64 ビット・モデルの間で移植する場合は、パフォーマンスの低下やデータの破損のおそれがあります。これを回避するために、環境が変わったことによる、使用可能なアライメントの設定の違いを考慮する必要があります。ベスト・プラクティスは、データ項目の自然なアライメントを適用することです。自然なアライメントとは、データ項目を、そのサイズの倍数のアドレスに格納することを意味します (例えば、8 バイトのデータ項目は、8 の倍数のアドレスに格納されます)。XL C/C++ コンパイラーでは、さまざまなデータ型の集合体 (C/C++ 構造体/共用体および C++ クラス) を構成するそれぞれのデータ型は、linuxppc ルールまたはビット・パックのいずれかのルール (デフォルトは、自然なアライメントを適用する linuxppc です) に従って、バイト境界に合わせてアライメントされます。linuxppc は、デフォルトの GCC アライメント・ルールと互換します。表 2 に、POWER と x86 でのアライメント値とそのデータ型の幅 (バイト数) を示します。

表 2. POWER と x86 でのアライメント値 (バイト数)
データ型POWERx86
ILP32LP64ILP32LP64
アライメント値 アライメント値 アライメント値 アライメント値
Char 1 1 1 1 1 1 1 1
short 2 2 2 2 2 2 2 2
int 4 4 4 4 4 4 4 4
float 4 4 4 4 4 4 4 4
long 4 4 8 8 4 4 8 8
long long 8 8 8 8 8 8 8 8
double 8 8 8 8 8 8 8 8
long double 8/16 8 8/16 8 12 4 16 16
ポインター 4 4 8 8 4 4 8 8

GCC と XL C/C++ では、どちらもキーワード __alignof__ を使用して、オブジェクトのアライメント方法を照会することができます。構文は、sizeof と同様です。例えば、ターゲット・システムで、double 型の値を 8 バイト境界に合わせてアライメントしなければならない場合、__alignof__ (double) は 8 になります。

表 2 に示されているように、long double 型の変数は、x86 では 4 バイト幅でアライメントされますが、Power Systems では 8 バイト幅でアライメントされます。したがって、構造体はプラットフォームによって異なるレイアウトを持つことになります。サイズとオフセットはハードコーディングしないようにすることが重要です。代わりに、C の sizeof 演算子を使用して、基本型と複合型両方のサイズを照会します。offsetof マクロを使用すると、構造体の先頭に対する、構造体メンバーのオフセットを取得することができます。

使用するコンパイラーの決定: GCC または IBM XL C/C++

Linux on Power で使用できる C/C++ コンパイラーには、GCC と IBM XL C/C++ の 2 つがあります。GCC は、Linux でコンパイルされることを意図したコードに強力な移植性を提供します。一方、IBM XL C/C++ コンパイラーは、上位レベルの最適化が使用されている場合には、GCC よりもかなり高いパフォーマンスを実現します。どちらのコンパイラーにも、32 ビット・コンパイル・モードと 64 ビット・コンパイル・モードがあります。また、Linux on Power 環境では、パフォーマンスを犠牲にすることなく、32 ビットのコードと 64 ビットのコードを同時に実行することができます。

GCC コンパイラー・セットを使用する場合の移植

コンパイラーとして始めから GCC コンパイラーが使用されている複数のプラットフォームで開発されるプロジェクトでは、Linux on Power のアプリケーションをデプロイするために、GCC コンパイラーが使用されることがよくあります。これは特に、サイズの小さいユーティリティーなど、パフォーマンスがそれほど重要でないアプリケーションの場合に当てはまります。GCC では、GCC にしか理解できないコード・プロトタイプ (例えば、GCC 固有のマクロなど) も使用することができます。ただし、XL C/C++ コンパイラーには、GCC 固有の機能の多くが組み込まれていることに注意してください。

一般に、GCC コンパイラーを使用してコードを移植するのは簡単なはずです。この作業は、ほとんどの場合、単純な再コンパイル作業であり、make コマンドを入力するだけの簡単なものです。アーキテクチャーが異なると、ライブラリー・バージョンに相違が生じる可能性はありますが、ほとんどのところ、どのアーキテクチャーでコードを実行するかは問題になりません。Power Linux 上でのコンパイルでは、アーキテクチャー固有のフラグ (-m486-mpowerpc64 など) を使用しないようにしてください。その理由は、GCC には、これらのアーキテクチャーでの最適化ルーチンに対応する広範なプロセッサー・マップがないためです。また、アーキテクチャー固有のフラグを使用しないようにすれば、POWER ハードウェアのさまざまなモデルの間でのバイナリー互換性が高くなります。

SLES 11 と RHEL 6 に付属の GCC コンパイラーは、32 ビットと 64 ビットのアプリケーションを両方ともサポートしています。SLES 11 と RHEL 6 のバージョンでは、デフォルト・コンパイル・モードは 64 ビットです。

すべてのアーキテクチャーにおいて、ライブラリーをコンパイルするには -fPIC を指定する必要があります。x86 では、このフラグがデフォルトで GCC に適用されます。POWER では、このフラグを適用すると、生成されるコードは共有オブジェクトで使用されるようになります。詳細については、GCC コンパイラーのマニュアル (「参考文献」を参照) を調べてください。

IBM XL C/C++ コンパイラーを使用する場合の移植

XL C/C++ は GNU C および C++ ヘッダーを使用します。これによって生成されるアプリケーションは、GCC に付属の C および C++ ランタイム・ライブラリーにリンクされます。つまり、XL C/C++ コンパイラーは、GCC コンパイラーが生成するオブジェクトと完全に互換する GNU ELF (Executable and Linking Format) オブジェクトを生成するということです。XL C/C++ コンパイラーの自動並列化および OpenMP 機能をサポートするために、XL C/C++ には SMP (Symmetrical Multiprocessing) ランタイム・ライブラリーが含まれています。

Linux on Power で GCC から XL C/C++ に移行するのは簡単です。XL C/C++ には、この作業を支援するためのオプション -qinfo=por があります。このオプションを指定すると、出力される診断メッセージをフィルタリングして、移植性の問題に関連するメッセージのみを表示できるようになります。さらに、XL C/C++ は、gcc および gcc-c++ に対する GNU 拡張機能の一部をサポートしています。

サポートされている全機能のリスト、および許可されるものの、セマンティックは無視される機能については、「XL C/C++ for Linux on pSeries Compiler Reference」を参照してください。

サポートされている機能を C コードで使用するには、-qlanglvl=extended または -qlanglvl=extc89 のいずれかを指定します。C++ では、サポートされている GNU gcc/gcc-c++ 機能のすべてが、デフォルトで許可されます。しかも、gxlc と gxlc++ を利用することで、GNU コンパイラーでビルドした既存のアプリケーションの makefile に加える変更を最小限にすることもできます。

XL C/C++ での最適化オプション

XL C/C++ には、IBM ハードウェアに合わせて調整された最適化オプションが揃っています。Linux on Power の場合、XL C/C++ で正しい最適化フラグの組み合わせを使用してコンパイルされたアプリケーションの多くが、GCC でコンパイルされたアプリケーションを大幅に上回るパフォーマンスを発揮します。ただし、すべての最適化がすべてのアプリケーションに有効であるとは限りません。通常は、コンパイラーによる最適化レベルと、デバッグ機能の縮小に伴うコンパイル時間の増加との間で、トレードオフがあります。

最適化レベル
最適化レベルは、コンパイラー・オプションで指定します。以下の表に、最適化レベルごとのコンパイラーの動作を要約します。

表 3. 各最適化レベルでのコンパイラーの動作
オプション動作
-qnoopt 高速コンパイルと完全デバッグをサポートします。
-O2 (-O と同等)コンパイル速度とランタイム・パフォーマンスが最も望ましいとコンパイラー開発者が考える最適化を実行します。このオプションを指定した場合、-qnostrict_induction または -qnostrict を指定して明示的に無効にしない限り、-qstrict および -qstrict_induction を指定したのと同じ効果が表れます。
-O3 メモリーに重点を置いた最適化、コンパイル時間に重点を置いた最適化、あるいはその両方に重点を置いた最適化を実行します。コンパイルのリソースを最小限にすることよりも、ランタイムの改善のほうが優先される場合には、この設定が推奨されます。
-O4 および -O5プロシージャー間の最適化、ループ最適化、および自動マシン・チューニングを実行します。

指定すべきでない、以前の Power オプション

以下に、x86 から Linux on Power に移植する場合に指定すると、悪影響を及ぼすため、指定すべきでない古い Power Architecture のオプションをリストアップします。

  • -mminimal-toc または -mfull-toc を指定した PPC64 ビルドは、-mcmodel=medium (デフォルト) に置き換える必要があります。
  • -ffloat-store は、Power では指定しないでください。

ターゲット・マシンのオプションは、コンパイラーに対し、特定のマイクロプロセッサーまたはアーキテクチャー・ファミリーで最適に実行されるコードを生成するよう指示するものです。適切なターゲット・マシンのオプションを選択することにより、選択可能な最大限のターゲット・プロセッサーに適合するか、特定のプロセッサー・アーキテクチャー・ファミリーに含まれる一連のプロセッサーに適合するか、特定の 1 つのプロセッサーに適合するように、最適化を実行することができます。以下の表に記載するオプションは、ターゲット・マシンの個々の側面に影響を及ぼす最適化を制御します。

表 4. ターゲット・マシンの個々の側面に影響を及ぼす最適化のオプション
オプション動作
-qarch命令コードの生成対象とするプロセッサー・アーキテクチャー・ファミリーを選択します。デフォルトは -qarch=auto です。指定可能なサブオプションには、ppc64grsq、pwr3、pwr4、pwr5、ppc970、ppc64、pcgr、rs64b、rs64c があります。
-qtune特定のマイクロプロセッサーでの実行に、最適化のバイアスをかけますが、ターゲットとして使用する命令セット・アーキテクチャーについての暗黙的な指定はありません。Linux でのデフォルトは -qtune=auto です。使用可能なサブオプションには、pwr3、pwr4、pwr5、pwr6、pwr7、pwr8、ppc970、rs64b、rs64c があります。ただし、この設定は多くの場合、-qarch の設定に基づいて自動的に指定されます。
-qcache特定のキャッシュまたはメモリー・ジオメトリーを定義します。-qcache を指定する場合は、-qhot または -qsmp を同時に使用します。
-qhot高次変換とは、交換、フュージョン、アンロールなどの手法によって、特にループのパフォーマンスを向上させる最適化です。-qhot を指定すると、オプション -qhot=vector がデフォルトになります。-qhot は、-O2 および -O3 と同時に使用するようにしてください。このオプションは、変換の最適化が存在しない場合に、中立的な効果を及ぼすように設計されています。
-qsmp共有メモリーの並列処理に必要なスレッド化コードを生成します。-qsmp を指定すると、オプション -qsmp=auto がデフォルトになります。OpenMP プログラムをコンパイルしていて、自動並列処理を望んでいない場合には、-qsmp=omp:noauto を指定します。-qsmp を使用する場合は、必ず _r コンパイラー呼び出しを指定してください。

ターゲット・マシンのオプションを最大限利用するには、以下のようにしてください。

  • -qarch を指定することで、コードが適切に実行されることが見込まれる最小限のマシン・ファミリーを指定します。
  • -qtune を指定することで、最大限のパフォーマンスを必要とするマシンを指定します。例えば、アプリケーションのターゲットが、POWER8 プロセッサー・ベースのシステムで開始される Power サーバーの場合、-O3 -qarch=pwr8 -qtune=pwr8 のように指定します。

IBM Power プラットフォームは、他のプラットフォームでは使用できないマシン命令をサポートします。XL C/C++ には、特定の POWER プロセッサー命令に直接マッピングされる一連の組み込み関数が用意されています。これらの関数を使用することで、関数をコールしてリターンするのにかかるコスト、パラメーターの受け渡し、スタックの調整、そして関数コールに関連するすべての追加コストが排除されます。サポートされている組み込み関数の全リストについては、pSeries での Linux 向け XL C/C++ コンパイラー・リファレンスのインストール・マニュアルを参照してください。

一方、元々 GCC コンパイラーでのコンパイルが意図されているソフトウェアについては、IBM XL C/C++ コンパイラーで再コンパイルする際に、さらに注意が必要になるかもしれません。第一に、makefile を編集して、XL C/C++ コンパイラーの正しいパス (デフォルトでは、/opt/ibmcmp/) を反映させなければなりません。また、特定のアーキテクチャーに適切な最適化フラグを設定する必要もあります (例えば、IBM POWER8 プロセッサーの場合は、-03 -qarch=pwr8 -qtune=pwr8)。

Power Architecture のさまざまなバリエーションに応じた最適化モードに加え、XL C/C++ コンパイラーに対し、共通モードでソフトウェアをコンパイルするよう命令することもできます。これにより、すべての Power Architecture バリエーションでの互換性が保証されます。ただし、その代償として、アーキテクチャー固有の最適化から得られるパフォーマンスの向上は犠牲になります。64 ビットのコードをコンパイルする場合は、コンパイラーに 64 ビット・ビルドのフラグ (-q64) を指定する必要があります。これは、デフォルトでは 32 ビット・モードに設定されるためです。

XL C/C++ コンパイラー・セットを使用して GCC 指向のコードをコンパイルする場合は、以下に記載するヒントを参考にしてください。

  • GCC ではデフォルトで、C ファイル内で C++ スタイルのコメントを使用できるようになっていますが、XLC (XL C コンパイラー) ではその限りではありません。一連のソース・ファイルですべてのコメントを C スタイルのコメントに適合するように変更するのは効率的ではないため、XLC では、-q 引数を使用して、C++ スタイルのコメントを使用できるようにしています (-q cpluscmt)。このフラグを指定して C コードをコンパイルすると、C スタイルと C++ スタイル両方のコメントが解釈されます。
  • 環境変数は、ビルド・スクリプトを構成する最も簡単な手段になることがよくあります。手作業で構成スクリプトと makefile を編集するのではなく、関連する環境変数を設定してください。例えば、$CC$CFLAGS を使用すると、手作業で編集しなくても、構成スクリプトで makefile を生成することができます。
  • 構成スクリプトも、正しいプラットフォームのタイプを認識する必要があります。これは、linux-powerpc-unknown-gnu または linux-powerpc64-unknown-gnu のいずれかです。GCC または XL C/C++ のいずれかを使用したコンパイルで、プラットフォームのタイプを設定するには、-target= フラグを構成スクリプトに追加します。
  • IBM XL C/C++ コンパイラーについては広範なドキュメントがありますが、引数を指定せずにコンパイラーを実行することで (例えば、$COMPILER_PATH/bin/cc)、引数のリストをコンソールに出力することができます。

コンパイラー・オプションの比較

以下の表では、GCC と XL C/C++ のコンパイラー・オプションのうち、よく使用されるものを比較しています。

表 5. GCC と XL C/C++ のコンパイラー・オプションのうち、よく使用されるもの
GCC XL C/C++ 説明
-v -v, -V, -# 詳細モードを有効にします。
-p/-profile -p プロファイルを作成するために、コンパイラーが生成するオブジェクト・ファイルをセットアップします。
-m32, -m64 -q32、-q64、または OBJECT_MODE 環境変数を設定 32 ビットまたは 64 ビットのオブジェクトを作成します。
-fsyntax-only -qsyntaxonly オブジェクト・ファイルを生成せずに、構文チェックを実行します。
-fpic -qpic=small 共有ライブラリーで使用するコードを、共有ライブラリーの場所によらないコードとして生成します。XL C/C++ では、グローバル・オフセット・テーブルのサイズは 64 KB 未満です。-qpic を指定して、サブオプションを指定しない場合は、-qpic=small が前提とされます。-qmkshrobj コンパイラー・オプションを指定すると、-qpic オプションが有効になります。
-fPIC -qpic=large 64 KB より大きいグローバル・オフセット・テーブルを使用可能にします。
-pthread -qthreaded または _r 呼び出しモード マルチスレッド環境で実行するプログラムを作成します。
-fno-rtti -qnortti 例外処理用であり、typeid 演算子と dynamic_cast 演算子で使用するための RTTI (実行時型情報) -qrtti の生成を無効にします。XL C/C++ でのデフォルトは、-qnortti です。
-static -qstaticlink このオプションを指定して生成されたオブジェクトは、共有ライブラリーにリンクされません。
-static-libgcc -qstaticlink=libgcc コンパイラーに、静的バージョンの libgcc とリンクするよう命令します。
-shared -qmkshrobj コンパイラーに共有オブジェクトを生成するよう命令します。
-shared-libgcc -qnostaticlink=libgcc コンパイラーに、共有バージョンの libgcc とリンクするよう命令します。
-Wl,-rpath -Wl,-rpath or -R ランタイム・リンカーの検索対象ディレクトリーを指定するために使用する、コロンで区切ったディレクトリーのリストを渡します。
-fno-implicit-templates, -frepo -qtempinc, -qtemplateregistry, -qtemplaterecompile テンプレートをインスタンス化します。
-w -w 警告メッセージを抑止します。
-warn64 long 型から integer 型への変換チェックを有効にします。
-qinfo=< > 情報メッセージを生成します。
-fpack-struct -qalign=bit_packed bit_packed アライメント・ルールを使用します。
-qalign=linuxppc デフォルトの GCC アライメント・ルールを使用して、GCC オブジェクトとの互換性を維持します。これがデフォルトです。
-O,-O2,-O3 -O,-O2,-O3,-O4,-O5 最適化レベルを設定するために使用します。
Ofast, Og Ofast ― 標準に完全に準拠することなく、速さを目的とした最適化を実行します。
Og ― 最適化を実行しますが、必要に応じて効果的なデバッグも実行可能にします。
-mcpu, -mtune -qarch, -qtune, -qcache 特定のプロセッサーを対象とした最適化オプションを設定するために使用します。

GCC による大規模なプログラムのビルド

顧客から、ビルド時にとても巨大なサイズの実行可能ファイルが生成されるようなビルドが求められることは時折あります。このような場合に発生する一般的なエラー・メッセージは、リスト 5 に示すようなメッセージです。

リスト 5. 巨大な実行可能ファイルをビルドする際のエラー・メッセージ
modelfile.cxx.o:(.text+0x212012):
       relocation truncated to fit: 
R_PPC64_TOC16_DS against `.toc'+10000

これは、大規模なプログラムと古い GCC コンパイラーの組み合わせで発生しがちな問題です。古い GCC コンパイラーは、1 つのロード命令による 64 KB の範囲を目次 (TOC) がオーバーフローしないことをオプティミスティックに前提とします。上記の例では、プログラムのサイズが大きいため、TOC に必要な全エントリーの合計が 16 ビット (TOC16_DS) を超えています。

この問題を解決する方法は、2 つあります。

  1. Advance Toolchain 3.0 およびそれ以前のコンパイラーでは、-mminimal-toc を使用して再コンパイルすることができます。
  2. Advance Toolchain 4.0 およびそれ以降のコンパイラーでは、-mcmodel=medium を指定して再コンパイルすることができます。-mcmodel=medium のほうがパフォーマンスに優れていますが、これにはアップグレードが必要になります。

詳細については、GCC の PowerPC オプションを参照してください。

移植手順

計画段階での各ステップを完了した時点で、移植を実行する準備が整います。このセクションでは、アプリケーションを Linux on Power に正常に移植するために推奨される手順を概説します。

  1. ビルド・システムを GNU Make へと移行する (必要な場合)
    これは、1 つまたは複数の makefile を作成するプロセスです。GNU のプログラム・ビルド自動化ユーティリティー (Autoconf、Automake、Buildtool など) を利用して、さまざまな UNIX プラットフォームでのプログラムの移植性を最大限にすることもできます。GNU のプログラム・ビルド自動化ユーティリティーは、.fsf.org/devel/build/ ディレクトリーにあります。
  2. アーキテクチャーに依存するコードを修正する (必要な場合)
    バイト・オーダー (エンディアン方式)、32 ビット・モデルと 64 ビット・モデルでのデータ長、異なる種類のプラットフォームでのデータ・アライメントについて、考慮してください。これらについては、「x86 と Power Architecture のバリエーションとの違いを理解する」セクションで説明しています。
  3. ビルドする
    makefile を作成して、すべてのプログラムを修正すれば、後は make などのコマンドを実行するだけで、ビルド・プロセスは完了です。ビルド・プロセス中にエラーが発生した場合、そのエラーは通常、コンパイラーやリンカーのエラー、あるいはプログラムのシンタックス・エラーです。その場合は、makefile でコンパイラー・オプションを修正するか、コードで問題の原因となっている構文を修正すれば、通常はエラーが修正されます。このフェーズでは、コンパイラー参照メニューおよびプログラミング・ガイドが、最も頼りになります。IBM XL C/C++ については、「IBM XL C/C++ for Linux, Compiler Reference」(compiler.pdf) と「IBM XL C/C++ for Linux, Optimization and Programming Guide」(proguide.pdf) を参照してください。GCC のコンパイル・リファレンスとプログラミング・ガイドは、どちらも gcc.gnu.org/onlinedocs にあります。
  4. テストとトラブルシューティングを行う
    プログラムのビルドが正常に完了した後は、プログラムを実行してランタイム・エラーが発生するかどうかをテストします。ランタイム・エラーは、通常、このフェーズでのプログラム・ロジックに関連します。複数のテスト・プログラムを作成し、アプリケーションの出力が期待通りであるのを確認することは、いつでも賢明なことです。
  5. パフォーマンスのチューニングを行う
    移植したコードが Power プラットフォーム上で実行中になったら、コードのパフォーマンスが期待通りであることをモニターして確認します。期待通りに動作しない場合は、パフォーマンス・チューニングを行う必要があります。以下のツール・スイートを使用すると、アプリケーションのパフォーマンス上の問題を特定し、アプリケーションが Linux カーネルと、どのようなやりとりをしているのかを明らかにすることができます。
    • OProfile
      OProfile ツールは、ハードウェア関連のイベント (キャッシュ・ミスやプロセッサー・サイクルなど) に基づいて、コードのプロファイルを作成します。例えば、OProfile を使用すると、ほとんどのキャッシュ・ミスの原因となっているソース・ルーチンを判別できるようになります。OProfile は、IBM POWER6 や POWER7 をはじめ、多くのプロセッサーに提供されているハードウェア・パフォーマンス・カウンターを利用します。Power Linux 用 OProfile の詳細については、OProfile Webサイト (「参考文献」を参照) にアクセスしてください。
    • ポストリンク最適化 (別名、FDPRpro)
      ポストリンク最適化ツールは、典型的なワークロードにプログラムが使用されている間、プログラムの実行可能イメージを最適化するために、プログラムの動作に関する情報を収集します。その後、プログラムを (収集したプロファイルと一緒に) 再分析し、グローバル最適化 (プログラムの再構築を含む) を適用して、その特定のワークロードを対象に最適化された新しいバージョンのプログラムを作成します。このオプティマイザーによって生成される新規プログラムは、元のプログラムより実行速度が速く、使用する実際のメモリー量も少なくなるのが通常です。詳細については、ポストリンク最適化 Web サイト (「参考文献」を参照) にアクセスしてください。
  6. パッケージ化する
    移植したアプリケーションが商用の製品である場合、またはそのアプリケーションをサード・パーティーがインストールできるように配布する場合には、移植したアプリケーションをライブラリー、ドキュメント、そして場合によってはソース・コードと一緒にパッケージ化する必要があります。Linux では、アプリケーションをパッケージ化するために、.tar ファイル、自己インストール・シェル・スクリプト、RPM などの方法を使用できるようになっています。そのうち、Linux のパッケージ化ツールとして最もよく使われているのは、RPM です。
図 7. 上記の 1 から 6 のステップで説明した移植作業のフロー

まとめ

Linux on Power は、32 ビットと 64 ビット両方のアプリケーション環境とツールチェーンを完備した、エンタープライズ・クラスの Linux 環境を提供します。Linux on Power に対で備わっているコンパイラー・セットにより、オープンソース・コードを容易に移植して、受賞の栄誉に輝いた Power Architecture の高いパフォーマンスを利用することができます。Linux on x86 アプリケーションを Linux on Power に移植することで、これまで Linux オペレーティング・システムにはなかった開発ツールで強化された、Power Architecture のアプリケーション・パフォーマンスを利用することができます。要するに、Linux on Power は、ハイパフォーマンスの Linux アプリケーションをデプロイできる有数のプラットフォームなのです。

謝辞

元の記事を執筆してくださった Calvin Sze 氏、元の記事のテンプレートを作成してレビューに協力してくださった Linda Kinnunen 氏、そしてこの記事の技術的サポートとレビューに協力してくださった IBM Linux on Power チームに感謝いたします。

新しい IBM SDK for Linux on Powerに関して、この記事を更新してくれた Otavio Busatto Pontes 氏に感謝いたします。Linux on Power コミュニティーで、SDK に関するその他の参照先と Wainer dos Santos Moschetta 氏による SDK に関するブログ投稿を調べてください。

IBM SDK for PowerLinux の Migration Advisor に関する最新情報を提供してくださった、Roberto Guimaraes Dutra 氏 (Oliveira/Brazil/IBM@IBMBR) と Leonardo Rangel 氏(Augusto/Brazil/IBM@IBMBR) に感謝いたします。


ダウンロード可能なリソース


関連トピック

  • Linux on Power コミュニティーに参加してください。このコミュニティーは、Linux on Power での移植および開発に必要なもの、知りたい情報がすべてある、ワンストップ・テクニカル・ハブです。
  • ディスカッション・フォーラムに参加してください。
  • アプリケーションが Chiphopper オファリングに適格であるかどうかを調べてください。
  • Linux onIBM Power Systems に関する参考情報を他にも調べてください。
  • POWER8 Facts and Features
  • どの Linux on Power ディストリビューションを使用するかを決める際には、SUSE Linux および Red Hat の Web サイトを参考にしてください。
  • GNU Make に移行してアプリケーションをビルドすることを検討してください。
  • Eclipse テクノロジーをベースにした IBM SDK for Linux on Power の詳細については、IBM の SDK for Linux on Power を参照してください。
  • 最新の GCC および POWER プロセッサーに合わせてチューニングされたライブラリーを活用するには、IBM SDK for PowerLinux を参照してください。
  • Linux on Power 用 OProfile の詳細については、OProfile の Webサイトにアクセスしてください。
  • ポストリンク最適化ツール (別名、FDPRpro) の詳細については、ポストリンク最適化コミュニティーにアクセスしてください。
  • GCC コンパイラー情報の詳細については、GCC コンパイラー・マニュアルを調べてください。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=985145
ArticleTitle=Linux on x86 から Linux on Power へのアプリケーション移植ガイド
publish-date=10092014