リスト6は推論部分を並列化するために書き直したコードです。先に説明した通り、実行順序に依存したコードを全て排除したものになります。
そのために前回は使いまわしていたsum変数(レジスタ)をneurosのドット数の25個分用意しました。そこにノンブロッキング代入で値を入れていきます。これを25回繰り返すことで推論結果である5×5の文字のドットを決定します。25ドットの1と0を決めるのは50行のコードです。コードとしてはちょっと冗長すぎますが執筆時はこの記述方法しか思い浮かびませんでした。読者の皆さんでもっとスマートな書き方をご存じの方がいらっしゃいましたら編集部までご一報ください。
23: for (k=0;k<25;k=k+1) begin 24: sum[k]<=((neuros[0]==1)?links[25*k+0]:(-links[25*k+0]))+ 25: ((neuros[1]==1)?links[25*k+1]:(-links[25*k+1]))+ 26: ((neuros[2]==1)?links[25*k+2]:(-links[25*k+2]))+ 27: ((neuros[3]==1)?links[25*k+3]:(-links[25*k+3]))+ 28: ((neuros[4]==1)?links[25*k+4]:(-links[25*k+4]))+ 29: ((neuros[5]==1)?links[25*k+5]:(-links[25*k+5]))+ 30: ((neuros[6]==1)?links[25*k+6]:(-links[25*k+6]))+ 31: ((neuros[7]==1)?links[25*k+7]:(-links[25*k+7]))+ 32: ((neuros[8]==1)?links[25*k+8]:(-links[25*k+8]))+ 33: ((neuros[9]==1)?links[25*k+9]:(-links[25*k+9]))+ 34: ((neuros[10]==1)?links[25*k+10]:(-links[25*k+10]))+ 35: ((neuros[11]==1)?links[25*k+11]:(-links[25*k+11]))+ 36: ((neuros[12]==1)?links[25*k+12]:(-links[25*k+12]))+ 37: ((neuros[13]==1)?links[25*k+13]:(-links[25*k+13]))+ 38: ((neuros[14]==1)?links[25*k+14]:(-links[25*k+14]))+ 39: ((neuros[15]==1)?links[25*k+15]:(-links[25*k+15]))+ 40: ((neuros[16]==1)?links[25*k+16]:(-links[25*k+16]))+ 41: ((neuros[17]==1)?links[25*k+17]:(-links[25*k+17]))+ 42: ((neuros[18]==1)?links[25*k+18]:(-links[25*k+18]))+ 43: ((neuros[19]==1)?links[25*k+19]:(-links[25*k+19]))+ 44: ((neuros[20]==1)?links[25*k+20]:(-links[25*k+20]))+ 45: ((neuros[21]==1)?links[25*k+21]:(-links[25*k+21]))+ 46: ((neuros[22]==1)?links[25*k+22]:(-links[25*k+22]))+ 47: ((neuros[23]==1)?links[25*k+23]:(-links[25*k+23]))+ 48: ((neuros[24]==1)?links[25*k+24]:(-links[25*k+24])); 49: end 50: for (k=0;k<25;k=k+1) neuros[k]<=(sum[k]>0)?1:0;
ここでは推論部分を並列化していない場合と並列化した場合について、FPGAのリソースの消費と実行速度を検証したいと思います。次に示すリスト7は、本連載で使用しているFPGA開発ボード「Tang Nano 9K」で利用できるGOWIN SemiconductorのIDE(統合開発環境)でシンセサイズした後に出力される“Resource Utilization Summary”からの抜粋です。
リスト7の中身は、並列化していないコードのFPGAのリソース消費に関するレポートです。オリジナルのレポートに行番号などは付いていないのですが、説明の便宜上行番号をけました。1行目はFPGA内のロジック系、いわゆる組み合わせ回路の消費具合を示しています。このレポートの場合、ロジック系リソースはLUTsとALUsとなっていますが、LUT(Look Up Table)はルックアップテーブルといわれる回路ユニットです。そしてALU(Arithmetic and Logic Unit)は演算を担う回路ユニットです。
このリスト7を見る限り、推論部分を並列していない場合、Tang Nano 9Kに搭載されているリソースのうちLUTとALUの合計が18%となります。あと4行目にあるレジスタ系のリソースを見ると、レジスタを使うとFF(Flip Flop)が消費されます。これらについては1%の消費にとどまっています。
Resource Usage Utilization 1: Logic 1537(247 LUTs, 1290 ALUs) / 8640 18% 2: Register 51 / 6693 1% 3: --Register as Latch 0 / 6693 0% 4: --Register as FF 51 / 6693 1% 5: BSRAM 0 / 26 0%
リスト8は、このコードで実行できる最大周波数を示しています。“Actual Fmax”の欄にある通り、6.4(MHz)で実行可能ということを示しています。
Max Frequency Summary: No. Clock Name Constraint Actual Fmax Logic Level Entity 1 clk 50.0(MHz) 6.4(MHz) 139 TOP
次のリスト9は並列化したコードのFPGAのリソース消費に関するレポートです。レジスタ消費が多少増えているところでしょうか。それ以外はあまり遜色がないですね。
Resource Usage Utilization Logic 1499(209 LUTs, 1290 ALUs) / 8640 17% Register 202 / 6693 3% --Register as Latch 0 / 6693 0% --Register as FF 202 / 6693 3% BSRAM 0 / 26 0%
リスト10は並列化したコードで実行可能な最大周波数を示しています。“Actual Fmax”が82.2(MHz)になっており、並列化する前の6.4(MHz)と比べて顕著に改善されていることが分かります。
Max Frequency Summary: No. Clock Name Constraint Actual Fmax Logic Level Entity 1 clk 50.0(MHz) 82.2(MHz) 11 TOP
本記事を執筆中にうれしいニュースが飛び込んできました。「ニューラルネットワークによる機械学習を可能にする基礎的発見と発明」の功績により、米プリンストン大学 名誉教授のジョン・ホップフィールド(John Hopfield)氏に2024年のノーベル物理学賞が授与されることが決まりました。本連載でも同氏のホップフィードネットワークを用いています。
Copyright © ITmedia, Inc. All Rights Reserved.