言語モデルをFPGA上で動作させる - takgto/utokyo-chipathon2023 GitHub Wiki

このページではswanという言語モデルをVitisとVivadoを使ってKV260に実装する方法を説明します。

言語モデルを高位合成でFPGAに実装してみた
このサイトのやり方で、KV260上で言語モデルを動作させます。授業用PCの全てにVitis 2022.1がインストールされています。
TAに「KV260上でswanを動かしたい」と伝えてもらえたら、次のファイルをUSBからPCのDownloadフォルダにコピーします。

  • kv260_custom_pkgディレクトリ(kv260_custom,sysroots,pl.dtbo(デバイスツリー)が入っています)

次に、これらフォルダとファイルをWSL側にコピーする。 WSLのターミナルから

cp -r kv260_custom_pkg /mnt/c/Users/x-nics-kuroda

sysrootはkv260_custom_pkgの中のkv260_sysroot.tar.gzを解凍して取り出します。

tar -xvzf kv260_sysroot.tar.gz

解凍してできた、kv260_sysroot/sysrootsの下のcortexa72-cortexa53-xilinx-linuxをsysrootsとして後で出てくるVitis applicationで指定します。

以下、次の手順で言語モデルを作成してください。

1. swanをgit cloneする。

swanというディレクトリができます。その下にsrcフォルダがあり、swanのソースコードが入っています(上の参考サイトにコードの中身や解説が書かれています。)

git clone https://github.com/turingmotors/swan.git

2. Vitisの起動

mkdir kv260_swan
cd kv260_swan
vitis&

Vitis IDE Launcherが立ち上がるので、Worksapceの最後がkv260_swanであることを確認して右下のLaunchをクリックする。

次の画面でCreate Application Projectをクリックする。

次の画面ではそのままNextをクリックする。

次の画面ではVitis Application Platformを選択する。図の番号の準に渡したkv260_custom_pkgの中のkv260_cutomディレクトリを指定してOpenをクリック。

kv260が新たなプラットフォームとして加わったことを確認してNextをクリック。

次の画面ではApplication project nameにswanとだけ記入してNextをクリック。

次の画面では、番号に従ってsysrootの下のcortexa72-cortexa53-xilinx-linuxディレクトリを入力してください。Root FS: と Kernel Imageは空欄のままで構いません。

次の画面ではEmpty Applicationを選択して(defaultでEmpty Applicaitonです)、Finishをクリック。

次の画面に切り替わるはずです。

次にPL(FPGA)側のソースコードをimportします。まず次の画面の左上の Explorer から swan_kernels/src を右クリックし、Import Sources を選択します。 この時、Active build configuarationをHardwareにします。

次の画面のFrom directoryでBrowseを選択し、git cloneしてできたswanの下のsrcを選択してOpenします。次の画面が現れるはずです。ここで、Kernel_と先頭についてたファイル(計6つ)を選択してFinishをクリックします。Kernel_がつくとFPGA側の高位合成C program(HLSC)であることを意味します。

ファイルを追加できたら、右上のExplorerから swan_kernels/swan_kernels.prj を選択し、丸いアイコンの Add Hardware Functionsをクリック

kernel_と先頭についたファイルを選択してOKをクリック

次の図はKV260の構成を示したものです。図のPL側とPS側のビルドを次に行います。

3. PL(FPGA)側Programのビルド

エクスプローラの左側のswan_system_hw_linkを選択して上のメニューの下にある金づちマークをクリックするとビルドが始まります。約50分かかります。
TargetがHardwareであることを確認すること。ビルドが終了するとHardwareのフォルダができ、そこにbinary_container_1.xclbinが生成されます。

4. PS(ホスト側)Programのビルド

PL側と同様に、今度はswan/srcを右クリックしてimport sourcesを選択、swan リポジトリのsrcディレクトリにあるホストプログラム(kernel_*以外全て)を追加します。

swan.prjを選択して、メニューの金づちマークをクリックします。こちらのビルドは直ぐに終了します。swan/Hardwareの下にswanという実行ファイルができます。

[注意点]

  • 「error while loading shared libraries: libxilinxopencl.so.2: cannot open shared object file: No such file or directory」のようなエラーが出る場合は、KV260 のデフォルトの rootfs に XRT がインストールされていないことが原因です。しかし、sudo apt install xrtではなく以下のコマンドを使用してください。
    --> 次のコマンドを実行するにはKV260とPCをネットワーク共有して、KV260からインターネットサイトが見えるようにしないとなりません。行う前にTAに相談ください。
$ sudo apt install zocl-202210.2.13.479-r0.0.xilinx_k26_kv
$ sudo apt install xrt-202210.2.13.479-r0.0.cortexa72_cortexa53
$ sudo apt install packagegroup-petalinux-opencv

xrtに含まれるzoclのバージョンが新しいと正常に動作しないようです。

5. KV260へのファイル転送

次の3つのファイルはKV260のホームディレクトリ(/home/root)に置きます。 WSL2において、

  • ~/kv260_swan/swan_system_hw_link/Hardware/binary_container_1.xclbin をbinary_container_1.bin にリネームしたもの
  • ~/kv260_swan/swan/Hardware/swan
  • ~/swan/model (TAから)

/lib/firmware/xilinx/swanディレクトリを作成しそこに置く

  • kv260_swan/swan_system_hw_link/Hardware/binary_container_1.xclbin をbinary_container_1.bit.bin にリネームしたもの
  • pl.dtbo (TAから)
  • shell.json (下の内容のテキストファイル. 自分で作成する)
{
  "shell_type" : "XRT_FLAT",
  "num_slots": "1"
}

6. SWANの実行

まず、xmutilコマンドを用いてPLにハードウェアを生成します。 KV260上で、

sudo xmutil listapps
sudo xmutil unloadapp
sudo xmutil loadapp swan

Loaded to Slot 0と出れば成功です。

これで、ホームディレクトリにある swanを実行すると、KV260上でLLMが動き出します。

お世辞にも早いとは言い難いですが、わずか~4GBメモリのFPGAボード上で小型LLMが動きます。

先の参考資料には、PCだけでSWANを実行する方法が載ってます。直ぐにできますのでやってみてください。

7. 改良するためには、

主に応答速度を改良するには、次の方法があると思います。

  1. HLSプラグマ最適化
  • #pragma HLS PIPELINE:ループのパイプライン化
  • #pragma HLS UNROLL:ループ展開で並列度向上
  • #pragma HLS ARRAY_PARTITION:BRAMの並列アクセス
  • II(Initiation Interval)の改善
  1. カーネル統合 + Dataflow化 現在は各カーネルが完全に終わってから次のカーネルが開始、中間データは毎回DRAMに書き戻しているので効率いいとは言えません。
  • 各処理が重なって動作(パイプライン)
  • 中間データはFIFO経由(DRAM不要)
  1. タイリング + オンチップバッファ 大きな行列を小さなタイル(ブロック)に分割し、タイル単位で処理する。 行列演算を小ブロックに分割し、BRAMにタイルをキャッシュしてDRAMアクセス回数を削減。 これは、
  1. より小さなモデルへの変更
  • TinyLlama、SmolLM等の軽量モデル
  • 層数・hidden sizeの削減
  1. 量子化
  • モデル自体をfloat32からINT8等に量子化
  • メモリ転送量が1/4〜1/8に削減
  • DSPの利用効率も向上

どれも難易度は高いです。特に、量子化やネットワークの変更はLLMの重み係数を学習し直しする必要がでてくるかもしれませんので更に難易度は上がります。

5. 量子化を試してみたい方はこちらへ

より大きいFPGAの乗っているMKUBOSでswanを動かしたい方はこちらへ