レベル: 中級 Jonathan Bartlett (johnnyb@eskimo.com), Director of Technology, New Medio
2007年 1月 03日 プログラマーが新たな Cell Broadband Engine™ (Cell BE) プロセッサーを体験して使いこなせるようになるには、Sony® PLAYSTATION® 3 (PS3) が最も簡単で最も安上がりな方法になります。この記事を読んで、話題の全容、そして PS3 に Linux® をインストールして PS3 の Cell BE プロセッサーを対象とした開発に着手する方法を学んでください。
PLAYSTATION 3 が普通のゲーム・コンソールとは違う理由は 2 つあります。まず、従来のどのコンソールと比べても、極めてオープンであるということです。ほとんどのコンソールは考えられる限りの対策をとって、システムで無許可のゲームをプレイできないようにしている一方、PS3 はそれとは正反対に、外部オペレーティング・システムのインストールおよび起動を直接サポートしています。もちろん、ビデオ・アクセラレーションをはじめとしたゲーム関連機能の多くはサード・パーティー・オペレーティング・システムに対して保護されていますが、この連載ではより多目的の科学的アプリケーションに話題を絞ります。
PS3 の実際の目玉的存在はそのプロセッサー、Cell Broadband Engine チップ (よく Cell BE チップと呼ばれます) です。Cell BE アーキテクチャーは従来のプロセッサー設計とは完全に一線を画しています。Cell BE プロセッサーは 9 基の処理要素で構成されたチップです (PS3 ではこのうち 1 基が無効に設定され、さらに 1 基がシステム用の予備となっているため、自由に使えるのは残りの 7 基の処理ユニットとなります)。メインの処理要素は極めて標準的な汎用プロセッサーです。Power Processing Element (略して PPE) と呼ばれるこの要素はデュアル・コア PowerPC® をベースとしています。一方、他の 8 基の処理要素となると話は別です。
Cell BE 内の PPE 以外の要素は Synergistic Processing Element (SPE) として知られるもので、それぞれの SPE は、以下で構成されます。
- Synergistic Processing Unit (SPU) と呼ばれるベクトル・プロセッサー
- SPU に内蔵されたローカル・ストアと呼ばれる専用メモリー域 (PS3 でのサイズは 256K)
- 外部との窓口となる通信チャネル群
- 128 ビット幅×128 のレジスター群 (それぞれのレジスターが通常、32 ビットの値を 4 つ同時に保持するものとして扱われます。)
- SPU のローカル・ストアとメイン・メモリー間の DMA 転送を管理する Memory Flow Controller (MFC)
SPE には、プロセッサーに通常期待する汎用機能のほとんどが欠けています。基本的に、SPE は一般的なオペレーティング・システム・タスクを実行できません。仮想メモリーをサポートすることも、コンピューターの RAM に直接アクセスすることも不可能で、割り込みサポートは極度に限られています。SPE はあくまでも、データを可能な限り高速処理することに特化されているためです。
つまり、PPE はリソース・マネージャーとして機能し、SPE はデータ演算装置として機能します。PPE 上のプログラムはタスクをそれぞれの SPE に分配して実行し、SPE 間でデータのやり取りが行われます。
各 SPE、PPE、そしてメイン・メモリー・コントローラーをすべて繋げたものが、Element Interconnect Bus (EIB) と呼ばれるバスです。これが、データが行き来する主要な経路となります。
この設計で最も驚くべきことは、SPE の 256Kというローカル・ストアがキャッシュではないというところにあります。この数値は実際には、SPE がプログラムとデータを一度に処理しなければならないメモリー量の合計です。これは不利なように思えますが、実は以下のように有利な点がいくつかあります。
- メイン・メモリーへのアクセスに比べ、ローカル・ストア・メモリーへのアクセスが極めて高速であること。
- ローカル・ストア・メモリーへのアクセスをクロック・サイクルまで予測できること。
- メイン・メモリーでのデータの出し入れを非同期で要求し、前もって予測できること。
基本的には、すべてキャッシュの速度に関する利点ですが、プログラムはローカル・ストアを直接かつ明示的に使用するため、ローカル・ストアの管理という点では遥かに賢い方法になるはずです。つまり、必要になる前にデータのロードを要求し、データがロードされるのを待っている間に他のタスクに移って実行することができるのです。
Cell BE プロセッサーは特殊化したハードウェアでは前から使われていましたが、手頃な価格ですぐに入手できる Cell BE ベースのデバイスとしては、PS3 が初めてです。さらに、Linux を使えば誰でもプログラミングできます。
Linux を実行するようにさせるまでの手順
外部オペレーティング・システムをインストールできるのは、ゲーム・コンソールとしては珍しいことです。コンソールは乱売されるのが一般的であるため、通常はコンソール開発者にパブリッシャーがロイヤルティーを払わないとゲームを実行できないようにされています。それに反して Sony が決定したことは、PS3 コンソールを多少開放し、アクセラレーテッド・グラフィックスを使用してはならないという警告付きで、サード・パーティー・オペレーティング・システムのインストールを許可することです。
この決定により、PS3 に Linux をインストールできるようになりました。多少の試練を乗り越えなければなりませんが、インストールできることは確実です。Terra Soft Solutions は、Sony と協力して PS3 専用の Yellow Dog Linux 5 を開発しました。さらに、これを PS3 で使用するためのサポートも提供しています。これは未だかつて、他の配布には類を見ないことです。Yellow Dog Linux (YDL) は当初から PowerPC ベース専用の配布だったので、次のバージョンの YDL を PS3 専用として開発するよう Sony が契約したのも当然の成り行きでした。
YDL 5 の初期リリースを PS3 にインストールする手順については、この先を読んでください。
PS3 の準備
Linux をインストールするには、以下のハードウェアを追加する必要があります。
- ディスプレイおよび対応するケーブル
- USB キーボード
- USB マウス
- USB フラッシュ・ドライブ
ディスプレイではいくつかの注意事項があります。まず第一に、20GB の PS3 には、TV のような出力装置との接続用としてアナログのコンポジット RCA プラグしか付属していません。これは特殊ケーブルを使って VGA に変換できます (詳細は、「参考文献」を参照)。ただし動作は 576x384 に限定されます。これより高い解像度が必要な場合は HDMI ポートを使用しなければなりませんが、そうすると別の問題が持ち上がります。HDMI はケーブルで DVI に簡単に変換できるので DVI 互換モニターに入力できると思いがちですが、そういうわけにはいきません。HDCP と呼ばれるコンテンツ保護プロトコルがあるためです。データを HDMI ポートに出力すると、PS3 は HDCP 互換装置以外にはデータを出力しません。そのためモニターが HDCP 互換でない限り、PS3 からのデジタル出力を受信できないばかりか、解像度も 576x384 どまりです (ただし、コンポジットではなく、コンポーネント・ビデオ出力を使って解像度を上げたというレポートもあります)。
PLAYSTATION 3 を準備するには、以下のステップに従ってください。
- イーサネット・ケーブルを PS3 に接続します。ネットワークに DHCP サーバーがあることを確認してください。
- 工場から出荷された状態の PS3 の場合は、最初のブート時に表示されるプロンプトに従ってセットアップ手順を行います。この手順には、PS3 システムの言語、時間、ユーザー名の設定が含まれます。
-
Settings、System Settings の順に進み、Format Utility を選択します。
-
Format Hard Disk を選択し、選択した内容を 2 回確認します。
-
Custom パーティショニング方式の使用を選択します。
-
Allot 10GB to the Other OS の使用を選択します。これによって、自動的に残りのディスク・スペースが PS3 のゲーム・オペレーティング・システム用に確保されます。選択し終わると、システムが再起動します。
- システムが再起動したら、Settings、System Update の順に進みます。
-
Update via Internet を選択します。
- システム更新の画面に従って、最新のシステム更新をダウンロードしてインストールします。一部の画面にはキャンセル・ボタンだけが表示され、次の画面に進む方法が説明されていません。この場合、次の画面に先に進むには、コントローラーの X ボタンを使います。
- PS3 が再起動したら、Linux をインストールする準備は完了です。
インストールの準備
今度は、Linux 側を準備する番です。インストールの準備をするために、ご使用のコンピューター (PS3 ではありません) で行う手順は以下のとおりです。
- YDL 5 DVD ISO をダウンロードして DVD に焼きます。CD インストールはありません。PS3 が対応するのは DVD のみです。
- Sony から PS3 OtherOS インストーラーをダウンロードして (「参考文献」を参照)、otheros.self という名前を付けて保存します。このファイルを PS3 ゲーム・オペレーティング・システムで実行して、外部ブート・ローダーをインストールすることになります。
- Terra Soft から YDL ブート・ローダーをダウンロードして (「参考文献」を参照)、otheros.bld という名前を付けて保存します。これが、Sony インストーラーがインストールするブート・ローダーです。
- USB フラッシュ・ドライブをコンピューターに挿入します。
- フラッシュ・ドライブの最上位レベルに、PS3 というディレクトリーを作成します。PS3 ディレクトリーの直下に別のディレクトリーを作成して otheros という名前を付けます。
- ダウンロードした 2 つのファイル、otheros.self と otheros.bld をフラッシュ・ドライブに作成した PS3/otheros ディレクトリーにコピーします。
次は、いよいよインストールに取り掛かります。
インストールの実行
PS3 で以下の手順を行って、Linux をインストールします。
- フラッシュ・ドライブをコンピューターから取り外して PS3 に挿入します。
-
Settings、System Settings の順に進み、Install Other OS を選択します。
- インストーラーの場所を確認し、画面に従ってインストール・プロセスを行います。このインストーラーがインストールするのはブート・ローダーだけで、オペレーティング・システムはインストールされないことに注意してください。
- インストーラーが完了したら、Settings、System Settings の順に進み、Default System を選択します。次に Other OS を選択して、X ボタンを押します。
- YDL 5 DVD を挿入します。
- USB キーボードとマウスを接続します。
- ここでシステムを再起動します。それには、コントローラーの PS ボタンを押し続けて Turn off the system を選択するか、または電源ボタンを 5 秒間押します。電源が切れたら、システムの電源を入れてください。
- システムが再起動すると、Linux がブート中であるように見えます。このブート・ローダーは実際には、必要最小限のものを備えた kboot と呼ばれる Linux カーネルだからです。
- kboot: プロンプトが表示されたら、HDMI ポート経由で出力する場合は install と入力し、アナログの場合は installtext と入力します。ここから先の手順では installtext オプションが使用されていることを前提としますが、違いはほとんどありません。
- メディア検証の後、画面の青色の領域に Traceback エラーと表示される場合があります。このエラーは無視して、インストール画面に進んでください。
- パーティショニングに関する質問が表示されても、これによって PS3 ゲーム・オペレーティング・システムが消去される心配はありません。PS3 の Other OS モードでは、ゲスト・オペレーティング・システムに公開されるのは、ドライブで割り当てられた独自の部分だけです。下位レベルのユーティリティーでさえも、ドライブの他の部分は見ることができません。躊躇せずに、YDL がドライブ上のすべてのデータを消去するのを許可し、次にすべてのパーティションを除去してデフォルト・レイアウトを作成するのを許可してください。
- パッケージをインストールする段階では、インストールが完了するまで約 1 時間かかります。ただし、DVD 全体がインストールされるわけではありません。
- アナログ出力を使用している場合、システムがリブートする際に kboot: ブート・プロンプトで ydl480i と入力します。それ以外の場合は、アナログ出力では対応できない解像度に出力を変更することになります。
- システムがブートするとセットアップ・ツールが表示されますが、操作は必要ありません。何もしなければ、タイムアウトしてブート・プロセスが完了します。
これで手順は完了です。YDL 5 が PS3 にインストールされました。
インストール後のセットアップ
残念ながら、インストール・プログラムはすべての詳細を設定してはくれません。特に、アナログ・ディスプレイの場合はなおさらです。適切な解像度での自動ブート、アナログ・デバイスでの X Window System 構成、Cell BE SDK のインストールなどが必要な場合には、いくつかの手順を踏まなければなりません。それにはいずれの場合にしても、YDL 5 DVD がドライブに入っていることを確認して、以下のようにマウントしてください。
以下の手順では一貫して、インストール DVD が上記のようにマウントされていること、そしてルートとしてログインしていることを前提とします。
アナログ・システムを起動時に適切な解像度でブートさせるには、/etc/kboot.conf ファイルを編集して default=ydl という行を default=ydl480i に変更し、ファイルを保存します。
アナログ・デバイスに対応した X Window System を構成するには、Xautoconfig パッケージをインストールして以下のように実行します。
rpm -i /mnt/YellowDog/RPMS/Xautoconfig-*
Xautoconfig
|
これで、startx を実行すると X Window System が起動するようになりますが、アナログ・デバイスでは画面が非常に小さいという難点があります。そのような小さい画面のデバイスに対処するヒントとして、Alt キーと左のマウス・ボタンを同時に押したままにすると、タイトル・バーが見えなくてもデスクトップ上で画面を自由にドラッグできます。
システム起動時にグラフィカル・ログインを表示するには、/etc/inittab ファイルを編集します。id:3:initdefault: という行を id:5:initdefault: に変更してファイルを保存してください。これでシステムをリブートすると、グラフィカル・ログインが表示されるようになります。リブートした後には、残りの手順のために、上記のように DVD をマウントするのを忘れないでください。Nautilus は実際には別の場所に DVD をマウントします。Nautilus を使用すると、DVD は /mnt ではなく /media/CDROM にマウントされます。
今度は Cell BE SDK V2.0 をインストールします。インストーラーによってすでにインストールされているかどうかを調べるには、which spu-gcc を実行するだけで十分です。プログラムが検出されなかったら、SDK はインストールされていないということになります。SDK をインストールするには、以下を実行します。
cd /mnt/YellowDog/RPMS
rpm -i spu-binutils-* spu-gcc-* spu-gdb-* spu-utils* libspe-devel-*
|
ただし、この DVD には重要なパッケージのセット (libspe の64 ビット・バージョン) が含まれていません。これを修正するのは簡単で、ソース DVD または Web サイトから libspe の SRPM (libspe-1.1.0-1.src.rpm という名前) をダウンロードしてください。次に、ダウンロード先のディレクトリーに進んで以下の手順を行います。
以上の手順で YDL 5 のインストールと構成が完了し、準備万端となりました。
rpm -i libspe-*.src.rpm
cd /usr/src/yellowdog/SPECS
rpmbuild -bb --target ppc64 libspe.spec
cd ../RPMS/ppc64
rpm -i elfspe-* libspe-*
|
万が一、PS3 でゲームを楽しみたいという場合にゲーム・オペレーティング・システムに戻るにはどうしたらいいかと心配している読者もいることでしょう。それには、kboot: プロンプトあるいはコマンド・ラインで boot-game-os を実行します。何らかの理由で Linux にエラーが発生した場合は、PS3 の電源を切った後、電源を入れるときに電源ボタンを 5 秒間押すと (ビープ音が鳴るまで)、ゲーム・オペレーティング・システムをロードできます。いずれの方法でもゲーム・オペレーティング・システムはロードされますが、デフォルト・システムまでゲーム・オペレーティング・システムに設定されてしまいます。再び Linux にブートするには、設定に戻り、デフォルトで Other OS がブートされるように設定する必要があります。
Linux をインストールしたところで、次に学ぶこと
Linux と Cell BE SDK は完全にインストールされたので、この連載ではこの後、プログラミング方法と使用方法に話題を移します。ここで予告編として短い初歩的なプログラムを見てみましょう。C 言語で作成されたこのプログラムは、以下の PPE と SPE の両方を使用します。
このプログラムがどのように機能するかを説明する前に、Cell BE プログラムの作成に使用する一般的なツールをいくつか紹介します。
-
gcc
信頼できるコンパイラーで、PPE に対応した PPC Linux バイナリーの生成用として作成されています。-m64 スイッチを使用して 64 ビットの実行可能プログラムを生成します。
-
spu-gcc
同じく信頼できるコンパイラーですが、こちらのツールは SPE 用のコードを生成します。
-
embedspu
SPE プログラムを PPE 実行可能ファイルにリンク可能なオブジェクト・ファイルに変換する特殊なツールです。また、SPE プログラムを参照するグローバル変数を作成して、PPE がプログラムを SPE にロードし、必要に応じて実行できるようにします。64 ビットの PPC プログラムに組み込むには、-m64 フラグを使用してください。
SPE を抜きにすると、Cell BE プロセッサーは基本的に他の PowerPC ベース・システムと同じようにプログラムされています。実際、SPE が存在しないかのごとく装っても、コードは正常に機能するはずです。ただし、その場合は演算能力の大部分が活用されないままになってしまいます。SPE を生かすには、もう少しの工夫が必要です。
Cell BE 技術の初心者が念頭に置いておかなければならないのは、PPE はシステムのリソース・マネージャーであるということです。PPE はオペレーティング・システムのタスクを処理し、メモリーへのアクセスを規制し、SPE を制御します。PPE 用のコードはプログラムの初期化、タスクでの 1 つ以上の SPE のセットアップ、そして入出力の実行を処理します。もちろん PPE は処理タスクも実行できますが、通常重点が置かれるのは、SPE に適切なリソースを確保することです。
それでは、SPE で処理タスクを実行する単純なプログラムがどのように構成されているかを見てみましょう。このプログラムは極めて初歩的なもので、一定の速度 (1 時間当たりのマイル数) と時間 (時間単位) に基づく移動距離を計算します。PPE 用のコードは以下のとおりです (ppe_distance.c として入力)。
リスト 1. 方程式の解を求める PPE コード
#include <stdio.h>
#include <libspe.h>
//This global is for the SPE program code itself. It will be created by
//the embedspu program.
extern spe_program_handle_t calculate_distance_handle;
//This struct is used for input/output with the SPE task
typedef struct {
float speed; //input parameter
float num_hours; //input parameter
float distance; //output parameter
float padding; //pad the struct a multiple of 16 bytes
} program_data;
int main() {
program_data pd __attribute__((aligned(16))); //aligned for transfer
//GATHER DATA TO SEND TO SPE
printf("Enter the speed at which your car is travelling in miles/hr: ");
scanf("%f", &pd.speed);
printf("Enter the number of hours you have been driving at that speed: ");
scanf("%f", &pd.num_hours);
//USE THE SPE TO PROCESS THE DATA
//Create SPE Task
speid_t spe_id = spe_create_thread(0, &calculate_distance_handle, &pd, NULL,
-1, 0);
//Check For Errors
if(spe_id == 0) {
fprintf(stderr, "Error creating SPE thread!\n");
return 1;
}
//Wait For Completion
spe_wait(spe_id, NULL, 0);
//FORMAT THE RESULTS FOR DISPLAY
printf("The distance travelled is %f miles.\n", pd.distance);
return 0;
}
|
前にも述べたように、Cell BE プロセッサー内での PPE の主要なジョブは、入出力タスクを処理することです。上記のリストで唯一興味深い部分は spe_create_thread で、最初のパラメーターはスレッド・グループ ID (ゼロは、スレッドに新規グループを作成することを示します)、2 番目のパラメーターは SPE プログラムに対するハンドル、3 番目のパラメーターは転送するデータへのポインター、4 番目のパラメーターはオプションの環境ポインター、5 番目のパラメーターはプログラムを実行させる SPE のマスク (-1 は、利用可能な任意の SPE を示します)、そして最後のパラメーターは使用するオプションのリストです (この場合はオプションを使用していません)。この関数が返す SPE タスクの ID 番号を spe_wait へのパラメーターとして使用します。spe_wait は SPE タスクが終了するとリターンします。
SPE 用のコードは以下のとおりです (spe_distance.c として入力)。
リスト 2. SPE の計算例
//Pull in DMA commands
#include <spu_mfcio.h>
//Struct for communication with the PPE
typedef struct {
float speed; //input parameter
float num_hours; //input parameter
float distance; //output parameter
float padding; //pad the struct a multiple of 16 bytes
} program_data;
int main(unsigned long long spe_id, unsigned long long program_data_ea, unsigned
long long env) {
program_data pd __attribute__((aligned(16)));
int tag_id = 0;
//READ DATA IN
//Initiate copy
mfc_get(&pd, program_data_ea, sizeof(pd), tag_id, 0, 0);
//Wait for completion
mfc_write_tag_mask(1<<tag_id);
mfc_read_tag_status_any();
//PROCESS DATA
pd.distance = pd.speed * pd.num_hours;
//WRITE RESULTS OUT
//Initiate copy
mfc_put(&pd, program_data_ea, sizeof(program_data), tag_id, 0, 0);
//Wait for completion
mfc_write_tag_mask(1<<tag_id);
mfc_read_tag_status_any();
return 0;
}
|
SPU プログラムについては、今後の記事でより詳しく検討していきますが、実行内容をここで簡単に説明すると、spe_create_thread への 3 番目のパラメーターとして渡されたポインターが、このプログラムに program_data_ea として入力されます。EA は実効アドレス (Effective Address) を表します。これがつまり、主要な PPE プログラムから見たメイン・メモリー・アドレスです。SPE はメイン・メモリーに直接アクセスしないので、この EA をポインターとして逆参照することはできません。そのため、代わりに転送要求を開始して、データをローカル・ストアにコピーします。データがローカル・ストアに入れば、ローカル・ストア・アドレス (LSA) によって、そのデータにアクセスできるようになります。
mfc_get はローカル・ストアへの転送を開始します。PPE と SPE の両方で、struct が 16 バイトに揃えられ、16 バイトになるようにパディングが行われていることに注意してください。これについては今後の記事で詳細を説明しますが、DMA が転送する大部分は 16 バイト境界に揃え、16 バイトの倍数と等しくしなければなりません。DMA 操作の状況を検索するには、tag_id を使います。転送後の次の 2 つの関数によって、プログラムは転送が完了するまで待機します。
メインの処理は明らかに単純なもので、速度と時間を乗算するだけです。データが処理されると、mfc_put がメイン・メモリーへの転送を開始し、次の 2 つの関数によって DMA が完了するまで待機されられます。すべてが完了すると、プログラムが終了します。
ここでプログラムをコンパイルして実行しますが、以下を見るとわかるように、その手順は非常に単純です。
#Compile the SPE program
spu-gcc spe_distance.c -o spe_distance
#Embed the SPE program into an ELF object file, and expose it
#through the global variable: calculate_distance_handle
embedspu calculate_distance_handle spe_distance spe_distance_csf.o
#Compile the PPE program together with the SPE program
gcc ppe_distance.c spe_distance_csf.o -lspe -o distance
#Run the program
./distance
|
これで手順は完了です。完全に機能する Cell BE プログラムの出来上がりです。
まとめ
PS3 を直接プログラミングすることはできませんが、サード・パーティー・オペレーティング・システムのサポートにより、PS3 に Linux をインストールできます。PS3 に Linux をインストールするには多少の努力が必要ですが、最終的には低価格で完全に機能する Cell Broadband Engine プロセッサーを実現できます。この連載の今後の記事では、Cell BE のプログラミング方法、そして SPE から可能な限りの最高速度を引き出す方法を詳しく説明します。
参考文献
著者について
記事の評価
|