SPU code overlay take.1-CELLプロセッサ
Cell SDK 2.0 に追加された SPU code overlays を...
Cell SDK 2.0 に追加された SPU code overlays を試してみました。この機 能の説明は cd image (CellSDK20.iso) の pdf/cpbprg00.pdf - "Software Development Kit 2.0 Programmer's Guide Version 1.0" Chapter 4. SPU code overlays にあります。
overlay 機能の概要
詳細は上記を参照ですが、基本的には、linker script の変更のみで overlay 機能を使用することが可能です。overlay 実現に必要なものは linker が実行バイナリ作成時に自動的に追加してくれます。
overlay するためには、関数の実体がどの section にあるか?や、いつ section を入れ換えるか?を管理する必要があり、linker の手助けなしにやろう とすると結構手間がかかるのですが、linker script を変更するだけでよいとい うことになると、手軽にいろいろな構成が試せるので、ハマればかなり強力な機 能だと思います。
overlay 機能を使用する場合の linker script の変更点
以下の default で使用される linker script と、overlay 機能のサンプル (simple) で使用される linker script の diff を見てもらえば一目瞭然ですが、 OVERLAY 出力 section の追加と、overlay 対象の入力 section の移動を行うだ けです。
$ diff -u /opt/cell/toolchain-3.3/spu/lib/ldscripts/elf32_spu.x \
/opt/ibm/cell-sdk/prototype/src/samples/overlay/simple/spu_olay/ld.script
--- /opt/cell/toolchain-3.3/spu/lib/ldscripts/elf32_spu.x
+++ sdk-2.0_overlay/simple/spu_olay/ld.script
@@ -3,7 +3,7 @@
"elf32-spu")
OUTPUT_ARCH(spu)
ENTRY(_start)
-SEARCH_DIR("=/usr/spu/lib");
+SEARCH_DIR("/opt/cell/toolchain-3.3/spu/spu/lib");
/* Do we need any of these for elf?
__DYNAMIC = 0; */
SECTIONS
@@ -51,12 +51,17 @@
.plt : { *(.plt) }
.text :
{
- *(.text .stub .text.* .gnu.linkonce.t.*)
+ *( EXCLUDE_FILE(olay1/*.o olay2/*.o) .text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
*(.spu.elf)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0
+ OVERLAY :
+ {
+ .segment1 {olay1/*.o(.text)}
+ .segment2 {olay2/*.o(.text)}
+ }
.fini :
{
KEEP (*(.fini))
@@ -180,7 +185,6 @@
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
- .note.spu_name 0 : { *(.note.spu_name) }
PROVIDE (__stack = 0x3fff0);
/DISCARD/ : { *(.note.GNU-stack) }
}
いろいろ試す
用意されたサンプルをただ実行してもしょうがないので、変更を加えて、以 下のことができるか確かめてみました。もとのサンプルは overview を使用して います。
overview には se.o が overlay されないバグがありますが、これも修正し ています。
overlay region 間をピンポンする関数呼び出し
ここでピンポンとは、ある region (reg A) の segment (seg A1) にある関 数 (func A1) から他の region (reg B) にある関数 (func B) が呼ばれた場合に、 func B から reg A の seg A1 と異なる segment (seg A2) にある関数 (func A2) を呼ぶことです。
これが出来ると overlay の自由度はかなり高まります。
今回は、sj.c 内に sj() という関数を作成し、 sf() [reg 2, seg 3] -> sh() [reg 3, seg 5] -> sj() [reg 2, seg 7] という 順番で呼び出しを行っています。
data section の overlay
C 言語 (それとも OS のプロセス空間?) の規格的には、全ての data は全 ての text から参照可能になっている必要がありますが、運用として、あるdata はある関数からしか参照しないようにすることは可能であり、overlay 対象とし て考えられるため、実現できるか確かめてみました。
ただし、const でない場合や、overlay region 間をピンポンする関数呼び出 し を考慮すると、適用はよく考えないとハマることになります。それでもローカ ル変数や、malloc で確保している領域を含めて overlay を検討すると LS は有 効活用できます。(例えば、同じ region に入れる segment のサイズに差があ り、この差で data が吸収できる場合)
今回は、sj.c で static char 型の配列 (.data)、static const char の文 字列 (.rodata) を定義して、text と同じ segment に入れています。ついでに 例として、文字列を書き換えても反映されないバグも入れています。
実行結果
以下のように sj() も実行され、message (Hello World!) もきちんと表示 されているようです。
また、上記のバグは 2 回目の message は "modified!" と表示されるよう に書き換えているのにそれが変更されていないことを指しています。
$ ./overlay_overview Entering main sa prints 97 sb prints 98 sc prints 100100099 sd prints 200200100 se prints 200200101 succeeded! expecting 101, got 101 succeeded! expecting 100, got 100 sf prints 200300102 sh prints 300500104 sj prints 300600106 sj overlay message: Hello World! succeeded! expecting 106, got 106 succeeded! expecting 104, got 104 si prints 300600105 succeeded! expecting 105, got 105 succeeded! expecting 102, got 102 succeeded! expecting 99, got 99 sg prints 100400103 sh prints 300500104 sj prints 300600106 sj overlay message: Hello World! succeeded! expecting 106, got 106 succeeded! expecting 104, got 104 si prints 300600105 succeeded! expecting 105, got 105 succeeded! expecting 103, got 103 succeeded! expecting 98, got 98 succeeded! expecting 97, got 97 Exiting main, status=0



