parallella触ろう #00
こんにちは。Sakamotoです。
ついに、ポータブルスーパーコンピュータと呼ばれて久しいParallellaが
国内でも容易に入手可能になりました。
Parallellaって何?って方は、PC Watchさんの記事をご覧いただければ
http://pc.watch.impress.co.jp/docs/news/20141110_675205.html
その凄さもそこはかとなく伝わるのではないでしょうか
というわけでParallellaをいじってみることにします。
公式サイト(http://www.parallella.org)
ドキュメント(http://www.parallella.org/board/)
サンプル(https://github.com/adapteva/epiphany-examples/)
まずはざっくりとしたアーキテクチャの解説ですが、たぶんすでにこの手のものはあらゆるところで解説されつくしているので、超絶ざっくりと
- Cortex A9 Dual-Core
- Epiphany-III 16-Core
- Zynq 7010
と、これだけで、ARM, 独自アーキテクチャのRISCプロセッサ、FPGAの3つの開発環境があるという、あそびがいのあるボードになっています
主にEpiphany-III(以下Epiphany)を触っていくつもりでいますが、FPGA部分のZynqとかは誰かがやってくれるんじゃないでしょうか(ブン投げ
Hello world
https://github.com/adapteva/epiphany-examples/tree/2014.11/apps/hello-world
このHello worldは基本的なEpiphanyの使い方のエッセンスが含まれています
# ただしいくつか気になるところが…
というわけでソースコードを追いかけていきます
Epiphanyの初期化
Epiphanyは基本的に、ホストプロセッサの処理の一部をEpiphanyで実行するというプログラミングモデルを取ります
一昔前で言えばCell/B.E.が一番近い?プロセッサです
まず、ホストプロセッサ上からEpiphanyの初期化を行います
e_init関数がEpiphanyの初期化を担当する関数です
e_platform_t platform;
e_init(NULL);
e_reset_system();
e_get_platform_info(&platform);
e_get_platform_info関数で、Epiphanyの情報がe_platform_t構造体に格納されます
Epiphany上のメモリ確保
Epiphanyのメモリ空間はホストと独立しており、双方でデータのやり取りをするためには、データをやり取りできる場所を作ってあげる必要があります。
それを行っているのが以下です
e_mem_t emem;
char emsg[_BufSize];
e_alloc(&emem, _BufOffset, _BufSize);
OpenCLをご存じの方は、OpenCLのメモリオブジェクトをイメージしてもらえれば。アレとほぼ同等のイメージです
eCoreのオープン
EpiphanyがCell/B.E.と似ているというのはこの挙動だったりします(あと、XeonPhiもそうかも
Cell/B.E.では、1つのホストプロセッサに、8つのSPEと呼ばれるコプロセッサがぶら下がっており、それぞれのSPEに対して、別々のプログラムをロードすることが可能でした
Epiphanyも同様に、各コアに対して異なるプログラムをロードすることができます
そのためのEpiphanyコア(eCore)の起動とプログラムのロードを行っているのが以下です
e_epiphany_t dev;
e_open(&dev, row, col, 1, 1);
e_reset_group(&dev);
e_load("e_hello_world.srec", &dev, 0, 0, E_TRUE);
e_open関数でeCoreに対して起動を指示します。第2~5引数は、起動する個数を指定していますが、これについては後程別項で解説します
起動したeCoreについての情報は、第1引数のe_epiphany_t構造体に格納されます。
続いて、起動したeCoreに対して、e_loadでプログラムの読み込みを行います。
ここで読み込まれたプログラムが転送され、めでたくeCoreで処理がスタートします
終了待ちとデータの読み込みとeCoreの解放
さて、起動したはいいものの、じゃあどうやって終了を待つかといえば
usleep(10000);
そして燦然と輝くusleep...!
現状のSDK(Ver 5.xx系)では、終了通知については提供されていません
なので、ユーザー側でどうにかする必要がありますが、この方法についてはまた別項にて。
Epiphany側からデータを読むには、e_read関数を使用します。
e_read(&emem, 0, 0, 0x0, emsg, _BufSize);
先ほどe_alloc関数で作成したメモリ領域から、第6引数サイズを読み込み、第5引数の領域に書き込みます。
このe_alloc関数は、第1引数に与えるものによって挙動が変わるのですが、それはまた別の機会に
# さっきから別の機会多いな
終了してデータを読み終わったら、eCoreの役目は終了です。
eCoreは忘れずに解放してあげましょう
e_close(&dev);
Epiphany上のメモリ解放とEpiphanyの解放
全てが終わったら、ちゃんともろもろを解放してあげましょう
e_free(&emem);
e_finalize();
このようにしてあげることで、確保したメモリが解放されます。またe_finalize関数でEpiphanyとの接続が終了します
eCore上のコードについては特に語るべきこともないぐらいシンプルに、バッファにHello worldって書いてるだけなので割愛!
という風に一から追いかけてみましたが、このHello worldにはいくつか気になる点があります
次回は、その気になる点に触れつつ、Epiphanyのアーキテクチャについてももう少し掘り下げて行こうと思います。
Discussion