FC2カウンター FPGAの部屋 (目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る5(チューンナップ2)
FC2ブログ

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

FPGAの部屋

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

(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る5(チューンナップ2)

(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る4(チューンナップ1)”の続き。

MNIST データセットを使った2層の全結合層を持ったニューラル・ネットワークについて、目標の1クロック毎に結果を出力できるようにチューンナップしようとしたが、large runtime and excessive memory usage エラーになってしまった。今回は、そのエラーを回避するために 1/4 の入力数に変更して高位合成してみよう。

入力数を 784 から 196 つまり 14 x 14 に変更してみよう。
mnist_nn.cpp に一部を示す。

int mnist_nn(ap_ufixed<8, 0, AP_TRN, AP_WRAP> in[196], ap_fixed<13, 7, AP_TRN, AP_WRAP> out[10]){
#pragma HLS PIPELINE II=1
#pragma HLS ARRAY_PARTITION variable=af2_bias complete dim=0
#pragma HLS ARRAY_PARTITION variable=af2_weight complete dim=0
#pragma HLS ARRAY_PARTITION variable=af1_bias complete dim=0
#pragma HLS ARRAY_PARTITION variable=af1_weight complete dim=0
#pragma HLS ARRAY_PARTITION variable=out complete dim=0
#pragma HLS ARRAY_PARTITION variable=in complete dim=0

    ap_fixed<13, 7, AP_TRN, AP_WRAP> dot1[20];
#pragma HLS ARRAY_PARTITION variable=dot1 complete dim=1
    ap_fixed<13, 7, AP_TRN, AP_WRAP> dot2[10];
#pragma HLS ARRAY_PARTITION variable=dot2 complete dim=1

    af1_dot1: for(int col=0; col<20; col++){
        dot1[col] = 0;
        af1_dot2: for(int row=0; row<196; row++){
            dot1[col] += in[row]*af1_weight[row][col];
        }
        dot1[col] += af1_bias[col];

        if(dot1[col] < 0)    // ReLU
            dot1[col] = 0;
    }

    af2_dot1: for(int col=0; col<10; col++){
        dot2[col] = 0;
        af2_dot2: for(int row=0; row<20; row++){
            dot2[col] += dot1[row]*af2_weight[row][col];
        }
        dot2[col] += af2_bias[col];

        if(dot2[col] < 0)    // ReLU
            dot2[col] = 0;
        out[col] = dot2[col];
    }

    return(0);
}


これで合成した。結果を示す。
all_deploy_afnet4mnist_21_190401.png

Latency は 33 クロックだが、Interval は 1 クロックになった。目標達成だ。
DSP48E は 607 個で 168 % 、LUTが 137589 個で 194 % でオーバーしているので、Ultra96 には実装できない。

さて、次に 10 回連続でニューラル・ネットワークの推論をさせてみよう。
mnist_nn.cpp の一部を示す。

int mnist_nn(ap_ufixed<8, 0, AP_TRN, AP_WRAP> in[1960], ap_fixed<13, 7, AP_TRN, AP_WRAP> out[100]){
#pragma HLS ARRAY_PARTITION variable=af2_bias complete dim=0
#pragma HLS ARRAY_PARTITION variable=af2_weight complete dim=0
#pragma HLS ARRAY_PARTITION variable=af1_bias complete dim=0
#pragma HLS ARRAY_PARTITION variable=af1_weight complete dim=0
#pragma HLS ARRAY_PARTITION variable=out complete dim=0
#pragma HLS ARRAY_PARTITION variable=in complete dim=0

    ap_fixed<13, 7, AP_TRN, AP_WRAP> dot1[20];
#pragma HLS ARRAY_PARTITION variable=dot1 complete dim=1
    ap_fixed<13, 7, AP_TRN, AP_WRAP> dot2[10];
#pragma HLS ARRAY_PARTITION variable=dot2 complete dim=1

    itre_10: for(int i=0; i<10; i++){
#pragma HLS PIPELINE II=1
        af1_dot1: for(int col=0; col<20; col++){
            dot1[col] = 0;
            af1_dot2: for(int row=0; row<196; row++){
                dot1[col] += in[row+i*196]*af1_weight[row][col];
            }
            dot1[col] += af1_bias[col];

            if(dot1[col] < 0)    // ReLU
                dot1[col] = 0;
        }

        af2_dot1: for(int col=0; col<10; col++){
            dot2[col] = 0;
            af2_dot2: for(int row=0; row<20; row++){
                dot2[col] += dot1[row]*af2_weight[row][col];
            }
            dot2[col] += af2_bias[col];

            if(dot2[col] < 0)    // ReLU
                dot2[col] = 0;
            out[col+i*10] = dot2[col];
        }
    }

    return(0);
}


このコードで合成した。結果を示す。
all_deploy_afnet4mnist_22_190401.png

Latency の Detail -> Loop を見るとInitiation Interval の Target が 1 クリックで、 achieved も 1 クロックであるのが分かる。
リソース使用量は DSP48E は 607 個 168 % で変わらないが、 LUT が 147368 個で 208 % と増えてしまっている。

これで、Vivado HLSで1クロック毎に結果を出力できるNNを作るという目標は達成できたのだが、通常のMNIST のニューラル・ネットワークだと、Vivado HLS が large runtime and excessive memory usage エラーになって音を上げてしまう。ランタイムが大きくてもやってくれれば良いのだが。。。

なお、このmnist_nn.cpp を合成する時に”ARRAY_PARTITION COMPLETE has exceeded the threshold (1024)”のエラーが出てしまう。
” ARRAY_PARTITION COMPLETE has exceeded the threshold (1024)”の解決策”を参照しながら、maximum_size に 2000 を入れたら問題なく合成ができた。
all_deploy_afnet4mnist_23_190330.png

all_deploy_afnet4mnist_24_190330.png

  1. 2019年04月01日 04:26 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/4487-3cd1703b
この記事にトラックバックする(FC2ブログユーザー)