SDAccelでOpenCLのプロジェクトをbuildする
Amazon Web ServicesでFPGAを使い、OpenCLのコードを実行するため。
準備
OpenCLのbuildをするためには"FPGA Developer AMI"のインスタンスを稼働する必要がある。 buildには、ソフトウェアエミュレーション(sw_emu)、ハードウエアエミュレーション(hw_emu)、 FPGA用のビットファイル生成(hw)の三種類がある。
ビットファイルを生成するには、メモリの多い(32GB程度)インスタンスが推奨されているが、 2種のエミュレーションをするだけなら、その必要はないと思われる。 テストのプロジェクトでは、t2.large(メモリ8GB)でも問題はなかった。 build用のインスタンスは東京リージョン(ap-northeast-1)でもかまわない。 ただし、FPGAが使えるF1インスタンスは現時点では東京リージョンでは使えないため、 ビットファイルをテストするときには米国東部:バージニア北部リージョン(us-east-1)などの利用が必要。
ビットファイルを生成したあと、Amazon FPGA Imageの生成というタスクを AWS CLIから実行する必要があり、 これは東京リージョンではできない。 利用するS3のバケットおよび"aws"コマンドを実行するリージョンをus-east-1にする必要がある。
倹約のためt2.largeとc4.4xlargeのインスンタスを切り替えて使う。 OpenCLコードのテストデバッグはt2.largeで、ビットファイル生成はc4.4xlargeで。 切り替える時に、AMI用とユーザー領域のボリュームとをデタッチ・アタッチするのが面倒。 AWS CLIによって、Webコンソールを使わなくても、デタッチ・アタッチ及びインスタンス開始が可能。
“FPGA Developer AMI"を稼働する際のディスクは以下のようになっている。
ルートデバイス /dev/sda1 /
ユーザー領域 /dev/sdb /home/centos/src/project_data
ユーザー領域には念のため30GBを割り当てた。
このAMIの中身はcentosで、sshするときのデフォルトのユーザー名は"centos"であり、 “root"や"ec2-user"ではない。
手順
SSAccelのガイドに従えばよい。
aws-fpgaレポジトリのclone
適当な場所にて。
git clone https://github.com/aws/aws-fpga.git
環境の設定
以下のコマンドはbashで行う必要がある。
source aws-fpga/sdaccel_setup.sh
この実行後は、他のshellを起動してもいい。zshでは問題なし。
ソフトウェアエミュレーション用のbuild
サンプルのプロジェクト(helloworld_oclなど)をコピーする、または自分のプロジェクトを作る。 以下、そのディレクトリ内で実行する必要がある。
make TARGETS=sw_emu DEVICES=$AWS_PLATFORM_1DDR all
DEVICESに指定できるのは、$AWS_PLATFORM、$AWS_PLATFORM_4DDRまたは$AWS_PLATFORM_1DDRのどれか。 最後の指定はメモリをひとつしか使わないので、より短時間で実行できるはず。テスト用。
ソフトウェアエミュレーションで実行する。
XCL_EMULATION_MODE=sw_emu ./helloworld
ハードウェアエミュレーション用のbuild
make TARGETS=hw_emu DEVICES=$AWS_PLATFORM_1DDR all
このエミュレーションもt2.largeインスンタスで実行した。 東京リージョンでは1時間あたり0.1216ドルかかる。
ハードウェアエミュレーションで実行する。
XCL_EMULATION_MODE=hw_emu ./helloworld
実機用のbuild
make TARGETS=hw DEVICES=$AWS_PLATFORM_1DDR all
この実行だけは推奨されているc4.4xlargeでおこなった。 c4.4xlargeの利用は東京リージョンでは1時間あたり1.008ドル(20180307時点)かかる。無料枠でもない。 これよりしょぼいインスタンスで実行するとどうなるかは不明。
デフォルトの$AWS_PLATFORM($AWS_PLATFORM_4DDR)の場合3時間以上かかった。 $AWS_PLATFORM_1DDRの場合1-2時間くらいで気持ち速い。
Amazon FPGA Image(AFI)の生成
実機用のビットファイルをEC2で実行できる形式に変換する。詳細は不明だが30分程度かかる。 結果を保持するS3のバケットを事前に作成する。 これはF1インスタンスがあるリージョン(今回はus-east-1リージョン)に作る必要がある。 また、以下のスクリプトはAWS CLIを呼び出すので、 デフォルトリージョンもus-east-1に設定する。
$SDACCEL_DIR/tools/create_sdaccel_afi.sh -xclbin=xclbin/<長い名前>.xclbin -o=<長い名前> \
-s3_bucket=<bucket-name> -s3_dcp_key=dcp -s3_logs_key=log
ガイドに従う。"-xclbin"にはbuildしたビットファイルを指定する。 結果を保持するバケットに"dcp"と"log"というフォルダを作成しておく。
F1インスタンスで実行
AWSのアカウントを作っただけでは、us-east-1リージョンでのF1インスンタスの稼働は認められていない。 EC2ダッシュボードの「制限」から、F1を使えるようにリクエストする必要がある。
英語で、制限解除のリクエストをしてから約1日で承認された。 承認のメールは、日本時間の深夜に届いたので、多分USの担当者と思われる。 追加での特別な説明は必要なかった。
F1インスタンスの利用が承認されたら、 そのリージョンにて、“FPGA Developer AMI"を使ってF1インスタンスを開始する。 なおこのAMIはスワップ領域を30GBも指定しているが、実機テストには必要ない。 AMIをカスタマイズしたほうがよさそう。
AFIの生成が終わりavailableになっているとして、実機での実行に必要なものは、 アプリケーションの実行ファイルと”<長い名前>.awsxclbin"のファイルだけでよい。 後者のファイルにAFIをロードするのに必要な情報が入っている模様。 これらを稼働中のインスタンスまたは、利用するボリュームにコピーする必要がある。 今回は別の計算機を介してscpでコピーした。
1DDR用のビットファイルを利用するには、 SDAccelのガイドにあるように、 “<長い名前>.awsxclbin"の名前を変えたコピーが必要。
cp <kernel名>.hw.xilinx_aws-vu9p-f1_1ddr-xpr-2pr_4_0.awsxclbin <kernel名>.hw.xilinx_aws-vu9p-f1_4ddr-xpr-2pr_4_0.awsxclbin
これをしないと4DDR用のファイル名を探して失敗する。
実行するにはroot権限が必要なので
sudo bash
source /opt/Xilinx/SDx/2017.1.rte.1ddr/setup.sh #1DDRの場合
の後で、buildしたアプリケーションを実行できる。 初めて実行する時にビットファイルのコンフィグが行われるので、それにしばらく時間がかかる。
できた。 deviceに"4ddr"とあるが、上にあるようにファイルをコピーしているので、実際には1ddrである。
これは、整数ベクトルに定数を乗算するカーネル。 2度目以降は、コンフィグをスキップするので即実行される。
F1インスタンスが使えるリージョン
オンデマンドインスタンス 2018年3月
リージョン | 英語名 | f1.2xlarge | f1.16xlarge |
---|---|---|---|
バージニア北部 | us-east-1 | 1.65ドル | 13.2ドル |
オレゴン | us-west-2 | 1.65ドル | 13.2ドル |
アイルランド | eu-west-1 | 1.815ドル | 14.52ドル |
スポットインスタンス(20180308のある時刻)
リージョン | 英語名 | f1.2xlarge | f1.16xlarge |
---|---|---|---|
バージニア北部 | us-east-1 | 0.6572ドル | 5.1121ドル |
オレゴン | us-west-2 | 0.7031ドル | 13.2ドル |
アイルランド | eu-west-1 | 0.7003ドル | 14.52ドル |
新規プロジェクト用のMakefile
Introduction to the SDAccel Makefileにより詳しい説明がある。
アプケーションのコードが"main.cpp”、実行ファイル名が"run”、 OpenCLのカーネルファイルが"TemplateC_Kernels.cl”、 その中の利用するうカーネル関数名が"templateKernel"の場合。
COMMON_REPO := $(SDACCEL_DIR)/examples/xilinx
include $(COMMON_REPO)/utility/boards.mk
include $(COMMON_REPO)/libs/xcl2/xcl2.mk
include $(COMMON_REPO)/libs/opencl/opencl.mk
# run Host Application
run_SRCS=./main.cpp $(xcl2_SRCS)
run_HDRS=$(xcl2_HDRS)
run_CXXFLAGS=-I. $(xcl2_CXXFLAGS) $(opencl_CXXFLAGS)
run_LDFLAGS=$(opencl_LDFLAGS)
EXES=run
# Kernel
templateKernel_SRCS=./TemplateC_Kernels.cl
XOS=templateKernel
# run xclbin
templateKernel_XOS=$(XOS)
XCLBINS=$XOS
# check
check_EXE=$(EXES)
check_XCLBINS=$(XOS)
CHECKS=check
include $(COMMON_REPO)/utility/rules.mk
“# Kernel"と”# run xclbin"の次の行の変数名を正しく設定しないと、 カーネルファイル(今の場合、TemplateC_Kernels.cl)が見つからないと怒られる。