Ryuz's tech blog

FPGAなどの技術ブログ

リアルタイムコンピューティング再考

はじめに

私のサイトでは 1998年に μITRON仕様の HOS-80をリリースさせていただいたのを出発点に、リアルタイムコンピューティングを扱ってきました。

いくつかの活動や成果物は私のWebサイトなどにも貼っておりますし、いろんな個人的な発表やTwitterなどでも述べてきた次第なのですが、あまりちゃんとまとめたことが無かった気がするので、少しまとめておこうかと思った次第です。

リアルタイムコンピューティングとは何か?

きちんとした定義もありそうですが、とりあえず私の中の理解では

「現実世界で発生したイベントに対して、計算による応答反応を決まった時間内に実施できることが保証できる計算体系」

がそれではないかと思う次第です。

すなわち

  1. 入力/出力ともに現実世界とインターフェースしている
  2. 演算リソースの時間割り当てを保証する仕組みがある

の2点が重要となってきます。特に1つ目の特性から、これは必ず エッジコンピューティング になります。現実で起こった事象に対して、現実に対して応答しなければ、リアルタイムである事の意味がありません。

2つ目の特性について、トランジスタが高価でCPU自体がシングルコアが当たり前だった時代は、1個しかないCPUリソースを活用する上でスケジューリング理論が極めて重要でした。所謂リアルタイムOSがその時間保証の肝となっているわけです。

一方で、現在のようにマルチコアや並列計算が当たり前になってくると少し事情が変わってきたように思います。エッジ向けの SoC の中にはノンリアルタイムOS用と、リアルタイムOS用に複数のコアをアサインできるケースも増えているかと思います。

そういった中で、私が特に思い入れが強いのがFPGAです。CPUと異なって演算リソースが、設計空間上で固定されていませんので、時空間のすべてを使ってパズルを解くような設計を楽しむことができます。

ノイマン型でのリアルタイムコンピューティング

では、FPGAを使って、リアルタイムコンピューティングをやろうとしたときのアーキテクチャってどうなるのか? という話なのですが、私の考える基本アーキテクチャは下記のとおりです。

f:id:Ryuz88:20210711160700p:plain
当サイトの考えるリアルタイム計算機

要点としては

  • 入出力とも現実世界と直接的に繋がっている
  • 今ある情報から今出力できる最善の出力を生成できる

ということを基本にした計算機です。

状態空間モデルそのものであり、IIRフィルタのような形になるわけですが、どんな計算を行い、何を記録しておくかが自由に決められますので、これはこれでれっきとしたチューリング完全な計算機となります。

ことリアルタイム性に関しては、メモリに対しての演算として定義されているノイマン型コンピュータのアーキテクチャは、一度メモリを介さないと現実世界とインターフェースできないため、これは一つのノイマンボトルネックだと感じております。 信号処理においてメモリは遅延素子であり、 Z^{-1} 演算子として、情報を未来に送るという積極的な使い方をする分にはいいのですが、計算アーキテクチャの都合で形式変換の為に経由させる何の計算も行わずに遅延だけを発生させてしまいます。

もちろんFPGAなので、従来と同じCPUのような構成も作ろうと思えば作れてしまうし、ノイマン型でなくてもメモリに対する演算コアは沢山ありますので、私的な分類として、アクセラレータ型とフィルタ型のような呼び方で分類してみました。

f:id:Ryuz88:20210711161840p:plain
アクセラレータ型とフィルタ型

フィルタ型演算器の考え方

リアルタイムコンピューティングでは入力データを最短時間で出力に反映させたいと言うのが大前提です。

したがって、入力データはスループット 1/1 で最新データを出力まで処理したいという事になります。

という事は、クリティカルパスに対して、演算はすべて回路に一度に載せきってしまい、かつ、演算器の再利用は基本的に行わないという事になります。

これはどういうことかと言うと、係数は常にロード済みの演算しかしないという事であり、演算は部分部分で個別最適化して構わないという事になってきます。

この分部分で個別最適化して構わないというのはFPGAの得意なところでして、必要なところで必要な精度の計算をすればいいわけです。

また、リアルタイム性の観点では、サンプリングレートは高ければ高いほどよく、サンプリングレートが高ければ、1bit⊿Σのようによりバイナリに近い精度での演算で性能が担保できる世界に近づきます。

バイナリに近づけば近づくほど、FPGAが得意な領域になっていき、演算効率が上がっていきます。

LUT-Network の最近の取り組み

ちなみに今ちょうど、BinaryBrain の次のフェーズに向けてこんなネットワークが学習できないか企み中です。

(あくまで概念図なので実際にはミップマップを作っていくようなPoolingとUp-sampleのループを作らないといけない気はしますが)

f:id:Ryuz88:20210711154948p:plain
1つ前の結果を使うIIRフィルタ的ネットワーク

LUT-Network の特徴として、すべての係数をLUTのテーブルとしてロードする というものがあります。そしてクリティカルパス内に Pooling 層を入れない限り、すべてのLUT が 100% 演算に活用されます。

  • 入力と出力が計算を伴わないメモリを排して回路として最短で接続される
  • バイナリ演算でありFPGAのLUTを効果的に演算に活用できる
  • 最短回路でありながらそのまま学習できる

という特徴があるわけです。

加えて今回は、1つ前の結果を残す事を企んでおりIIRフィルタ的構成にしているわけですが、MaxPooling をここに入れる事で、古い情報ほど 1/4, 1/16, 1/64... と縮小されていくので、U-Net のようにグローバルな情報と、部分の情報を重ね合わせながら処理できる可能性があります。現実世界も一定のダイナミクスを持って動いているので、サンプリング周波数が十分であれば過去と現在は高い相関性を持っており、古い情報程縮小されていくというのはいろいろとうまく嵌ってくれれば面白い結果を出してくれそうです。

また、今回は2次元の画像に適用しようとしていますが、もっと1次元的なデータに使う事も出来る可能性があります。基本的に状態空間モデルですので、どんな計算をして何を記録して何を記録するかは、状態方程式や、状態変数に相当する筈です。ここを機械学習に丸投げと言うのは強化学習と同じことなのですが、LUT-Networkの場合は1層の計算が1サイクルで出来てしまいますので、例えば 200~300MHz ぐらいで、遅延時間も 10ns ぐらいのフィルタが学習できてしまったりする可能性があります。

そうなると、そのあたりの帯域で制御しているような対象に対して、データさえ集まれば、システム同定的なものを機械学習に丸投げしたうえで、そのまま実装できてしまう可能性も出てきたりしないかと夢を膨らませてみたりもしています。

一方で、RNNの学習はいろいろと環境面では面倒な部分が多く、学習時間やGPUのメモリの制約もいろいろと出てくるので、まだまだ越えなければいけないハードルが多数ありそうです。

どこまで思惑通りできるかは未知ですが、少しは実用性のあるものに近づければ嬉しいなと思っております。

追記(実装案)

実際には U-Net のように階層的なスケールの Pooling と Upsampling を行うには、少し複雑な構成が必要にあると考えられる。しかしながらスケール不変の認識をする分にはスケールが変わっても回路もパラメータも共有化できるはずなので、ミップマップ的なメモリの使い方をすれば 1/3 の帯域でスケール対応できるはずだ(多分)。

ビデオ信号が 2割ほどブランキングがあれば回路1個ですべて賄えそうな気もするが、2並列にしておけばひとまずマルチスケールが狙えるのではないだろうか?

1フレーム前の情報で4倍の広さ、2フレーム前の情報で16倍の広さと、面積が4倍づつスケールしていくので、十分なオーバーサンプリングを前提としているLUT-Netであれば、認識の補助情報として過去フレームを使う分には問題ない気がしている。

f:id:Ryuz88:20210711222622p:plain
実際の実装案