編集:
すべての提案をありがとう。これを元の質問にもっとうまく入れるべきだったので、明確でなくて申し訳ありません。行 prod[0] <= prod[0] + input[0] x weight1[i]; prod[25] までが 200 クロック サイクルにわたって実行されます。ただし、26 の乗算は並行して行われます。一度に多すぎるのでしょうか、それとも 1 クロック サイクルで 1 つの乗算 (32 ビット x 32 ビット) を実行する必要がありますか? つまり、200 x 26 クロック サイクルで 200 x 26 のすべての乗算を行う必要がありますか?
また、全体をパイプライン処理するための 6 つのステージがあります。
26 の行列乗算を並列で 200 回 (200 クロック サイクル) 繰り返します。
約 200 要素の LUT で構成されるアクティベーション モジュールが処理を実行し、結果を送信できるように、制御フラグを設定します。ニューロンごとに 25 回繰り返されます (25 クロック サイクル以上)。
フラグをリセットして起動機能を停止します。カウンターとすべてをリセットして、次のパートの準備をします。
3 つの行列乗算を並列に 25 回 (25 クロック サイクル) 繰り返します。
アクティベーション関数を再度呼び出します。
6 から得られた 3 つの値の最大値を見つけて、出力がどうあるべきかを判断します (これは分類問題です)。
上記のステージと、1 クロック サイクルあたりの乗算回数 (ステージ 1 で 25、ステージ 2 で 3) は問題ありませんか?
それとも、ステージ 2 を 200x25 クロック サイクルで実行し、ステージ 4 を 10x3 クロック サイクルで実行するようにやり直す必要がありますか?
助けてくれて、アドバイスしてくれたみんな、どうもありがとう。
ファイサル
オリジナル:
人工ニューラル ネットワークのフィードフォワード アルゴリズムのモジュールをコーディングしてシミュレートしました。合成ツールには長い時間がかかります (Synopsys DCS および Xilinx ISE 14.4)...現在 9 時間以上実行されているので、本当に気分が悪いです! ただし、シミュレーション結果は正しいです。
私は新しい設計のアイデアを (メッセージの最後に) 持っていますが、それが私の現在の実装 (以下を参照) よりも効率的かどうか、またはそれよりも悪いかどうかを確認するために、経験豊富な人に実行してもらいたいと考えていました。多くの算術演算がより効率的ですか?
ネットワークの背景:
入力層には 200 の入力があり、
隠れ層には 25 個のニューロンがあり、
出力レイヤーには 3 つの出力がありました。
Verilog コードのアイデア: アルゴリズム全体を実装するモジュールは 1 つしかありません。
- 最初のステップは、入力 (200 個) に各ニューロン (25 個のニューロンがある) の重み (200 個) を掛けることです。
prod[0] <= prod[0] + input[0] x weight1[i]; i = 0 to 200-1
.......
prod[25] <= prod[25] + input[25] x weight1[i]; i = 0 to 200-1
そして、200 個の入力のそれぞれについて、上記のことを 200 回繰り返します。25 個のニューロンすべての計算を同時に行っています。
次に、上記の結果に対して ANN アクティベーション関数が呼び出されます。これは、200 近くの要素を持つ LUT を使用して行われます (case ステートメントを使用しました)。これを行うために、別の activation.v ファイルを作成し、ニューロンごとに 25 回インスタンス化する必要がありました。
次に、上記の結果に最後の 3 つのニューロンの重みを掛けます。
prod_2[0] <= prod_2[0] + prod[0]*weight2[i]; i = 0 to 25-1;
prod_2[1] <= prod_2[1] + prod[0]*weight2[i]; i = 0 to 25-1;
prod_2[2] <= prod_2[2] + prod[0]*weight2[i]; i = 0 to 25-1;
そして、25 個の prod 入力のそれぞれについて、上記を 25 回繰り返します。3 つの出力ニューロンすべてに対して同時に計算を行っています。
- 最後のステップは、prod_2[0 から 2] で sigmoid を呼び出すことです。このために、さらに 3 つのアクティベーション モジュールをインスタンス化する必要がありました。
シミュレートされた結果は素晴らしいです。しかし、おそらく恐ろしく非効率です!!!!
それで、これがより良いアイデアかどうか知りたいですか?
Top_Module -> Neuron -> 乗算と活性化
一番上のモジュールはニューロン関数を呼び出し (これには 28 個のニューロンをインスタンス化する必要があります!)、関連する入力と重みをそれに渡します。ニューロン関数は乗算モジュールを呼び出します (最初の部分には 200 個、2 番目の部分には 25 個必要です)。ニューロン関数は次に、上記の 200 個の結果 (パート 2 では 25 個) を追加し、活性化関数を呼び出します。出力は最終的に Top_Module に戻ります。
私の質問:
これは、1 つのモジュールですべてを実行していた以前の実装よりも効率的ですか?
28 個のニューロンをインスタンス化し、各ニューロンが 200 個の乗算モジュールをインスタンス化することは悪いことですか、それとも良いことですか?
Synopsys Design Compiler が 12 時間もかからないようにコードを効率化する他のアイデアはありますか?
これを行うと、各ニューロンには 200 の入力と、その入力ポートとなる 200 の重みがあります。Verilog モジュールが互いに配列を渡すことができるとは思いませんでした。そうでない場合、配列を渡す代わりに、手動で 400 個のポートすべてを書き出す必要がありますか?
奇妙な質問で申し訳ありませんが、私は合成の概念全体に不慣れで、これらのツールがモジュールをインスタンス化する方法を知りたいですか?
ありがとう、
ファイサル。