Libspeの概要
出典: PS3 Linux Information Site / Cell/B.E.のパワーを体験しよう
English / Japanese
PS3 Linux上では、アプリケーションはlibspe (SPE Runtime Management Library) と呼ばれるライブラリを利用して、Cellの演算用プロセッサである SPEを使用することが出来ます。
2006年11月以降、libspeにはlibspe1系とlibspe2系の 異なるAPIを持つ2つのバージョンが存在しており、 状況がわかりにくくなっています。
このページでは、libspeを使ったPS3(やその他のCellマシン)上のプログラミング環境について、 その状況や概要を簡単に説明します。
libspe 1.x と libspe 2.x
IBMのCell SDKのページやバルセロナスーパーコンピュータセンタ(BSC)のLinux on Cellのサイトでは、2006年頃からlibspeの古いバージョンであるlibspe 1.x系列のSPE開発用ライブラリを公開していました。
これまでに、2006年7月にCell SDK 1.1の一部としてlibspe 1.1が、2006年12月にはCell SDK 2.0の一部としてlibspe 1.2が公開されています。これらのlibspe 1.x系のプログラミング環境は、かなり初期の頃からIBMのCellシミュレータ環境でも使うことができたため、Cell wikiのプログラミングチュートリアルなどで既に試してみたことがあるという人もいるかも知れません。
一方、2007年6月現在である最新版のCell SDK 2.1では、libspe 1.2 は deprecated であるとされ、libspe 2.1という新しいバージョンのlibspeのrpmが収録されています。 libspe 2系のライブラリはこれまでのlibspe 1系のAPIを1から再設計し直したもので、libspe 1.x に比べるとより低レベル(OSによる抽象化に近いレベル)から高レベルまで、幅広いプログラミング要求をカバーするようなAPI設計となっているようです。 現在配布されているlibspe 2.1では、そのうちもっとも基本的なレベル(システムコールに近いレベル)である base 層とその上の event 層のAPIが利用可能となっています。
libspe2 の base API は、libspe1で提供されていたAPIよりやや細粒度のAPIとなっています。 将来的には予定されているようですが、 残念ながら現在公開されているlibspe 2.X系のライブラリではlibspe1互換のAPIは提供されていません。 もちろんlibspe1で書かれたプログラムを同等のlibspe2プログラムに書き換えることは可能です。
今までに公開されてきたCellのサンプルプログラムやプログラミングチュートリアルには libspe1をベースにしたものがまだまだ多く存在しますが、今後は Cell Linuxのプログラミング環境の中心は 徐々に新しい方のバージョンであるlibspe2に移行していくと予想されます。
libspeにおけるSPEの扱い
libspe1では、SPEを使うときの基本的なフローは次のようになっていました:
- spe_open_image: SPEプログラムファイルをオープン
- spe_create_thread: SPEスレッドを生成 (同時にSPEスレッドが実行を開始)
- spe_wait: SPEスレッドの終了待ち (同時にSPEスレッド資源の破棄)
- spe_close_image: SPEプログラムファイルをクローズ
libspe1では、SPEスレッドを生成すると必ず対になるPPEスレッド(pthread)が生成されるため、 SPEスレッドの生成API (spe_create_thread) はすぐに終了し、呼び出したスレッドは続けて他の処理を行うことができます。 従って、複数個のSPEを使う場合も、単純にspe_create_threadを 複数回呼び出せばいいことになります。
一方、libspe2 base層では、次のようなフローでSPEを利用します。
- spe_image_open: SPEプログラムファイルをオープン
- spe_context_create: SPEコンテキストを作成
- spe_program_load: SPE実行イメージをSPEコンテキストのLSにロード
- spe_context_run: SPEコンテキストを実行
- spe_context_destroy: SPEコンテキストの破棄
- spe_image_close: SPEプログラムファイルをクローズ
ここで1つ注意しなければいならないのは、 SPEコンテキストを実行するspe_context_runはブロッキングなAPIであるということです。 つまり、spe_context_runを呼び出すと、SPEプログラムが正常終了あるいは異常終了したり、 (stopシグナルなどで)PPE側に処理を戻す処理が呼び出されたりしない限り、 呼び出し側は先に進みません。
従って、libspe2 のbase層を使って複数のSPEを使う場合、pthreadなどの PPE上のスレッドライブラリと組み合わせてプログラムを書く必要があります。 N個のSPEを使う場合の典型的なフローは次のようになります:
- SPEプログラムファイルをオープン
- N個のSPEコンテキストを作成
- SPE実行イメージをSPEコンテキストのLSにロード
- N個のPPEスレッド(pthreadなど)を作成
- スレッド内でSPEコンテキストを実行
- N個のPPEスレッドが終了するのを待機
- N個のSPEコンテキストを破棄
- SPEプログラムファイルをクローズ
spufs: LinuxにおけるSPEの扱い
ここで、参考までにOS (Linux)においてSPEがどのように抽象化されているのか 簡単に説明しておきましょう。
Linuxでは、SPEはspufsという仮想ファイルシステムとして抽象化されています。 物理的なSPEプロセッサはOS内では仮想化されたSPUコンテキストとして管理されており、 1つのSPUコンテキストがspufsでいう1つの仮想ディレクトリを構成します。 この仮想ディレクトリの下にSPEのメモリ(LS領域)を抽象化する memやmboxを表すmboxなどの仮想ファイルが 作られますが、普通はユーザがこれらの仮想ファイルを直接扱うことはほとんどありません。
SPUコンテキストと物理的なSPEはn対mでマッピングされるため、 ユーザレベルのプログラムは 物理的に利用可能なSPEの数を超えて仮想的なSPEを扱うことが可能です。 このSPUコンテキストとそれに対する操作APIがlibspe2におけるSPEコンテキストと 基本層のAPIにほぼマップされている形となります。
