Successfully reported this slideshow.

「FPGA 開発入門:FPGA を用いたエッジ AI の高速化手法を学ぶ」

0

Share

Loading in …3
×
1 of 55
1 of 55

「FPGA 開発入門:FPGA を用いたエッジ AI の高速化手法を学ぶ」

0

Share

Download to read offline

Description

「FPGA 開発入門:FPGA を用いたエッジ AI の高速化手法を学ぶ」
2020年11月27日第1回ACRiウェビナー 講演資料(1)
講演者:  株式会社フィックスターズ シニアエンジニア 森高晃大様

Transcript

  1. 1. FPGA 開発入門:FPGA を用いたエッジ AI の高速 化手法を学ぶ ACRi ウェビナー 2020/11/27 株式会社フィックスターズ
  2. 2. 目次 自己紹介 ウェビナーの目的 CNN 高速化 ✔ 畳み込み層のタスク並列化 ✔ 畳み込み層のループ並列化 ✔ 畳み込み層のデータ並列化 ✔ 全結合層のループ並列化、データ並列化 まとめ 2
  3. 3. 自己紹介 森高 晃大 エンジニア ✔ 主に FPGA (HLS, Verilog-HDL)、C/C++ 略歴 ✔ 2013 年 4 月、某電機メーカ入社 サーバ、最先端スパコン向け CPU のメモリコントローラ開発 ✔ 2018 年 4 月、フィックスターズ入社 FPGA を使った HFT, 画像処理、ディープラーニングなどの プロジェクトに参加、開発の中心を担う。 3
  4. 4. ウェビナーの目的 Naive に実装されたある CNN の高速化を 通じて、HLS における高速化の原理・手法を習 得する。 ✔ 手法自体は基本的なもの 目的達成に向けて ✔ その手法の手軽さと効果、またそのインパクトの大きさを確認 ✔ HLS といえどもハードウェア (アーキテクチャ) 設計は必要であることを確 認 4※Xilinx Vivado/Vitis HLS を前提
  5. 5. HLS における高速化手法を学ぶ 3 つの理由 1. FPGA 活躍の場面が増加しており、効率的な設計を狙った HLS の利用ケースが増加 ✔ 低消費電力や低レイテンシなどを狙って、ディープラーニングの推論に FPGA を利用することが注目されている。 2. HLS で性能を出すための手段は今後も重要 3. 自前で作らなくても高速化の原理を知ることは大切 ✔ Vitis Libraries でもこのウェビナーで紹介する手法は頻出 5
  6. 6. 本ウェビナーの題材 畳み込みニューラルネットワーク (CNN) の 1 つである LeNet を簡略化し たネットワークモデルで MNIST の手書き文字認識 HLS で FPGA 上に実装し、高速化していく。 ✔ 講演内容は ACRi ブログ「FPGA で始めるエッジディープラーニング」(7)~(10) が ベース ソースコードは https://github.com/fixstars/dnn-kernel-fpga で公開 6 Netron で可視化したモデル。モデルのソースコードは https://github.com/fixstars/dnn-kernel-fpga/blob/master/learning/train_mnist.py#L9-L60
  7. 7. 本ウェビナーの題材 (続き) 7 CNN Conv Conv FC FC これは 4 です。 MNIST https://www.tensorflow.org/datasets/catalog/mnist 出力 (ラベル)入力 (画像 1 枚)
  8. 8. 畳み込み層 (CONV) と全結合層 (FC) 全結合層 ベクトルと行列の掛け算 畳み込みの出力 (画像の特徴) をラベル データに変換する場合などに使用 8 畳み込み層 「入力ピクセルとその周辺 ピクセル (X)」に 「カーネル (W)」を掛けて総和を 「出力ピクセル (Y)」とする層
  9. 9. PCIe カード FPGA ベースデザインとその性能 9 CPU DRAM CNN Conv1 Conv2 fc1 fc2 ※300MHz 動作
  10. 10. 本ウェビナーで実施する高速化手法 以下の FPGA アーキテクチャに適した高速化手法を実施 ✔ タスク並列化 ✔ ループ並列化 ✔ データ並列化 上記はディープラーニングだけでなく FPGA 開発一般に利用可能な高速化手法 10
  11. 11. タスク並列化 FPGA アーキテクチャに適した高速化
  12. 12. タスクの並列実行 逐次的に実行される関数 (タスク) を並列に実行させ レイテンシ・スループットを向上 12FPGA で始めるエッジディープラーニング(7) https://www.acri.c.titech.ac.jp/wordpress/archives/7134 推論処理全体のタイムチャート 青がフレーム 1、橙がフレーム 2、緑がフレーム 3 を処理 逐次的に実行されるタスクから並列性を抽出 (要コード修正) ある時刻において、複数のタスクが別々のフレームを処理可能に ただし、conv2 がボトルネックとなる。
  13. 13. プラグマ 3 つを追加するだけ* で並列化可能に 1. #pragma HLS dataflow ✔ タスク間を FIFO もしくは Ping-pong バッファで接続 ■ ハードウェアリソース的なオーバヘッドあり ✔ 各タスクは、自身のペースで処理を実行可能 ■ 前後のタスクからは独立 2. #pragma HLS stable ✔ 詳細はブログにて 3. #pragma HLS interface ap_ctrl_chain ✔ 詳細はブログにて 13 * dataflow 適用にはいくつか制限がある。詳細は 詳細は UG902 Exploiting Task Level Parallelism: Dataflow Optimization を参照
  14. 14. なぜ Ping-pong バッファ ? 14 Ping-pong バッファ なし Ping-pong バッファ あり conv1 は conv2 が 1 つ前のフレームを処 理し切るまで待たなければならない。前フ レームのデータを壊しかねないため。 conv1 は conv2 が 1 つ前のフレームの処 理を待たなくてよい。conv1 の書き込み バッファは、conv2 の読み込みバッファと別 であり、前フレームのデータを壊すことはな いため。 conv1 conv2 … conv1 conv2 … Ping-pong buffer 推論回路一部抜粋
  15. 15. 高位合成の結果を確認 タスク並列化前 15 タスク並列化後
  16. 16. 高位合成の結果を確認 (続き) 16 t conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 t conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 947405 cycles 947405 cycles 947407 cycles 504897 cycles 504897 cycless タスク並列化前 タスク並列化後
  17. 17. Vitis で実行 (タスク並列化前) タスク並列化は当然されていない。 17 conv1 conv2 fc1 fc2 1 フレーム 上図のように逐次実行 であることがわかる。
  18. 18. Vitis で実行 (タスク並列化後) タスク並列化により複数フレームを同時に処理 18 4 フレーム同 時処理 ボトルネックの conv2 に 絶えずデータが入力され ている。
  19. 19. 実行時間比較 19
  20. 20. タスク並列化まとめ タスク並列化で推論処理を高速化 ✔ タスク並列化前後で 1.65 倍の高速化 タスク並列により複数タスクが同時に動作可能、スループット向上 につながる。 タスク並列化に向けた 3 つの pragma を使用 ✔ dataflow, stable, ap_ctrl_chain 20
  21. 21. ループ並列化 FPGA アーキテクチャに適した高速化
  22. 22. 全タスクの処理速度を (できれば) 揃える 22FPGA で始めるエッジディープラーニング(5) https://www.acri.c.titech.ac.jp/wordpress/archives/6757 conv1, conv2 の処理時間を削減できれば さらに効率的に処理可能 ループ並列化・データ並列化を利用した conv1, conv2 の処理時間短縮 conv2 の実行時間が他と比べて長く conv2 で律速
  23. 23. ループ並列化 異なるイタレーション間で並列性を抽出すること イタレーションが実行可能な間隔は II (Initiation Interval) と呼ばれる。 23 ループ並列化前 II=8 ループ並列化後 II=1
  24. 24. タスク並列とループ並列の違いは並列化の粒度 24 t conv1 conv2 fc1 fc2 並列化前 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 タスク並列化、並列化対象はタスク t conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 ループ並列化、並列化対象はタスク内のループ t cv1 cv2 fc1 fc2 cv1 cv2 fc1 fc2 cv1 cv2 fc1 fc2 ループを並列化することで タスク単体のスループットを向上1 タスクを並列化することで 処理全体のスループットを向上 *1: 後述のデータ並列もタスク単体のスループット向上が目的
  25. 25. プラグマ 1 つを追加するだけ* で並列化可能に #pragma HLS pipeline II=1 もしくは単に #pragma HLS pipeline だけでも OK 25* ただし、Vivado が並列性を抽出可能なコードになっていることが前提 17 for (int32_t ich = 0; ich < in_channels; ++ich) { 18 for (int32_t kh = 0; kh < ksize; ++kh) { 19 for (int32_t kw = 0; kw < ksize; ++kw) { ... 30 #pragma HLS pipeline II=1 31 sum += x[pix_idx] * weight[weight_idx]; 32 } 33 } 34 } この 1 行の追加だけで ループ並列化が可能、 II=1 が達成できる…!?
  26. 26. II=1 未達の原因は? II=4 で合成 ✔ fadd の レイテンシ 4 サイクルに律速される。 ✔ sum にループ間依存関係 (Read After Write) が発生 ■ sum += x[pix_idx] * weight[weight_idx]; 26 fadd@{i+1} は fadd@{i} の結果を使いたい。 add@{i} は 8 サイクル目までかかる。 よって、fadd@{i+1} は 9 サイクル目まで開始できない。 DEPENDENCE !
  27. 27. II=1 を達成するには? 性能のためには、II=1 を目指したほうが良い。 回路を修正して以下のようなタイムチャートを目指す。 27詳細は「FPGA ではじめるエッジディープラーニング (8)」にて https://www.acri.c.titech.ac.jp/wordpress/archives/7434
  28. 28. シフトレジスタを用いて II=1 を達成 28 0 x w 1 2 3 (総和) シフトレジスタ fadd のレイテンシ 4 に合わせて 4 段のシフトレジスタを上図のように追加 ✔ 任意の連続する 4 イタレーションで加算結果の依存関係を解消 最後にシフトレジスタの結果 (部分和) を足し合わせて 総和を計算
  29. 29. conv2 スループット比較 29※外部メモリアクセス削減は本ウェビナー範囲外 ※
  30. 30. 実行時間比較 30
  31. 31. ループ並列化まとめ ループ並列化で推論処理を高速化 ✔ ループ並列化前後で 2.64 倍の高速化 タスク並列と違い、あるタスクのループを並列化し 全体の処理を高速化 ループ並列化に向けた pragma を使用 ✔ pipeline II=1 が満たせるようループ間の依存関係に注意 31
  32. 32. データ並列化 FPGA アーキテクチャに適した高速化
  33. 33. 全タスクの処理速度を (できれば) 揃える (再) 33FPGA で始めるエッジディープラーニング(5) https://www.acri.c.titech.ac.jp/wordpress/archives/6757 conv1, conv2 の処理時間を削減できれば さらに効率的に処理可能 ループ並列化・データ並列化を利用した conv1, conv2 の処理時間短縮 conv2 の実行時間が他と比べて長く conv2 で律速
  34. 34. データ並列化 データ間で並列性を抽出すること ✔ ループ並列はパイプラインを埋めるため ✔ データ並列はある計算を同時にたくさん行うため ループ並列性とデータ並列性は同時に抽出可能 34ループ並列の効果 データ並列の効果
  35. 35. データ並列性の難点 データ並列性を抽出すればするほど 複製される回路の数は増加 データ並列性については 以下の制限に注意して設計することが重要 ✔ 物理的なハードウェアリソース (LUT, FF, DSP, xRAM, ...) ✔ メモリアクセスのバンド幅 35
  36. 36. 畳み込み処理でデータ並列性を抽出 畳み込み処理の 6 段ループでは様々な並列性が抽出可能 ✔ 出力チャネル、y 座標、x 座標、入力チャネル、カーネル y 方向、カーネ ル x 方向 ここではそのうち 2 つを抽出してカーネルの性能向上 ✔ 処理ピクセル間の並列性 ✔ 出力チャネル間の並列性 36
  37. 37. 処理ピクセル間の並列性 37 入力 x カーネル w 出力 y for (i=0; i<N; ++i) { y[i] = f(x[i], w); } for (i=0; i<N/2; i+=2) { y[i] = f(x[i], w); y[i+1] = f(x[i+1], w); } 並列化 並列化前 並列化後 互いに依存しない入力ピクセルの計算を同サイクルに実行 畳み込み計算のカーネル (中央黄) は共通
  38. 38. 出力チャネル間の並列性 38 入力 x カーネル w 出力 y for (k=0; k<M; ++k) { y[k][i] = f(x[i], w[k]); } 並列化 並列化前 並列化後 互いに依存しない出力チャネルの計算を同サイクルに実行 入力ピクセル (左橙) は共通 for (k=0; k<M/2; k+=2) { y[k][i] = f(x[i], w[k]); y[k+1][i] = f(x[i], w[k+1]); }
  39. 39. 両並列性を組み合わせる 39 入力 x カーネル w 出力 y for (k=0; k<M; k++) { for (i=0; i<N; ++i) { y[k][i] = f(x[i], w[k]); } } 並列化 並列化前 並列化後 for (k=0; k<M/2; k+=2) { for (i=0; i<N/2; i+=2) { y[k][i] = f(x[i], w[k]); y[k][i+1] = f(x[i+1], w[k]); y[k+1][i] = f(x[i], w[k+1]); y[k+1][i+1] = f(x[i+1], w[k+1]); } } 2 入力ピクセル x 2 カーネル で同時に 4 出力
  40. 40. 実装する HW のイメージ 2 ピクセル x 2 カーネルで 4 出力 演算器 (PE) が 2 x 2 の格子状に 配置されている。 メモリアクセスは ✔ ピクセル 2 回読み出し ✔ カーネル 2 回読み出し 40
  41. 41. メモリのポート数と DSP 数 1 つの軸のみをデータ並列化 ✔ 並列度 n に対し演算器が n 個 ✔ FPGA 内のリソース数が 総 DSP 数 > BRAM ポート数であるため DSP を十分に使い切れない。 2 つの軸をデータ並列化 ✔ (ピクセル側の並列度を n, 出力チャネル側の並列度を m) ✔ 総メモリアクセスポート数 n + m に対して 演算器は n * m 個 ✔ 十分な DSP を使用可能 41
  42. 42. d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 演算器アレイ動作イメージ 42 d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 0 1 0 1 0 1 0 1 0 1 0 1 理論上、2 port RAM 2x4 個で 32 個の DSP を埋め られる
  43. 43. pragma (とループの書き換え) で実現 #pragma HLS unroll #pragma HLS array_partition 各プラグマについてはブログにて 並列化したい方向によってはループの書き換えが必要 ✔ 今回の畳み込み層では 全 6 重ループ (出力チャネル、y 座標、x 座標、入力チャネル、カーネ ル y 方向、カーネル x 方向) のうち 出力チャネルと x 軸方向のデータ並列性を抽出、 その 2 ループの回転数を並列化分考慮する必要がある。 43
  44. 44. 合成結果と動作結果 44 $ ./host/run_inference ./host/inference_unrolledx4_conv_v2_hw.xclbin inference_unrolledx4_conv_v2 1 Elapsed time: 0.335922 [ms/image] accuracy: 0.973 ↑合成レポート、全結合層がボトルネックになっていることがわかる。 ↓実行結果、全結合層の性能がそのまま見えている。
  45. 45. conv2 スループット比較 45
  46. 46. 実行時間比較 46
  47. 47. データ並列化まとめ データ並列化で推論処理を高速化 ✔ データ並列化前後で 1.81 倍の高速化 あるデータの計算を複製、並列化し全体の処理を高速化 データ並列化に向けた pragma を使用 ✔ unroll, array_partition 計算の複製はハードウェアリソースの増加に直結 LUT 数などだけでなく、メモリのポート数にも注意 47
  48. 48. その他最適化 全結合層の最適化と層間バランス
  49. 49. 全結合層の最適化と全体の最適化について 全結合層の最適化 ✔ 畳み込み層が速くなったので全結合層が遅くなった。 ✔ 畳み込み層と同様にループ並列化、データ並列化を実施 全体の最適化 ✔ 層間のバランスを取るためのチューニングを実施 ✔ 効率的なタスク並列を実現 49
  50. 50. conv1, conv2, fc1 の処理性能がほぼ同じに 50
  51. 51. 最終結果とここまでの高速化の変遷 51
  52. 52. 性能、リソース消費まとめ ベースラインの 417.87 倍の高速化を達成 以下の 2 手法の効果が大きい (本ウェビナー範囲外😥) ✔ 外部メモリアクセス削減 ✔ 最終版 (全結合層の高速化+層間のバランス) リソース消費の増加量は、400 倍の高速化に対し 2~3 倍程度に抑制 ✔ タスク並列化、ループ並列化はほとんどリソース増加なし 52
  53. 53. 全体のまとめ Naive な実装の CNN を対象に 3 つの並列性を抽出し高速化 ✔ タスク並列性:dataflow, stable, ap_ctrl_chain ✔ ループ並列性:pipeline ✔ データ並列性:unroll, array_partition プラグマを挿入するだけである程度の高速化が可能 さらなる高速化を目指すには以下が必要 ✔ ハードウェア実装を考慮したコーディング ✔ Vivado/Vitis HLS への優しさ 53
  54. 54. より現実的なモデルに向けて 今回の題材は非常に小さなデータセット (MNIST) ✔ 入力も重みも全部内部 RAM に入ってしまうほどの小ささ 現実的な問題では画像の解像度、 ネットワーク規模は文字通り桁違い ✔ 例) ResNet-101: 解像度 224x224、層数 101 さらなる並列度の抽出、計算ユニットの複製、 計算そのものを減らすこと (枝刈り、量子化) などの工夫が必要 54
  55. 55. Thank you.

Description

「FPGA 開発入門:FPGA を用いたエッジ AI の高速化手法を学ぶ」
2020年11月27日第1回ACRiウェビナー 講演資料(1)
講演者:  株式会社フィックスターズ シニアエンジニア 森高晃大様

Transcript

  1. 1. FPGA 開発入門:FPGA を用いたエッジ AI の高速 化手法を学ぶ ACRi ウェビナー 2020/11/27 株式会社フィックスターズ
  2. 2. 目次 自己紹介 ウェビナーの目的 CNN 高速化 ✔ 畳み込み層のタスク並列化 ✔ 畳み込み層のループ並列化 ✔ 畳み込み層のデータ並列化 ✔ 全結合層のループ並列化、データ並列化 まとめ 2
  3. 3. 自己紹介 森高 晃大 エンジニア ✔ 主に FPGA (HLS, Verilog-HDL)、C/C++ 略歴 ✔ 2013 年 4 月、某電機メーカ入社 サーバ、最先端スパコン向け CPU のメモリコントローラ開発 ✔ 2018 年 4 月、フィックスターズ入社 FPGA を使った HFT, 画像処理、ディープラーニングなどの プロジェクトに参加、開発の中心を担う。 3
  4. 4. ウェビナーの目的 Naive に実装されたある CNN の高速化を 通じて、HLS における高速化の原理・手法を習 得する。 ✔ 手法自体は基本的なもの 目的達成に向けて ✔ その手法の手軽さと効果、またそのインパクトの大きさを確認 ✔ HLS といえどもハードウェア (アーキテクチャ) 設計は必要であることを確 認 4※Xilinx Vivado/Vitis HLS を前提
  5. 5. HLS における高速化手法を学ぶ 3 つの理由 1. FPGA 活躍の場面が増加しており、効率的な設計を狙った HLS の利用ケースが増加 ✔ 低消費電力や低レイテンシなどを狙って、ディープラーニングの推論に FPGA を利用することが注目されている。 2. HLS で性能を出すための手段は今後も重要 3. 自前で作らなくても高速化の原理を知ることは大切 ✔ Vitis Libraries でもこのウェビナーで紹介する手法は頻出 5
  6. 6. 本ウェビナーの題材 畳み込みニューラルネットワーク (CNN) の 1 つである LeNet を簡略化し たネットワークモデルで MNIST の手書き文字認識 HLS で FPGA 上に実装し、高速化していく。 ✔ 講演内容は ACRi ブログ「FPGA で始めるエッジディープラーニング」(7)~(10) が ベース ソースコードは https://github.com/fixstars/dnn-kernel-fpga で公開 6 Netron で可視化したモデル。モデルのソースコードは https://github.com/fixstars/dnn-kernel-fpga/blob/master/learning/train_mnist.py#L9-L60
  7. 7. 本ウェビナーの題材 (続き) 7 CNN Conv Conv FC FC これは 4 です。 MNIST https://www.tensorflow.org/datasets/catalog/mnist 出力 (ラベル)入力 (画像 1 枚)
  8. 8. 畳み込み層 (CONV) と全結合層 (FC) 全結合層 ベクトルと行列の掛け算 畳み込みの出力 (画像の特徴) をラベル データに変換する場合などに使用 8 畳み込み層 「入力ピクセルとその周辺 ピクセル (X)」に 「カーネル (W)」を掛けて総和を 「出力ピクセル (Y)」とする層
  9. 9. PCIe カード FPGA ベースデザインとその性能 9 CPU DRAM CNN Conv1 Conv2 fc1 fc2 ※300MHz 動作
  10. 10. 本ウェビナーで実施する高速化手法 以下の FPGA アーキテクチャに適した高速化手法を実施 ✔ タスク並列化 ✔ ループ並列化 ✔ データ並列化 上記はディープラーニングだけでなく FPGA 開発一般に利用可能な高速化手法 10
  11. 11. タスク並列化 FPGA アーキテクチャに適した高速化
  12. 12. タスクの並列実行 逐次的に実行される関数 (タスク) を並列に実行させ レイテンシ・スループットを向上 12FPGA で始めるエッジディープラーニング(7) https://www.acri.c.titech.ac.jp/wordpress/archives/7134 推論処理全体のタイムチャート 青がフレーム 1、橙がフレーム 2、緑がフレーム 3 を処理 逐次的に実行されるタスクから並列性を抽出 (要コード修正) ある時刻において、複数のタスクが別々のフレームを処理可能に ただし、conv2 がボトルネックとなる。
  13. 13. プラグマ 3 つを追加するだけ* で並列化可能に 1. #pragma HLS dataflow ✔ タスク間を FIFO もしくは Ping-pong バッファで接続 ■ ハードウェアリソース的なオーバヘッドあり ✔ 各タスクは、自身のペースで処理を実行可能 ■ 前後のタスクからは独立 2. #pragma HLS stable ✔ 詳細はブログにて 3. #pragma HLS interface ap_ctrl_chain ✔ 詳細はブログにて 13 * dataflow 適用にはいくつか制限がある。詳細は 詳細は UG902 Exploiting Task Level Parallelism: Dataflow Optimization を参照
  14. 14. なぜ Ping-pong バッファ ? 14 Ping-pong バッファ なし Ping-pong バッファ あり conv1 は conv2 が 1 つ前のフレームを処 理し切るまで待たなければならない。前フ レームのデータを壊しかねないため。 conv1 は conv2 が 1 つ前のフレームの処 理を待たなくてよい。conv1 の書き込み バッファは、conv2 の読み込みバッファと別 であり、前フレームのデータを壊すことはな いため。 conv1 conv2 … conv1 conv2 … Ping-pong buffer 推論回路一部抜粋
  15. 15. 高位合成の結果を確認 タスク並列化前 15 タスク並列化後
  16. 16. 高位合成の結果を確認 (続き) 16 t conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 t conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 947405 cycles 947405 cycles 947407 cycles 504897 cycles 504897 cycless タスク並列化前 タスク並列化後
  17. 17. Vitis で実行 (タスク並列化前) タスク並列化は当然されていない。 17 conv1 conv2 fc1 fc2 1 フレーム 上図のように逐次実行 であることがわかる。
  18. 18. Vitis で実行 (タスク並列化後) タスク並列化により複数フレームを同時に処理 18 4 フレーム同 時処理 ボトルネックの conv2 に 絶えずデータが入力され ている。
  19. 19. 実行時間比較 19
  20. 20. タスク並列化まとめ タスク並列化で推論処理を高速化 ✔ タスク並列化前後で 1.65 倍の高速化 タスク並列により複数タスクが同時に動作可能、スループット向上 につながる。 タスク並列化に向けた 3 つの pragma を使用 ✔ dataflow, stable, ap_ctrl_chain 20
  21. 21. ループ並列化 FPGA アーキテクチャに適した高速化
  22. 22. 全タスクの処理速度を (できれば) 揃える 22FPGA で始めるエッジディープラーニング(5) https://www.acri.c.titech.ac.jp/wordpress/archives/6757 conv1, conv2 の処理時間を削減できれば さらに効率的に処理可能 ループ並列化・データ並列化を利用した conv1, conv2 の処理時間短縮 conv2 の実行時間が他と比べて長く conv2 で律速
  23. 23. ループ並列化 異なるイタレーション間で並列性を抽出すること イタレーションが実行可能な間隔は II (Initiation Interval) と呼ばれる。 23 ループ並列化前 II=8 ループ並列化後 II=1
  24. 24. タスク並列とループ並列の違いは並列化の粒度 24 t conv1 conv2 fc1 fc2 並列化前 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 タスク並列化、並列化対象はタスク t conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 conv1 conv2 fc1 fc2 ループ並列化、並列化対象はタスク内のループ t cv1 cv2 fc1 fc2 cv1 cv2 fc1 fc2 cv1 cv2 fc1 fc2 ループを並列化することで タスク単体のスループットを向上1 タスクを並列化することで 処理全体のスループットを向上 *1: 後述のデータ並列もタスク単体のスループット向上が目的
  25. 25. プラグマ 1 つを追加するだけ* で並列化可能に #pragma HLS pipeline II=1 もしくは単に #pragma HLS pipeline だけでも OK 25* ただし、Vivado が並列性を抽出可能なコードになっていることが前提 17 for (int32_t ich = 0; ich < in_channels; ++ich) { 18 for (int32_t kh = 0; kh < ksize; ++kh) { 19 for (int32_t kw = 0; kw < ksize; ++kw) { ... 30 #pragma HLS pipeline II=1 31 sum += x[pix_idx] * weight[weight_idx]; 32 } 33 } 34 } この 1 行の追加だけで ループ並列化が可能、 II=1 が達成できる…!?
  26. 26. II=1 未達の原因は? II=4 で合成 ✔ fadd の レイテンシ 4 サイクルに律速される。 ✔ sum にループ間依存関係 (Read After Write) が発生 ■ sum += x[pix_idx] * weight[weight_idx]; 26 fadd@{i+1} は fadd@{i} の結果を使いたい。 add@{i} は 8 サイクル目までかかる。 よって、fadd@{i+1} は 9 サイクル目まで開始できない。 DEPENDENCE !
  27. 27. II=1 を達成するには? 性能のためには、II=1 を目指したほうが良い。 回路を修正して以下のようなタイムチャートを目指す。 27詳細は「FPGA ではじめるエッジディープラーニング (8)」にて https://www.acri.c.titech.ac.jp/wordpress/archives/7434
  28. 28. シフトレジスタを用いて II=1 を達成 28 0 x w 1 2 3 (総和) シフトレジスタ fadd のレイテンシ 4 に合わせて 4 段のシフトレジスタを上図のように追加 ✔ 任意の連続する 4 イタレーションで加算結果の依存関係を解消 最後にシフトレジスタの結果 (部分和) を足し合わせて 総和を計算
  29. 29. conv2 スループット比較 29※外部メモリアクセス削減は本ウェビナー範囲外 ※
  30. 30. 実行時間比較 30
  31. 31. ループ並列化まとめ ループ並列化で推論処理を高速化 ✔ ループ並列化前後で 2.64 倍の高速化 タスク並列と違い、あるタスクのループを並列化し 全体の処理を高速化 ループ並列化に向けた pragma を使用 ✔ pipeline II=1 が満たせるようループ間の依存関係に注意 31
  32. 32. データ並列化 FPGA アーキテクチャに適した高速化
  33. 33. 全タスクの処理速度を (できれば) 揃える (再) 33FPGA で始めるエッジディープラーニング(5) https://www.acri.c.titech.ac.jp/wordpress/archives/6757 conv1, conv2 の処理時間を削減できれば さらに効率的に処理可能 ループ並列化・データ並列化を利用した conv1, conv2 の処理時間短縮 conv2 の実行時間が他と比べて長く conv2 で律速
  34. 34. データ並列化 データ間で並列性を抽出すること ✔ ループ並列はパイプラインを埋めるため ✔ データ並列はある計算を同時にたくさん行うため ループ並列性とデータ並列性は同時に抽出可能 34ループ並列の効果 データ並列の効果
  35. 35. データ並列性の難点 データ並列性を抽出すればするほど 複製される回路の数は増加 データ並列性については 以下の制限に注意して設計することが重要 ✔ 物理的なハードウェアリソース (LUT, FF, DSP, xRAM, ...) ✔ メモリアクセスのバンド幅 35
  36. 36. 畳み込み処理でデータ並列性を抽出 畳み込み処理の 6 段ループでは様々な並列性が抽出可能 ✔ 出力チャネル、y 座標、x 座標、入力チャネル、カーネル y 方向、カーネ ル x 方向 ここではそのうち 2 つを抽出してカーネルの性能向上 ✔ 処理ピクセル間の並列性 ✔ 出力チャネル間の並列性 36
  37. 37. 処理ピクセル間の並列性 37 入力 x カーネル w 出力 y for (i=0; i<N; ++i) { y[i] = f(x[i], w); } for (i=0; i<N/2; i+=2) { y[i] = f(x[i], w); y[i+1] = f(x[i+1], w); } 並列化 並列化前 並列化後 互いに依存しない入力ピクセルの計算を同サイクルに実行 畳み込み計算のカーネル (中央黄) は共通
  38. 38. 出力チャネル間の並列性 38 入力 x カーネル w 出力 y for (k=0; k<M; ++k) { y[k][i] = f(x[i], w[k]); } 並列化 並列化前 並列化後 互いに依存しない出力チャネルの計算を同サイクルに実行 入力ピクセル (左橙) は共通 for (k=0; k<M/2; k+=2) { y[k][i] = f(x[i], w[k]); y[k+1][i] = f(x[i], w[k+1]); }
  39. 39. 両並列性を組み合わせる 39 入力 x カーネル w 出力 y for (k=0; k<M; k++) { for (i=0; i<N; ++i) { y[k][i] = f(x[i], w[k]); } } 並列化 並列化前 並列化後 for (k=0; k<M/2; k+=2) { for (i=0; i<N/2; i+=2) { y[k][i] = f(x[i], w[k]); y[k][i+1] = f(x[i+1], w[k]); y[k+1][i] = f(x[i], w[k+1]); y[k+1][i+1] = f(x[i+1], w[k+1]); } } 2 入力ピクセル x 2 カーネル で同時に 4 出力
  40. 40. 実装する HW のイメージ 2 ピクセル x 2 カーネルで 4 出力 演算器 (PE) が 2 x 2 の格子状に 配置されている。 メモリアクセスは ✔ ピクセル 2 回読み出し ✔ カーネル 2 回読み出し 40
  41. 41. メモリのポート数と DSP 数 1 つの軸のみをデータ並列化 ✔ 並列度 n に対し演算器が n 個 ✔ FPGA 内のリソース数が 総 DSP 数 > BRAM ポート数であるため DSP を十分に使い切れない。 2 つの軸をデータ並列化 ✔ (ピクセル側の並列度を n, 出力チャネル側の並列度を m) ✔ 総メモリアクセスポート数 n + m に対して 演算器は n * m 個 ✔ 十分な DSP を使用可能 41
  42. 42. d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 演算器アレイ動作イメージ 42 d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 d e f 0 9 a b c 5 6 7 8 1 2 3 4 0 1 0 1 0 1 0 1 0 1 0 1 理論上、2 port RAM 2x4 個で 32 個の DSP を埋め られる
  43. 43. pragma (とループの書き換え) で実現 #pragma HLS unroll #pragma HLS array_partition 各プラグマについてはブログにて 並列化したい方向によってはループの書き換えが必要 ✔ 今回の畳み込み層では 全 6 重ループ (出力チャネル、y 座標、x 座標、入力チャネル、カーネ ル y 方向、カーネル x 方向) のうち 出力チャネルと x 軸方向のデータ並列性を抽出、 その 2 ループの回転数を並列化分考慮する必要がある。 43
  44. 44. 合成結果と動作結果 44 $ ./host/run_inference ./host/inference_unrolledx4_conv_v2_hw.xclbin inference_unrolledx4_conv_v2 1 Elapsed time: 0.335922 [ms/image] accuracy: 0.973 ↑合成レポート、全結合層がボトルネックになっていることがわかる。 ↓実行結果、全結合層の性能がそのまま見えている。
  45. 45. conv2 スループット比較 45
  46. 46. 実行時間比較 46
  47. 47. データ並列化まとめ データ並列化で推論処理を高速化 ✔ データ並列化前後で 1.81 倍の高速化 あるデータの計算を複製、並列化し全体の処理を高速化 データ並列化に向けた pragma を使用 ✔ unroll, array_partition 計算の複製はハードウェアリソースの増加に直結 LUT 数などだけでなく、メモリのポート数にも注意 47
  48. 48. その他最適化 全結合層の最適化と層間バランス
  49. 49. 全結合層の最適化と全体の最適化について 全結合層の最適化 ✔ 畳み込み層が速くなったので全結合層が遅くなった。 ✔ 畳み込み層と同様にループ並列化、データ並列化を実施 全体の最適化 ✔ 層間のバランスを取るためのチューニングを実施 ✔ 効率的なタスク並列を実現 49
  50. 50. conv1, conv2, fc1 の処理性能がほぼ同じに 50
  51. 51. 最終結果とここまでの高速化の変遷 51
  52. 52. 性能、リソース消費まとめ ベースラインの 417.87 倍の高速化を達成 以下の 2 手法の効果が大きい (本ウェビナー範囲外😥) ✔ 外部メモリアクセス削減 ✔ 最終版 (全結合層の高速化+層間のバランス) リソース消費の増加量は、400 倍の高速化に対し 2~3 倍程度に抑制 ✔ タスク並列化、ループ並列化はほとんどリソース増加なし 52
  53. 53. 全体のまとめ Naive な実装の CNN を対象に 3 つの並列性を抽出し高速化 ✔ タスク並列性:dataflow, stable, ap_ctrl_chain ✔ ループ並列性:pipeline ✔ データ並列性:unroll, array_partition プラグマを挿入するだけである程度の高速化が可能 さらなる高速化を目指すには以下が必要 ✔ ハードウェア実装を考慮したコーディング ✔ Vivado/Vitis HLS への優しさ 53
  54. 54. より現実的なモデルに向けて 今回の題材は非常に小さなデータセット (MNIST) ✔ 入力も重みも全部内部 RAM に入ってしまうほどの小ささ 現実的な問題では画像の解像度、 ネットワーク規模は文字通り桁違い ✔ 例) ResNet-101: 解像度 224x224、層数 101 さらなる並列度の抽出、計算ユニットの複製、 計算そのものを減らすこと (枝刈り、量子化) などの工夫が必要 54
  55. 55. Thank you.

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

×