2017年02月01日

1月度概況

access1701.jpg1月度の弊社HPへのアクセスは図のようになりました。昨年7月に、ブログをこちらに移動して以来アクセスは急増していたのですが、今年に入ってから更に大きく増加しております。この理由は明らかではありませんが、昨年12月にブログ“comfort.saloon.jp”にSNSボタンを設置したことが奏功しているのかもしれません。

pv1701.jpg下のグラフがcomfort.saloon.jpへのアクセスで、太い点線は過去7日間の移動平均を示しています。これまでも大きな変動はあるのですが、本年1月の上昇は、変動というよりもトレンドの変化のようにみえます。実のところがどうであるかは、もう少し様子を見ないとわからないのですが。

今月度は、コンサルティング業務も一段落し、CodeSqueezerの開発に時間を割くことができました。

現在注力しているのが、リンクリストを全面的に採用した言語mhdlの開発で、1月度はパーサ部分のコーディングをいたしました。

パーサは、数式記述を項(class Term)に変換します。項は、先行する演算子(Ope^ pre_ope)、名前(String^ str)、単項演算子のリスト(List^ unary_opes)、同じ優先順位の演算子で結ばれた下位の項のリスト(List^ flat_expr)からなります。

パーサで処理した結果、名前がブロック配置の場合、flat_exprには引数が置かれます。演算子は全て、ブロック配置に変換されます。また、演算子のレベルやかっこによる演算の優先順位は、flat_exprを用いた項の木構造に変換されます。

新しいmhdlは、複数のリンクを束ねたリンクリストを扱いますが、パーサの段階では、リンクもリンクリストも同等に扱い、これに続くブロックの配置とリンクによる接続の段階でリンクリストを個々のリンクに分解します。

以下、いくつかの演算について、ソースコードとこれをブロック配置に変換した結果を示します。

代入文は、ブロック"_let"の配置に変換されます。
  ソース:x = y
 ブロック:_let ( x , y )

mhdlは複代入文も許されます。_letの引数は、最も右側の引数にのみ式を置くことが許され、その他の引数はリンクでなければいけません。_letは最終的には引数間のリンク接続に変換され、実際のブロックが配置されるわけではありません。

  ソース:x = y = z
 ブロック:_let ( x , y , z )

加減算は_sumというブロックで処理されます。加算と減算を区別するため、二番目以降の引数にはbool invとint selという修飾子が与えられます。これをソースコード上で表示するため、引数の区切り記号として次の6種類を用います。

“,”:inv = false, sel = 0
“-,”:inv = false, sel = -1
“+,”:inv = false, sel = +1
“;”:inv = true, sel = 0
“-;”:inv = true, sel = -1
“+;”:inv = true, sel = +1

加減算は次のように変換されます。

  ソース:x = a + b - c
 ブロック:_let ( x , _sum { a , b ; c } )

_sumブロックの最後の引数“c”は、その前の区切り記号が“;”であるため、逆の演算である減算が施されます。

乗除算は_prodブロックによって行われます。加減算と乗除算を組み合わせた式は次のように変換されます。

  ソース:x = a * b + c / d * e、
 ブロック: _let ( x , _sum { _prod [ a , b ] , _prod [ c ; d , e ] } )

二つ目の_prodブロックの引数“d”は除算であるため、その前の区切り記号が“;”となります。乗除算を一つのブロックで行うメリットは、除算を一つにまとめる最適化をコーダの内部でおこなえる点にあります。

今月度読みました書物に、斎藤 康毅著「ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 」があるのですが、同書はPythonを用いて、非常に簡素なソースコードでニューラルネットワークを記述しています。(内容はこちらでご紹介しています。)

ここで用いられているのは、ベクトルや行列の演算を記述するNumPyというモジュールのdot演算なのですが、mhdlのリンクリストはベクトルや行列を扱うことができますので、dot演算に相当する演算子をmhdlに導入しておけば、mhdlでも簡素なコードでニューラルネットワークを記述することが可能となります。

Pythonは、通常のコンピュータ上でCPUによりニューラルネットワークを構成しているのですが、mhdlを用いればFPGA上に並列論理の形でニューラルネットワークを実現することができます。AIは最近ホットな話題でもあり、mhdlの応用分野としてニューラルネットワークの記述が簡単にできるとなれば、営業上の意義も大きく、dot演算に相当する機能はmhdlにもぜひ導入したいところです。

mhdlでdot演算を行う方法として、次の二つを計画しました。

一つは、乗除算の演算子の一つとしてdot演算子を導入することで、このための演算子として数式で使用される“・”に近い記号として“ ' ”を用いることを計画しました。“ ' ”は降階演算子およびリストの接合演算に用いられていたのですが、このための演算子を“ ` ”(バッククォート)に変更することとします。

このようにしておけば、dot演算は乗除算をコード化する_prodコーダの内部で処理すれば良いことになります。

もう一つの手法として、テンソルの記述を許すという方法も計画しています。

テンソルは、共変・反変の二種類があるのですが、単に和の規約を用いるだけなら、あえて二種類を区別する必要はありません。ここでは“#”をテンソルの添え字記号に用いることとします。“#”は、番号記号と呼ばれ、番号を表す添え字に合致しますし、コンパイラに対する指示子であるという意味で、他のコンパイラディレクティブの識別に用いていることとの整合性もとられます。

x = y#i * z#i ⇒ x = y@0 * z@0 + y@1 * z@1

x#i = y#j * z#j#i
⇒ x@0 = y@0 * z@0@0 + y@1 * z@1@0,
  x@1 = y@0 * z@0@1 + y@1 * z@1@1

以下同様に、項の内部に同じ添え字が現れた場合、その添え字を該当する次元の大きさだけ振って演算した結果の和をとることを意味します。なお、この式はリンクリスト全体を表しており、左辺の添え字は右辺の添え字との対応関係を示しているということにご注意ください。

物理的には、共変、反変間での縮約をとることにより基底ベクトルの取り方に依存しない値が得られるという意味があるのですが、計算上はどの要素の積を計算するかというだけのことであり、添え字の順番にのみ意味があって、上付き・下付きの区別は不要です。

しかし、べき乗演算子を“**”に変更するなら、テンソルの添え字に“^”を使うことが可能で、こちらを上付きの添え字に用いることもできます。FortranやPythonとの共通性を考えれば、最初からべき乗演算子には“**”を用いることにしておくのが良さそうです。

テンソルの記法に上付き、下付きの双方を許容することの利点は、物理的に意味のない演算がおこなわれた際に警告メッセージを出力することができる点です。あまり警告メッセージが出ることは、これが不要な人には目障りともなりますので、この機能は環境変数などで動作を切り替えられるようにしておくのが良さそうです。

このように修正した結果を反映したパーサの処理結果を以下に示します。式自体には意味がありません。“**”はべき乗演算子と解釈されて_powブロックに、“#”は“@”と同様、修飾演算子と解釈され、_modブロックに割り当てられています。

  ソース:x = a ** b + c@3 + d#k
 ブロック:_let( x, _sum{ _pow[ a, b ], _mod[ c, 3 ], _mod[ d+, k ] } )

  ソース:x#k^j = a#j^k
 ブロック:_let( _mod{ x+, k+; j }, _mod{ a+, j+; k } )

さて、テンソル記法を導入すれば、さしあたりdot演算子は不要になります。テンソル記法は、行列積(dot)に比べてはるかに自由度が高く、ソースコードも読みやすいという長所があります。一方、コンパイラが複雑になることは難点です。

さしあたり、パーサの段階では、“.”や“@”と同じレベルの修飾演算子として“#”および"^"を解釈して“_mod”ブロックを配置する形としています。_modブロックの引数がこれらの演算子のいずれに該当するかの識別は、invとselによって行っており、上記最後のブロック表記のように、これらの値は区切り記号“,”、“;”、“+,”、“+:”によって表示されています。

dot演算子を導入するかテンソル記法を許容するかにつきましては、この先のコンパイラの複雑さを比較検討したうえで決めたいと考えています。

なお、テンソル記法は、通常のコンパイラにも比較的容易に導入することができます。これにつきましては別途議論いたしました。
posted by 管理人 at 09:29| Comment(0) | TrackBack(0) | 日記
Powered by さくらのブログ