Written by noda
Intel FPGA SDK for OpenClを使ってArria10上に回路を高位合成するときのメモ。
このメモを読めばArria10上で簡単な足し算コードが実行できます。
kernelコードのコンパイルに数時間要するので注意されたし。
このメモは半分nodaの備忘録なので、以下のリファレンスも参照して下さいませ。
https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_getting_started.pdf
https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_programming_guide.pdf
いろいろと忘れかけているので追加することあれば書き加えて下さいまし。
Arria10SoCは、Intel社が提供するARMとFPGAのSoCである。float演算用のハードマクロ(DSP)がArria10の売りである。これは業界で初らしい。このDSPはdouble演算には対応していないので注意。
OpenClはヘテロな環境(CPU+GPUとかCPU+FPGAとか)で並列計算を行うためのフレームワークである。Intel FPGA SDK for OpenCLは、Inrel社が提供するFPGA向けOpenCLベース高位合成環境であり、これを用いれば短期間で高性能なFPGA回路の記述が可能であるとされる(??)。
OpenCLではhostコードとkernelコードの2種類を用いる。前者は制御用プロセッサ(今回ならARM on Arria10SoC)のためのコードで、C++とOpenCL APIを使用して記述する。後者は演算用プロセッサ(今回ならFPGA on Arria10SoC)のふるまいを記述するコードで、OpenCL C言語を使用する。
この高位合成環境では、ボード依存のBoard Support Package(BSP)が提供されているため、ユーザはCPU-FPGA間のI/Oなどの周辺インターフェースの開発をする必要がない。このBSPを書き換えればいろんことが出来るらしいが、前に変なところを書き換えて動作しなくなったことがあったので、触らない方が無難。それか、ちゃんとバックアップを取ってチャレンジ。
以下は手順どおりに手を動かしながら読み進めると理解できる(はず)。
サンプルの足し算コードは、以下のディレクトリに置いた。
/home/asap2/noda/arria_test
中にはcommonとaddという2つのディレクトリがある。コードはaddの方で、commonがないと動かない。各自arria_testごとコピーしてaddへ移動。以下、カレントディレクトリがaddとして話を進める。
hostコードはhost/src/main.cpp、kernelコードはdevice/add.clにある。その他秘伝のシェルコードがある。
このコードは、ランダムに生成した100要素をひたすら足して集約するコードである。演算が正しく行われたかを確かめるために、CPU上で計算した結果とFPGA上で計算した結果を突合せている。また、kernelの計算時間及びhostとの通信時間含めた実行時間を計測している。hostコードはとても見づらいと思う、スマン、、
また、のちにArria10へsshおよびscpするが、その前にあなたの.ssh/id_rsa.pubをArria10のauthorized_keysにぶち込まねばならない。noda@..にパブリックキーを添えてメールをくれれば追加する。
さて、いきなりFPGAに落とすのはつらいので、まずはneutrino上でエミュレーション(動作確認)を行う。そののちにコンパイルして実機に焼く。
始めに、ssh neutrinoした後に~noda/.bash_profileをコピーしてsourceする。
これでPATHは通ったので、エミュレーションしてみる。add下にemu_goというシェルコードがあるので、それを叩けばエミュレーションが始まる。
様々なコンパイルオプションがある。詳しくはリファレンスを参照。
実行結果は以下のような感じ。
bash-4.1$ ./emu_go aoc: Environment checks are completed successfully. You are now compiling the full flow!! aoc: Selected target board a10soc_2ddr aoc: Running OpenCL parser.... aoc: OpenCL parser completed successfully. aoc: Compiling for Emulation .... aoc: Emulator Compilation completed successfully. Emulator flow is successful. To execute emulated kernel, invoke host with env CL_CONTEXT_EMULATOR_DEVICE_ALTERA=1 <host_program> For multi device emulations replace the 1 with the number of devices you which to emulate Initializing OpenCL Platform: Altera SDK for OpenCL Using 1 device(s) EmulatorDevice : Emulated Device Using AOCX: add.aocx Arria 10 SoC Turn_around_Time: 0.712237 ms Kernel time (device 0)(getStartEndTime): 0.619050 ms Output: 93.649620 Reference: 93.649620 Verification: PASS
これで、hostコードが起動してからkernelコードを呼び出して終了するまでの一連の流れをCPU上で確認できる。ちゃんと動いてくれるまで頑張ってhostとkernelのデバッグをする。
動作確認はできるが、実行時間はシミュレーションできない(値は出てくるけどたぶん適当な値)。実行時間はFPGAで実際に動かして計測するしかない。
また、FPGAリソース使用率の確認も行う。device下のemu_resourceを叩く。リソースもここで調整する。実行結果は以下。
bash-4.1$ cd device/ bash-4.1$ ./emu_resource aoc: Environment checks are completed successfully. aoc: Selected target board a10soc_2ddr aoc: Running OpenCL parser.... aoc: OpenCL parser completed successfully. aoc: Compiling.... aoc: Linking with IP library ... +--------------------------------------------------------------------+ ; Estimated Resource Usage Summary ; +----------------------------------------+---------------------------+ ; Resource + Usage ; +----------------------------------------+---------------------------+ ; Logic utilization ; 2% ; ; ALUTs ; 1% ; ; Dedicated logic registers ; 1% ; ; Memory blocks ; 3% ; ; DSP blocks ; 0% ; +----------------------------------------+---------------------------; aoc: First stage compilation completed successfully. aoc: To compile this project, run "aoc add.aoco"
float演算であれば勝手にDSPを使ってくれる。上は0%と書いてあるが回路規模が小さすぎるだけでちゃんと使われてるっぽい。 さて、サンプルの足し算はちゃんと動いたので、次へ進む。
まずはaocx_goというシェルを叩いてkernelコードのコンパイルをする。これが絶望的なくらいに時間がかかる。このサンプルコードでも2時間くらいかかる。hostコードのコンパイルはArria10上のARMで行うので放置。
実行結果はこんな感じ。
bash-4.1$ ./aocx_go aoc: Environment checks are completed successfully. You are now compiling the full flow!! aoc: Selected target board a10soc_2ddr aoc: Running OpenCL parser.... aoc: OpenCL parser completed successfully. aoc: Compiling.... aoc: Linking with IP library ... +--------------------------------------------------------------------+ ; Estimated Resource Usage Summary ; +----------------------------------------+---------------------------+ ; Resource + Usage ; +----------------------------------------+---------------------------+ ; Logic utilization ; 2% ; ; ALUTs ; 1% ; ; Dedicated logic registers ; 1% ; ; Memory blocks ; 3% ; ; DSP blocks ; 0% ; +----------------------------------------+---------------------------; aoc: First stage compilation completed successfully. aoc: Hardware generation completed successfully.
コンパイルが始まると、シェルコード内で指定したto_a10socというディレクトリが生成される。中には中間ファイルのadd.aocoと、様々な何かが入ったディレクトリが入っている。コンパイルが終わればadd.aocxというバイナリファイルが生成される。
無事kernelコードのコンパイルが終わったら、生成されたaocxファイルとhostコード(未コンパイル)の2つをscp等でArria10へ転送する。ここではto_a10soc下のgo_scpというシェルを使って転送する。宛先は各自で調整する。
./to_a10soc/go_scp
これで転送できた。
次からはArria10のARMへ移動して作業を進める。
sshでarria10に入る。
ssh root@131.113.69.239
現状誰しもがrootなのでふるまいに気を付ける。
コンパイルする前に、arria10上で以下の呪文を唱える。エラーは無視。
source ~/init_opencl.sh
その後、転送したディレクトリへ移動。デフォルトでは~/test/下にaocxファイルとmain.cppとMakefileがある。
自分のディレクトリを用意した場合は、~test/Makefileをコピーする。
ここでやっとmain.cppをmake allしてコンパイルする。
実行結果を以下に記す。エラーは無視する。
root@Arria10_linaro:~/test/test_add# make clean root@Arria10_linaro:~/test/test_add# make all ../common/src/AOCLUtils/opencl.cpp: In function ‘void* aocl_utils::alignedMalloc(size_t)’: ../common/src/AOCLUtils/opencl.cpp:55:49: warning: ignoring return value of ‘int posix_memalign(void**, size_t, size_t)’, declared with attribute warn_unused_result [-Wunused-result] posix_memalign (&result, AOCL_ALIGNMENT, size); ^ ../common/src/AOCLUtils/opencl.cpp: In function ‘bool aocl_utils::setCwdToExeDir()’: ../common/src/AOCLUtils/opencl.cpp:278:14: warning: ignoring return value of ‘int chdir(const char*)’, declared with attribute warn_unused_result [-Wunused-result] chdir(path); ^
すると、binというディレクトリが生成される。中にはコンパイルの成果物であるhostがある。
最後にbinにaocxファイルをぶち込み、./bin/hostを叩く。実行結果は以下の通り。
root@Arria10_linaro:~/test/test_add# ./bin/host Initializing OpenCL Platform: Altera SDK for OpenCL Using 1 device(s) a10soc_2ddrArria 10 SoC Development Kit Using AOCX: add.aocx Reprogramming device with handle 1 Arria 10 SoC Turn_around_Time: 1.022762 ms Kernel time (device 0)(getStartEndTime): 0.107940 ms Output: 93.649620 Reference: 93.649620 Verification: PASS
これでFPGA上で実行できた。
kernelコードのコンパイル時に--profileオプションを付けてFPGAに焼きこむと、走らせた後のbin内にprofile.monが生成される。これをneutrino(元のto_a10socディレクトリとか)に戻し(go_monとかで)、aocx(aocoでも可)ファイルとともにaocl reportコマンドを叩くとGUIプロファイラが立ち上がる。(Xのポート・フォワーディングを有効にするのを忘れぬよう)。視覚的にいろいろできる。
bash-4.1$ ./go_mon Enter passphrase for key '/home/hlab/hoge/.ssh/id_rsa': profile.mon 100% 97 0.1KB/s 00:00 bash-4.1$ aocl report profile.mon add.aocx &
もう力尽きたので並列化のテクニック等は各自リファレンスを当たって下さいませ。。。