FC2カウンター FPGAの部屋 TensorFlow + Kerasを使ってみた16(C コードの合成、ビット幅の削減)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

TensorFlow + Kerasを使ってみた16(C コードの合成、ビット幅の削減)

TensorFlow + Kerasを使ってみた15(飽和演算と通常の演算)”の続き。

前回は、畳み込み層に”Vivado HLS の任意精度固定小数点データ型の飽和演算”でテストした演算後の値を飽和演算し、また全結合層では内積の演算に飽和演算を用いる実装と、今まで通りにすべての演算に飽和演算を用いない場合について検証した。今回は、その飽和演算ありと飽和演算なしの2つの実装を合成して、リソース使用量を比較して見た後で、演算のビット幅を小さくして、C シミュレーション結果とC コードの合成結果を見ていこう。

最初に飽和演算なしの実装(mnist_conv_nn10_hlss_k_org)のC コードの合成結果を見る。
tensorflow_keras_73_180610.png
tensorflow_keras_74_180610.png

Latency は min が 202936 クロックで、 max が 204376 クロックだった。これは、100 MHz クロックを使用すると max の場合では、約 2.04 ms となった。
リソース使用量は、BRAM_18K が 130 個、DSP48E が 175 個、FF が 9005 個、LUT が 16391 個だった。

次に、飽和演算あり(mnist_conv_nn10_hlss_k)の実装のC コードの合成結果を見る。
tensorflow_keras_75_180610.png
tensorflow_keras_76_180610.png

こちらのLatency の min は 217336 クロックで max は 218776 クロックだった。100 MHz クロックだと max で 2.19 ms となった。飽和演算なしと比較すると、max 値で 217336 / 204376 ≒ 1.063 倍だった。
リソース使用量は、BRAM_18K が 130 個、DSP48E が 175 個は飽和演算なしと変化がないが、FF の 9168 個と LUT の 19109 個は飽和演算なしよりもリソース使用量が多かった。

次に演算のビット幅を縮小してみよう。
次に示す演算のビット幅でCNN の演算を行った。

#define INPUT_CHANNELS 1
#define INPUT_BIT_LENGTH 9
#define INPUT_INTEGER_LEN 1

#define CONV_BIT_LENGTH 8
#define CONV_INTEGER_LEN 3
#define CONV_CHANNELS 10
#define CONV_MID_BIT_LENGTH 13
#define CONV_MID_BIT_INTGER_LEN 3

#define AFFINE_BIT_LENGTH 11
#define AFFINE_INTEGER_LEN 5

#define OUTPUT_BIT_LENGTH 12
#define OUTPUT_INTEGER_LEN 7


演算のビット幅を 2 ビット減らしてみた。ただし整数部のビット幅はいじっていないので、飽和演算あり、飽和演算なしで同様のエラーになるはずである。
飽和演算ありと飽和演算なしの実装の C シミュレーション結果を示す。
tensorflow_keras_77_180610.png

飽和演算ありと飽和演算なしどちらも、HW_ERROR_COUNT = 23, SW_ERROR_COUNT = 15 だった。
エラー内容を示す。なおこのエラー内容も、飽和演算ありと飽和演算なしで同一だった。

id = 18, max_id_ref = 3, max_id_sw = 8
id = 115, max_id_ref = 4, max_id_sw = 9
id = 151, max_id_ref = 9, max_id_hw = 8
id = 184, max_id_ref = 8, max_id_hw = 3
id = 217, max_id_ref = 6, max_id_hw = 5
id = 247, max_id_ref = 4, max_id_sw = 2
id = 321, max_id_ref = 2, max_id_sw = 7
id = 324, max_id_ref = 0, max_id_hw = 6
id = 340, max_id_ref = 5, max_id_hw = 3
id = 340, max_id_ref = 5, max_id_sw = 3
id = 406, max_id_ref = 5, max_id_hw = 9
id = 445, max_id_ref = 6, max_id_sw = 0
id = 448, max_id_ref = 9, max_id_hw = 8
id = 449, max_id_ref = 3, max_id_sw = 5
id = 508, max_id_ref = 6, max_id_hw = 5
id = 547, max_id_ref = 2, max_id_hw = 3
id = 551, max_id_ref = 7, max_id_hw = 3
id = 582, max_id_ref = 8, max_id_hw = 2
id = 582, max_id_ref = 8, max_id_sw = 2
id = 619, max_id_ref = 1, max_id_hw = 8
id = 619, max_id_ref = 1, max_id_sw = 8
id = 625, max_id_ref = 6, max_id_hw = 4
id = 655, max_id_ref = 8, max_id_hw = 3
id = 658, max_id_ref = 7, max_id_hw = 4
id = 659, max_id_ref = 2, max_id_hw = 1
id = 659, max_id_ref = 2, max_id_sw = 1
id = 674, max_id_ref = 5, max_id_hw = 3
id = 684, max_id_ref = 7, max_id_hw = 3
id = 684, max_id_ref = 7, max_id_sw = 3
id = 685, max_id_ref = 8, max_id_hw = 2
id = 723, max_id_ref = 0, max_id_hw = 4
id = 738, max_id_ref = 2, max_id_hw = 8
id = 813, max_id_ref = 9, max_id_sw = 8
id = 846, max_id_ref = 7, max_id_hw = 9
id = 870, max_id_ref = 6, max_id_hw = 5
id = 883, max_id_ref = 3, max_id_sw = 5
id = 947, max_id_ref = 8, max_id_sw = 9
id = 965, max_id_ref = 6, max_id_sw = 0
HW_ERROR_COUNT = 23, SW_ERROR_COUNT = 15


次に、演算ビット幅を縮小したままC コードの合成を行った。
まずは、飽和演算なしからC コードの合成結果を示す。
tensorflow_keras_78_180611.png
tensorflow_keras_79_180611.png

Latency は min が 202936 クロックで、 max が 204376 クロックだった。これは、100 MHz クロックを使用すると max の場合では、約 2.04 ms となる。これはビット幅を変更する前と同じだった。
リソース使用量は、BRAM_18K が 130 個、DSP48E が 175 個、FF が 9005 個、LUT が 16391 個だった。これはビット幅を変更する前からすると、FF が約 88.2 % 、LUT が約 91.4 % に減少している。

次に飽和演算ありの C コードの合成結果を示す。
tensorflow_keras_80_180611.png
tensorflow_keras_81_180611.png

Latency の min は 217336 クロックで max は 218776 クロックだった。100 MHz クロックだと max で 2.19 ms となった。やはり、こちらもビット幅を変更する前と同一だった。
リソース使用量は、BRAM_18K が 130 個、DSP48E が 175 個は飽和演算なしと変化がないが、FF の 8107 個と LUT の 17641 個だった。これはビット幅を変更する前からすると、FF が約 88.4 % 、LUT が約 92.3 % に減少している。

ビット幅を縮小しても思ったよりリソース使用量の縮小がなかったので、以前の下に示す演算ビット幅で行こうと思う。

#define INPUT_CHANNELS 1
#define INPUT_BIT_LENGTH 9
#define INPUT_INTEGER_LEN 1

#define CONV_BIT_LENGTH 10
#define CONV_INTEGER_LEN 3
#define CONV_CHANNELS 10
#define CONV_MID_BIT_LENGTH 16
#define CONV_MID_BIT_INTGER_LEN 3

#define AFFINE_BIT_LENGTH 13
#define AFFINE_INTEGER_LEN 5

#define OUTPUT_BIT_LENGTH 12
#define OUTPUT_INTEGER_LEN 7


また、飽和演算ありと飽和演算なしだが、現在の整数ビット幅を維持できれば、飽和演算ありと飽和演算なしとエラー数も変化がないので、リソース使用量の少ない飽和演算なしで行くことにする。
  1. 2018年06月11日 05:04 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/4194-b0f72a09
この記事にトラックバックする(FC2ブログユーザー)