Ryuz's tech blog

FPGAなどの技術ブログ

(おまけ) 続・FPGAに対する誤解

はじめに

前回、FPGAに対する誤解と「どうFPGAを使うべきか」 という記事を書きました。

ちょっと調子に乗ってアンチパターンをイラスト化してみたのでおまけ記事として書いておこうと思います。

本来のFPGAの活用シーン

本来のFPGAの活用シーン

ISPなどの典型ですが、例えばカメラから入ってきた画像を入ってきた順で処理して、そのまま出力するのでとても効率的です。

従来は画像の現像や高画質化処理ノイズ除去などが一般的でしたが、当サイトではこのやり方で「動き計測」とか「AI認識」など、いわゆる CV(Computer Vision) と言われる領域に手広く適用可能であることがだいぶ示せてきていると思います。

CG分野でもこのアーキテクチャでの低遅延ポリゴン描画など示せてきました。

アルゴリズム研究者が使う環境

便利な並列計算機であるGPUの為に、一度データをメモリに溜めて並列化することで並列演算を可能にするように構成したものです。 最先端の半導体製造プロセスで作られた高速大容量の計算能力の恩恵に預かりやすいです。

アルゴリズム研究者が使う環境

画像処理アルゴリズム研究の分野では、多くの領域でAI(深層学習)を使った研究が、特に認識精度(accuracy)の観点で SOTA(state of the art) となっていきました。 必然、非AIの研究はしばし「AIと比べて性能で勝てるの?」と言われてしまう辛い時代になりました。

遅延や電力やコストを置いておけば、GPU上で机上でアルゴリズム精度の研究を行うのは非常に便利ですので、この形で研究されたアルゴリズムが世にあふれることになりました。

もちろん一度メモリに溜めた分遅延は増えますし、コストや電力も増大しますが、「簡単にアルゴリズム実験がいろいろできる」という効率性の前には些細な事です。

これはこれでもちろん世の中をすごく進歩させてくれたのですが、計算機は とにかく AI 性能がいいことだけを求められるようになってきました。

また、遅延等が課題になる分野の研究が置き去りになってしまうという、困ったことも起こっていると思っています。

誤解1:GPU計算をそのままFPGA化してしまうパターン

で、前回記事の続きで、GPU方面からFPGAに興味を持って下さった方が、陥る可能性のアンチパターンその1です。

GPU計算をそのままFPGA化してしまうパターン

FPGAにする(というかハードウェア化する)と高性能化する」と聞いて、今あるGPU用のプログラムをそのままFPGA化しちゃうパターンですね。

往々にして最先端プロセスで作られ、大量の浮動小数点演算器のハードマクロを持ち、GDDRなどの高速メモリを持つGPUに、汎用ロジックで勝てるわけがなく、苦しむことになります。もっとも計算機の勉強にはなると思います。

誤解2:そのままそこだけストリーム化してしまうパターン

そこだけストリーム化してしまうパターン

FPGAはストリーム処理が得意だと聞いて、そのままそこだけストリーム化してしまうパターンですね。

見ての通り、GPUの為に ストリームを並列データに変換してあるものを、再度ストリーム化するというもったいないことになっています。

とはいえ、「原理的には低遅延なリアルタイム処理に持っていけるアルゴリズム」が生まれてくる可能性がある点では、そこまで悲観的ではないです。

ただ、ストリーム処理は「演算器を再利用する」ことが苦手なので、しばし「リソースが足りなくて収まらない」という事になりがちです。

アルゴリズムを出発点にせずに、ハードウェアアーキテクチャを出発点にアルゴリズムを組み立てる という事が必要です。

考えて欲しいこと

冒頭のFPGAに適した処理は、実はアナログ時代の信号処理に似ています。 アナログ時代は、「信号をメモリに溜める」ということが極めて困難だったため、必然的にメモリによる遅延はありませんでしたが、できる演算に限りがありました。

一方で、デジタル時代ではメモリが使えますので過去のデータが自由に使えます。 (なお、未来のデータを使おうとするとそのデータが来るまで処理を遅延させることになります)。

これをアルゴリズムにうまく組み込むことが重要です。

冒頭の絵では入力が一直線に処理されているだけでしたが、下記のようにメモリを追加すれば、低遅延なストリーム処理に加えて、過去のデータへのアクセスが可能になります。

FPGAで効率よくメモリを使うモデル

AI で言えば RNN などのリカレント構造が作れるという事ですね。

以前「リアルタイムコンピューティングのメモリ階層」という記事を書き、こんな絵を載せました。

リアルタイムコンピューティングのメモリ階層

メモリ階層をしっかり考えて、アルゴリズムや学習モデルに反映させるというのは、リアルタイム性を高める上では非常に重要です。

おわりに

AIとGPUの台頭で、本来 FPGA が得意だったリアルタイム性の高い分野が、非リアルタイム分野で研究されていた画像処理研究からだいぶ置いて行かれてしまってているように思います。

  • 計算機アーキテクチャを勉強しないと太刀打ちできない
  • 難しいFPGAプログラミングを覚えなければ実験データすら取れない

などの壁はあるものの、これらを乗り越えれば

  • GPUのことしか考えていない人とは一線を課す新しいモデルの提案
  • みんなが使っているのとは全く異なるオリジナルなデータを使った研究

という差別化が可能です。

大事なのは本質がわからないまま表面的な理解でFPGAを使うと、余計な苦労をした挙句に成果が出ない、なんていうもったいないことになるので、よく理解して、作戦を立ててから使って欲しいという事です。 ちゃんとわかってしまえば、とても楽しいですし、レッドオーシャンで血の涙を流している研究者を横目に、前人未踏のブルーオーシャンを次々開拓していける事でしょう。

若い学生さん、研究者の皆様、FPGAは楽しいし狙い目ですよ!

私は研究者というよりはエンジニア側の人間ですので、「こんな研究があると面白い」という情報交換だったり、「こんな環境なら作れるよ」というったエンジニアリング側からのお手伝いしか出来ないのですが、新しくて面白い研究が生まれてくるのを楽しみにしております。そしてなにより、研究者の方々にも不毛な作業を減らし充実した日々を送っていただけれれば幸いに思う次第です。

FPGAに対する誤解と「どうFPGAを使うべきか」

はじめに

以前、FPGAを始めるときの壁 というのを書かせて頂きました。 また最近、CPUGPU についても幾つか個人的意見を書かせて頂きました。

今日は、今のところ私が最も熱を入れている FPGA について私見を書いてみたいと思います。

FPGA に対する誤解

今、特に GPU などで AI に取り組んでいる方々が「FPGAというデバイスがあるらしい」と興味を持ってこの分野の門をたたいてくださる機会が増えているように思います。

一方で、高価なFPGAボードを買ってきて、ものすごく苦労してベンダーの出しているツール(AI開発ツール含む)を覚え、慣れない難しいプログラムのデバッグに翻弄され、GPU の 10倍も100倍も苦労して作った挙句、GPU の 1/10 も性能が出ず、性能も電力もコストもリアルタイム性すらGPUに負け、いいとこなしで「意味のない研究だったね」と酷評されて終わってしまうなどという、なんとももったいない話ですが、こんなことも往々に起こっているのではないかと思います。

このパターンが発生する理由は意外とシンプルで、「GPU が最も得意とする処理を、わざわざ余分な苦労を追加して FPGA で無理やり同じことをやっている」からに他ならないケースが多い気がします。そして図らずも 苦労して追加した余計な事 が性能を下げてしまっていることに最後まで気づけないケースです。

そしてこのケースを生み出している要因の一つに、FPGAベンダーが「このツールを使えばGPUでやってるAIをFPGAで開発できるよ」と、GPUの代替になるFPGA を声高に宣伝文句にしている点があるように思います。ベンダーのこのうたい文句は、既にFPGAを使いこなしている人に対して「さらに GPU 市場の AIが簡単に取り込めるよ」という意味も含むので一概に批判もできないのですが、一部の人に誤解を生んでいる可能性はあるように思います。

先日、X で FPGA に USBカメラを繋ぐことについて下記のようなことを書いたら少し反響がありました。

FPGAを カメラのISP(Image Signal Processor) 代わりに使うのが便利だとして使っていたような層には、私と同様に FPGA + USBカメラに違和感を感じる方もおられたようです。

一方で、「GPU の代わりに FPGA を使ってみよう」というところから入ってくる方は、今の Jetson を KV260 に置き換えてみたり、PC で GPUボードが挿さっているところに替わりに Alveo や Agilex を挿さしてみるなどの話になるので、「カメラはそのまま今まで使っていたUSBカメラでいいよね」となってしまい、そこに疑問すら持たないわけです(むしろ条件を揃えて比較しないといけないと思ってわざわざGPUの土俵で比較評価をしてしまうわけです)。

一方で、先に違和感を感じた方からすると「そんなことしたらそれだけでFPGAのいいとこ全部死んじゃうよ!」という悲鳴が上がるのもまたよくわかります。

このやり方で FPGA に入ってきた場合、GPU と同じ条件で GPU に勝たないといけないので、実はかなり大変です。

  • GPUの得意な「同時に同じ計算を大量に」が効かないアルゴリズムで戦う
  • INT7以下とか 独自定義の非線形浮動小数点型とか、GPUにない演算を多用する
  • ホモジニアスなGPUに不利でヘテロジニアスな演算器構造を使うモデルを捻りだして勝ちに行く

などなど、GPUと同じ土俵で戦う際のノウハウと戦略を持っていないと、手も足も出ませんし、これらを駆使しても、常に先端製造プロセスで作られているGPUの地力でねじ伏せられてしまい、とても苦しむことになります。

RECONF研のこちらの天野先生のメッセージリコンフ8策 というのを見かけました。まさに金言だと思います。

ではどういうときにFPGAを使うべきなのか

ここではカメラの例を出しましたので引き続きそのまま例にしますが、FPGAISP として使っている層は、ISP に関しては GPU でやるより FPGA でやる方が、はるかに計算効率が良く、電力もコストもリアルタイム性も勝てることを知っています。

つまり、FPGA がすでに GPU に勝っている領域からスタートし、そこに AI など新しいものを足していく というのが個人的に最もお勧めするやり方です。

画像処理(マシンビジョン)であったり、スマートNICやネットワークスイッチのような通信分野、ロボットなどのリアルタイム制御、特殊なセンサー/アクチュエータなどのデバイス制御、などなど何もしなくても FPGA が圧勝していたり、そもそもCPU/GPUでは不可能なものだったり、FPGAが得意な分野は多数あります。

ここを出発点として、FPGAの強みを失わない範囲で拡張していくことが重要です。

これはズルでも何でもなく、裏返せば GPU も同じことを既にやっていて、自分の得意分野で戦っているから、FPGA より優位に見えているだけです。

計算機科学に触れよう

ここで、多くの場合、GPUはなぜAIが得意で、CPU は何故AI計算でGPUに負けているのか、などの なぜ? に踏み込まず、「FPGAと言うものがあってなんかGPUより高性能らしい」という話だけで、意味も分からず使ってしまうと失敗します。

先のリコンフ8策の分中でも「ハードウェアで実装したんだからソフトウェアに比べて速くなるに決まっている」なんて言葉が飛び出しておりましたが、アカデミック分野に属する先生方からですらこんな声が出る事もあるわけですから、やる側がそのレベルで飛びついてしまってはいけないのです。

もちろん、FPGA は正しく使えば、GPUより高性能になりえますし、わかってくるととても楽しいものです。

ですので、入り口で躓かないために計算機科学に興味を持っていただきたい ということをすごく感じてしまうのです。

ヘネパタ読めとまでは言いませんので、ネット上でいろいろ計算機の仕組みを調べてみたり、実際に CUDAのコードを書いてみて GPU の仕組みに触れてみるとか、いろいろ試してほしいと思います。 そのうえで、自分のやりたいこと、考えているアイデア、拘りたいポイントなどよく考えて、「これFPGAなら試せるアイデアじゃないか?」というゴールまでの道筋をしっかり考えて取り組むことをお勧めする次第です。

新しい時代の FPGA-AI 8策が必要

最後に、今なぜこんなことになっているかを少し振り返っておきます。

私にとって比較的なじみの深い画像信号処理の分野で言えば、アルゴリズムと計算機アーキテクチャをセットで考え、新規性と進歩性のある、新しいシステムを生み出すことが重要です。

ところが、認識率という観点でのみアルゴリズムを研究されている方々の中で、「それはAIと比べてどうなのか?」という ルールベースアルゴリズムの研究の成果の価値がAIと比較されてて、精度観点だけで駆逐されていった と言うのがあります。

また、ビジネスの観点でも、AIにあらずんば投資対象にあらず と言わんばかりに、AIでないと研究予算が取れなくなり、AI人材でないと就職先が絞られていく という事情変化もありました。

必然的に、多くの学生や研究者が何かしら AI と絡めた研究をこぞってやり始めて現状に至ります。

加えて AI の台頭で、GPUを使った GPGPU計算が台頭してきたため、今まで CPUに勝てればOK であったアーキテクチャ研究が、GPU にも勝たなければいけなくなりました。しかもGPUが得意とするAI分野でです。

正直、私はそこまでAIに拘りも無いのですが、時代がそれを許してくれないので、何とか、世の中の需要を満たす建前も必要です。

拙作の LUT-Network などが生まれてきた背景にもそういう部分は無視できません。

時代の変化に合わせて 8策 をアップデートするが必要があるのかもしれません。

GPU と比較されたときの理論武装が必要です。

  • GPU向けのモデルをそのまま使わない(同じ土俵で戦わない)
  • GPUが持つハードマクロ演算器が役立たない演算を入れる(GPUの苦手を狙う)
  • FPGAのLUTやDSPやBRAMの特性を生かしまくるモデルにする(FPGAの得意を活かす)
  • Sparce性、ヘテロ性など、均一でない計算を作る
  • 演算器へのデータ投入でキャッシュより効率の良いメモリアーキテクチャで差をつける
  • リアルタイム性を活かしたアルゴリズムモデルを考える(リカレント構造など)
  • 他の特殊なデバイスと連携する、RGB以外のデータを扱う
  • 複数のセンサーやタイミングを組み合わせる

などなど、様々な要素を考えてみて欲しいと思います。

FPGA はストリーム処理が得意

FPGA は基本的にストリームデータに対するパイプライン処理が得意です。

カメラからのデータはストリーム的に出てきますし、出力もDVIやHDMIなどにストリーム的にそのまま出力できます。

一方で、ストリームデータは一度メモリに貯めれば、GPU などで並列演算可能であり、メモリに格納された GPU の処理結果をまた ストリームに戻すことができます。

この際に

  • メモリに溜めた遅延が増加する
  • メモリと言う新しいコストと電力が発生する
  • メモリとデータ転送を行うDMAなりの新しいコストと電力が発生する

などの不利が発生します。

しかしながら、先に述べた USBカメラの例の場合、

  • USBのプロトコルスタックや V4L などが画像読み出しの段階で、GPUに便利なフレーム単位にメモリに貯めてしまう
  • 結果を表示するにも OpenGL などの為に GPU と同じようにビデオバッファにデータを並べないといけない

という制約の為に、

  • わざわざ GPU用に並列化されたデータをコストを掛けてFPGA用に再ストリーム化する
  • FPGAの出力ストリームをわざわざフレームバッファに貯めなおして、GPUと同じ結果にした後、実は再度、再ストリーム化されて表示される

という非常にもったいないことになっていたわけです。

これで勝とうとすると、よほど「並列に実行したときでもGPUに非効率な計算列」になってない限り勝てず、とても不利な戦いを求められます。

なので、ストリーム入力&ストリーム出力で、リアルタイム性が重要なFPGAの得意な土俵で戦うべきなのです。

リアルタイム性については、「単にサクサク応答すると気持ちい」と言うだけではなく

  • 今の音を逆位相の音で打ち消すノイズキャンセリングのような信号処理
  • 揺れているドローンを安定させる
  • 転ぶ前に足を出してバランスをとるロボット
  • 新しい情報を瞬時に判断して株の売買をするシステム
  • 絶対に負けないジャンケンゲーム

みたいなものを考えていくと、AIを使う事も生きてきますし、FPGAの強みが出てくるわけです。

おわりに

これまで FPGA 人口ってどんどん高齢化していると思っていたのですが、最近 FPGAやってみたいという若手とお話しさせて頂く機会も増えました。大変ありがたいことです。

一方で「FPGA やってみたけど成果が出ない」という相談も増えるようになってきております。

FPGAは苦労も多く手戻りも大きい為、早い段階で 成果の出る道筋 に軌道を向けることが大事です。

同じようなことで悩んでおられる方、「これからFPGAに触ってみたいという方」に、失敗しないFPGAの始め方 を模索する上でのヒントになれば幸いです。

なぜGPUは高性能なのか

はじめに

最近 FPGA をやっているとよく GPU と比べられるという事が起こります。

本来の FPGA の得意分野(通信処理とか画像信号処理とか)を考えると、不思議な感じもするのですが、逆に FPGA が汎用計算機と比較されてしまうぐらい守備範囲を広げているとも考えられますので、喜ばしいことです。

FPGA との比較は後に回して、まずは どうしてCPUに対してGPUは高性能になれたのか? について考えてみたいと思います。

HPC は一旦おいていて、コンシューマでも手の届くレンジで最新のものとして GeForce RTX 50 series を眺めていたのですが、TSMC 4N での製造でダイサイズが 16.9 ~ 750mm2 までラインナップがあり、CUDAコア数が 2,560 ~ 21,760、TensorCore も含めた演算性能だと 13.2 ~ 104.8 TFLOPS(FP32) となっているようです。

同世代の Core Ultra 9(Intel) や Ryzen(AMD) などのコンシューマ向け x86 CPU が 0.5~10 TFLOPS 程度のレンジだと思いますので、同じ半導体プロセスをもってして、計算機アーキテクチャの差で数十倍程度の性能差は出していることになるようです。

SIMD と SIMT と

この二つは計算機のアーキテクチャとしてはかなり似ていると思っているのですが、ソフトウェアから見た見え方はだいぶ変わってくると思います。

SIMD(Single Instruction Multiple Data)は、CPU の命令の中に並列計算を行う命令を用意して1つの命令で同じ演算を並列に沢山計算するというもので、x86 の AVX や ARM の NEONなどが有名です。

一方、SIMT(Single Instruction Multiple Thread)は、主に GPU で用いられているもので、同じ命令を実行する沢山のスレッドを同時に実行します。

どちらもハードウェアとしては、大量のALU(演算ユニット)に対して、1つの命令デコーダで構成されますので、かなり良く似ています。

ではなぜ SIMD は SIMT に十分に迫ることが出来ていないのでしょうか?

一つの理由に、SIMD はソフトウェア互換性を保ったまま並列度を増やすのがとても難しいという事があるように思います。

AVX-2(256bit) が AVX-512(512bit) に並列度倍増しようとしたときに、Linux の作者である Linus Torvalds 氏がこんな苦言 を呈したのは有名なのでご存じの方も多いかもしれません。

SIMD の並列度の増強は、新命令の追加だけでなくレジスタ幅も広げなければなりません。レジスタはOSなどがプロセスやスレッドをスイッチするときに退避復帰する部分ですので、まずOSがアップデートされなければその機能を使う事が出来ません。 加えて当然ながらコンパイラも新命令に対応を迫られ、アプリケーション側もその新命令を使ってプログラムしなければ恩恵に預かれません。 要するにSIMDの性能向上は方々のソフトウェアエコシステムに都度対応してもらうという迷惑を掛けないと進化できません。

一方で、SIMT はもともと「このスレッドをできるだけ沢山一度に実行して」という形でプログラミングする為、同じプログラムが、コア数の少ないGPUでは少しのスレッドに分けて何度も実行され、大量のコアを持つGPUでは一度に大量に数度だけ実行される、という動きになります。 早い話が元のプログラムはそのままで、デバイスドライバ層以下の狭い範囲の対応だけで並列度の高い新しいGPUの恩恵が受けられます。 これがGPUの強みの一つと考えており、半導体プロセスの進化とともにどんどんコア数を増やし、並列度を上げてきました。

それでは「CPUでもSIMTをやればいいじゃないか」と思われるかもしれません。 しかし残念ながら、CPU では過去にあまりにも複雑な命令を沢山実装しすぎたせいで簡単にはそれができません。SIMTをやりたければ、互換性の為に過去のすべての命令に対応したスレッドを並列実行しないといけないため極めて高コストになってしまいます。 SIMD は 新しく追加した「演算に特化したシンプルな命令だけ並列化する」からこそCPUでも採用できている部分があると思われます。

だったら、シンプルな命令だけ実行できるコアを別に用意して、それ用の命令列も別に作ってSIMTを追加すればいいじゃないかとも思われるかもしれません。が、それは GPU入りCPUに外ならず、既にあちこちに存在している通りです。

最先端プロセスの威力

次に、FPGA と比較するために、最先端プロセスの凄さにも触れておきます。

半導体は大量に製造販売できる需要の見えているものは、最先端プロセスでの製造に投資しやすく、大量生産の効果で価格も抑えやすいです。 今GPUはご承知の通りAI需要で引っ張りだこでですので、惜しげもなく先端プロセスに投資できる状況にあるかと思います。

私が普段使っている KV260 などの 16nm プロセスの FPGA の載ったものは DSP(積和演算器)の数も1000個程度の規模であるため、CUDAコアが数万個もある最新のGPUと比べると性能に圧倒されるわけですが、逆に同じ 16nm 世代の GPU として GeForce 10 series あたりを参照すると、CUDA コア数も 256 ~ 3840個で、同じ世代の FPGA でも積和演算性能であれば近いものが狙っていけますし、価格帯も数万から数十万円のGPUの値段に対して同じ価格でFPGAも同クラスの規模感が狙っていけます。

要するにアーキテクチャではそれほど優劣は無いと思っているのですが、現実には、最先端プロセスの採用に関して GPU がだいぶ先を行っている感があります。

今のところ FPGA は先端プロセスで作っても直ぐに大量に売れるわけではありませんので、こなれた価格で使える品種のプロセス世代が変わるにはどうしても時間がかかってしまいます。

プロセスの進化で圧倒的に変わるのがダイ面積あたりに詰め込めるトランジスタの数でありそのまま演算量となります。半導体の価格は面積と強い相関があるので、FLOPS/$ が改善します。 またしばし微細化が進むと1つあたりのトランジスタでの電力も減るため FLOPS/W も改善します(これとは別に「面積当たりの電力」は近年悪化の一途のようですが)。

今朝方、試しに RTX 50 series の性能を Wikipedia を見ながらプロットしてみました。

GeForce RTX 50 series

1mm2 増えるごとに コア数が 31.5個ぐらい増え、0.149 TFLOPS 程度上昇する計算のようです。

同じことを GeForce 10 series でもやってみました。

GeForce 10 series

1mm2 増えるごとに コア数が 8.45個ぐらい増え、0.0259 TFLOPS 程度上昇する計算のようです。

ものすごく大雑把な計算ですが、TFLOPSで見ると TSMC の 16nm を 4N にすると GPU では 5.75 倍ぐらい面積当たりの性能効率が上がっているようです。

はやい話が FPGA は、10倍まではいかなくても 5 倍ぐらい不利なプロセスで戦っているというのが見えてきたのではないかと思う次第です。

おわりに

「敵を知り己を知れば、百戦危うからず」と言いますが、まあ敵とは言わないまでも他のプロセッサアーキテクチャの特性をよく理解して、何を選択するのが最適なのか考える事は大事だと思います。

せっかく「FPGA で尖ったことがやりたい」と思っていたのに、「やってみたら、GPUでやるのに比べて良いところなしだった」だと寂しいですので、どういうところが強みで、弱みなのかと合わせて、「どれぐらい弱いのか」、または「どれぐらい強いのか」をもう少し定量的に見ておくこともまた必要なことのように思いました。

しかし、久々に最新スペックを見てみましたが、GPU凄いですね。 とはいえまだまだ GPU より凄い物を作れる余地は沢山あるのだと思いますので、また新しいものが出てくることを期待している今日この頃であります。

撮影ボックス買ってみた

以前、マクベスチャート(カラーチェッカー)欲しいけど高いと呟いたら、安いのあるよと言うお話を頂いたことがあります。

今回は、照明環境の話です。

画像処理開発していると、カメラで対象が綺麗に写らず「ドーム照明ほしい」、「同軸照明欲しい」、「積分球欲しい」、となりがちなシーンはしばしあるわけですが、個人ではスペースも金額も辛いので、何かないかなと思っていたらスマホ向けの撮影ボックスなるものがあることを知ったので買ってみました。

私が買ったのはナカバヤシ株式会社さんの SAC-BOX04 という製品になります。探すと他にもいろいろなものがありそうです。

こんな使い方をしております(まあMNISTには要らないけど、例として(笑))。

MNISTの撮影

多くの場合一般家庭にあるような照明環境ですと、照明が一部だけ鏡面反射で強く光ってしまい均一な画像が撮れないという事がよくあります。身近な例だと「口座を開くのにマイナカードの撮影認証がうまくいかない!」などがその典型でしょうか。

ですのでなるべく、360度全体から間接光を当てたいという要求が出てくるわけです。

これを極めてちゃんとやる場合は、積分球と言うランバート反射(すべての方向に一律に反射する)特性に近い素材で物体でドーム状に覆って、それを経由して間接光を当てるという装置を使うそうです。

そうでない場合でも被写体に対してなるべく360度すべての方向から均一な光がやってくるようにするとムラのない撮影が可能です。

この場合の条件は

  • 直接的な反射光が入る角度に光源を置かない
  • 間接光を反射してくれる対象はなるべく全方向にある

のような事をなるべく実現したいわけです。

その場合に撮影ボックスがとても便利そうに思いました。

本来の用途としては、メルカリとかヤフオクに出品するものを撮影する用途だと思いますが、個人や小さな研究室レベルの画像処理の研究でも案外便利そうな気がします。

で、届いたものを開けてみたのですが。

コンパクトサイズ

なかなかコンパクトです。

収納用の袋

持ち運び用の袋もついていました。

照明はLEDのリング照明で、薄いのでコンパクトにしまえる理由がわかりました。

LEDむき出しなので何かしらディフューザーになるものを追加で加工しても面白いかもしれません。

照明

USBを電源とするようで、輝度や色合いをリモコンで調整できるのもいいですね。

照明の調整

背景のシートも複数色あって便利そうです。

背景のシートも複数色

真上に穴も開いていて、リング照明の中心からも撮影できるようです。

上から撮影

近年は AI の学習の為の撮影を行う人も増えていると思います。

もちろん AI自身に写りの悪い画像に対する耐性を持たせたいケースももちろんあるかとは思うのですが、そうではなくもっと画像の持つ本質的な情報を学習させたいとき、綺麗に対象が写っていないというのは研究の本来の目的からすると遠回りになってしまいます。

こういったグッズをうまく活用するのもいいなと思った次第でした。

ちなみに私の作ったカメラをスマホで撮ってみたら、本来の用途通り結構きれいに写りました。

たまにこういうものを買ってみると楽しいですね。

結局CISC/RISC論争とは何だったのか?

はじめに

例によって当事者でもない人間が感想を書く素人考察ポエムです。

先日 こんな 記事を書き、その中で 「 このあたりで1命令で出来ること自体を複雑にするかシンプルにするかでCISC/RISC論争とかがあった気もしますが、今となってはあまり本質ではないのでおいておきます」と、バッサリと話をスキップしたので少しだけ回収しておきたいと思います。

なぜ本質ではないと言ったかというと、先日の記事の趣旨は「演算器の並列稼働率」にフォーカスしたものであり、CISC/RISC という「命令デコーダの効率」に関わる問題はそこで取り上げるべきではないと考えたからです。

事実、RISC の成功例だったはずの ARM は Thumb2 命令以降も複雑化を続けて十分 CISC っぽさを持っていますし、CISC の代表格の x86 もいつの間にやらRISC風の 内部 μ-OPs に変換して実行するようになっていきましたし、 Transmeta社が Crusoe というチップでVLIWに変換して実行してみたりもありましたし、ついにはAPX命令 のようなものまで飛び出しており、その境界はとても曖昧になってきています。

結局のところ、デコーダ設計者が血の涙を流しながら設計しないといけないほど複雑になった 点に目をつぶれば、どちらも如何様にも変換可能であり、「大量の演算器を並列に稼働させる」というターゲットに限定して語れば、技術的にはどちらも同水準に持ち込める ということになってるんじゃないかと思います。

ですので、命令密度であったり、デコーダの規模(コスト)や電力が問題になったりする小規模用途以外では、あまり関係なくなっている面はある気がしています。

幸い、普及期の携帯電話が上記が致命的に重要であったため、当時まだシンプルなRISCであった ARM がその分野の強いシェアを持つことになったわけですが、ご存じの通り、今のスマホはパソコン並みの性能を持っていますので、ARMももはや RISC であることのメリット よりも、スマホ市場などで育った膨大なARM命令セットでのエコシステム こそが最大の強みになっていると思われ、ここに 命令セットの権利 とか バイナリ互換性 という、重要な話を作っていくわけです。

CISC/RISC の爪痕としての命令セット

CISC/RISC の論争は、結果として様々な命令セットアーキテクチャのCPUを生み出し、そこからさらに生き残り競争の結果 x86 と ARM の2大勢力の構図を生み出しました。 述べてきた通り、守備範囲の違いはあれど、レンジの被る領域では、正直 ARM も x86 もそこまで大きな差はなくなってきています。 一方で、x86 は依然スマホ市場やタブレット市場への参入は苦戦していますし、パソコン分野は相変わらず x86 ですし、データセンターやHPCでは両者が争ってるイメージです。 どうしてこのようなことになっているかと言うと、結局、互換性の無い2種類の命令セットが、それぞれの得意分野でソフトウェアエコシステムの牙城を築いているからに他ならないと思うわけです。

先日の Kernel/VM にて、自作OSを動かすのに「UEFIなどの環境の揃ったARMデバイスがなかなか無い」という話をされていた方おられましたが、まさにそういう話です。 そしてその 命令セットこそが飯のタネ と言うのは両陣営よくわかっているんので、知的財産としてしっかり保護しているわけです。

うっかり、FPGA などで互換プロセッサを作って、GitHub に公開なんかすると、後悔することになるので誰もやらないわけです。

で、そんな中にダークホースとして出てきているのが「命令セット自由に利用していいよ」というオープンアーキテクチャRISC-V でして、学術機関や個人含めて、お布施を払ってどちらかの陣営に入れない 勢の救世主としてひそかに盛り上がってるわけです。

とはいえ、これらの話は、JS、JavaPython、Go など はもちろん C++ や Rust などでさえ、ある程度上流でプログラミングしている人々にはあまり関係のない話だったりします。最近の抽象度の高い プログラミング言語仮想マシンは、命令セットアーキテクチャの違いなんて綺麗に隠してくれます。

一方で、低レイヤー側の話として、OSだったり、仮想マシンだったり、コンパイラJITだったり、ブートローダーやデバイスドライバなりを作ってる人には大問題だったりして、これらのエコシステムを作っている領域の、歴史だったり人口だったり資金力だったりで、いろいろな勢力にそれぞれ得手不得手を生み出していたりするのだと思います。

そもそも CISC/RISC論争とは何だったのか?

話を戻すと、今でこそ大量の演算器をアウトオブオーダー実行によるスーパースカラで1サイクルに10命令とか実行したりしてるわけですが、この論争当時のマイコンは命令を入れるメモリも貴重でしたし、演算側もハードウェア乗算器が一個あれば「すげー」と言ってた時代であり、加算器を複数サイクル回して乗算命令を実現していたCPUも沢山あった時代です。

そうなってくると、少ないメモリに置いた1つの命令でより沢山の演算ができることも重要でしたし、命令デコーダが占めるLSI全体でのトランジスタ比率も重要でした、そして1つしかない ALU (Arithmetic Logic Unit) を如何に効率的に使うかもまた重要だったわけです。

どれもこれも重要だと並べてしまいましたが、結局これらのどこにウェイトを置いて考えるか重要になってきます。

「少ないメモリ、少ないトランジスタ数で、なんとか実用的な計算ができるプロセッサを作りたい」と考えたとき、確かに CISC は合理的だったのだと思います。

一方で、より「ALUを休みなく高いクロックで稼働させたい」となったとき、ここに演算指令とデータを次々送り込むのに RISC は優れていたと思います。

従ってまあ、どちらがいいのかの論争は起こったのだと思いますが、ここでもまた過去のソフトウェア資産(エコシステム)の話で、バイナリ互換性が重視され、x86 が生き残り、携帯電話/スマホと言う新しい市場で ARMというRISC が成功をおさめ、そしてまた命令セットライセンスと言う柵に対抗して RISC-V がじわじわ流行っているというのが今に繋がる流れではないかと思います。

おわりに

AIに聞いてみると CISC/RISC論争は概ね1980年代が盛り上がっていたようです。RISC自体はもっと前から開発が始まっていたようですが、表舞台でいわゆる論争と言うか議論が盛り上がったのがそのあたりのようです。

えっと私が丁度、中学生~大学生を過ごした時期ですね(笑)。

今は FPGA でCPU 作って遊べる時代になりましたので、過去を振り返って楽しめるいい歳のおじさんになってしまったわけですが、血の涙を流さなくても遊べる RISC-V の命令セットは本当によくできているなと思います(もちろんRISC-Vも本格的にやるとちゃんと血の涙が出てくるらしいですが)。

現代においてソフトウェアを学ぶ人からすると言葉だけ残ってる不思議なものかもしれませんが、CISCRISCのワードで検索していただくと、「今の計算機がなんでこんな仕組みなんだ?」という理解の一助にはなるかもしれません。

初期の CISCはマイクロコード方式でどうだこうだ、RISC が出てきてハードウェアパイプラインデコーダでどうだこうだといった話も、大変興味深いものです。実際今の x86 などは、ハードウェアデコードしつつもRISC化困難な複雑な命令の為にはマイクロコードもますます活用されてていますしね。

この駄文が誰かの役に立てば幸いです。

近代CPUのメリット/デメリットを考えてみる

はじめに

我々プログラマは CPU/GPU/NPU/FPGA なんかを特性に合わせて選択しながらプログラミングすることになっているわけですが、AI以降、CPU以外のプロセッサの台頭が著しいですので、今更ながら基本となる CPU をもう一度眺めてみようという書きながら考えているポエムです。

当然ながら私はCPUユーザーではあれど、CPU設計者ではありませんので、ユーザー視点から好き勝手レビューするという話なので、素人考察になるわけですが、マサカリ投げずにお付き合いください(笑)

CPU の進化の歴史を覗いてみる

4004 からのCPU の歴史を眺めてものすごく大雑把な感想を述べると

  • 1命令の実行時間を縮めるのに腐心していた時代(CPI縮小&周波数向上)
  • 一度に実行できる命令を増やすのに腐心してきた時代(IPC拡大&コア数増加)

の2つの時代に分けられる気がします。 ここで CPI(Clock cycle per Instruction) と IPC(Instruction per Clock-cycle) はまあ逆数を取っただけではあるのですが、考え方の転換の象徴でもあるので使い分けてみました。

どちらも 時間当たりの命令実行数 を増やすことにプロセッサ設計者が腐心されてきたことには変わりはありません。

もちろん、枝分かれとして、電力とかコストとか耐久性とか別の品質軸にウェイトを振った製品もいっぱいありますが、大雑把な流れとして、「絶対性能の向上」を幹として歴史を紡いでいるかと思います。

歴史の前半では、1命令を何クロックサイクルも掛けて計算していましたので、これを 如何に短くするか が重要で、CPIを下げることと、周波数を上げることが重要だったように思います。 (このあたりで1命令で出来ること自体を複雑にするかシンプルにするかでCISC/RISC論争とかがあった気もしますが、今となってはあまり本質ではないのでおいておきます(苦笑))

実際、当初は1命令に何十サイクルも掛かっていた命令実行は、最終的にはスーパーパイプライン技術の上で、実質1サイクルで実行できるようになり、周波数も数MHzだったものが数GHzまで達しました(半導体の微細化と、パイプライン段数を深くして1つのステージをどんどん薄っぺらくした賜物)。

一方で、このあたりで、半導体バイスとしても熱問題などで周波数の向上が頭打ちになり始めてきました。

そうなるとここからは、1クロックサイクルの中で 如何に沢山の命令を実行するか と言う話になっていき、

  • スーパースカラによる同時複数命令実行
  • OoO (Out of Order) による命令依存関係制約軽減による並列化増進
  • SMT (Simultaneous Multi-Threading)による命令依存関係制約軽減による並列化増進
  • マルチコアによる並列実行

などの方向に向かったように思います。 なお、ここでは SIMD(Single Instruction, Multiple Data) は、少し本質から外れるので話を置いておきます。

以前からポラックの法則というのがありましたが、もともと直列に書かれていたプログラムを互換性を保ったまま並列実行しようとしているのが現在なので、ますますリソース当たりの性能向上のハードルが上がっているようには思います。 いずれにせよLSIトランジスタ数はある程度ムーアの法則で増えているのに、CPUの絶対性能はそれより低いオーダーでしか伸びず、言い換えると非効率さが増加気味になってきているわけです。

なぜCPUが重要なのか

そんなCPUを裏目に、昨今、「CPU の何百倍の性能を誇る GPU で AI が加速した」みたいな話はニュースなどで誰もが聞くようになってきました。

「じゃあもうCPUなんてやめて GPU だけ載ったパソコンやスマホを作って、WindowsLinuxmacOSGPU 上で爆速で動かせばいいじゃないか、ブラウザも、表計算も、GPUでもっとサクサク動いてくれ!」と思われても仕方ありません。

が、残念ながらそうはいかず、CPU + GPU 構成のパソコンや、GPU入りCPUチップなどでしかシステムは構築できず、依然 CPU はコンピュータの心臓部です。

これは言うまでもなく、CPU で実行するのが最も効率が良いプログラム というものが大量にあるからに他なりません。 一応GPUチューリング完全なプロセッサですのでやろうと思えば何でもできるはずですが、 一度に同じ計算を大量にできる というだけで、それ以外はからっきしです。

では CPU が無いと困る処理とは何なのかを改めて考えてみると

  • 順番にしか計算出来ないものが1つづつやってくる処理
  • バイナリレベルでの高い互換性が必要な処理

の2つを真っ先に思いつきました。

前者は そもそも人間がそうである ため、世の中に大量にあふれていて、例えば表計算ソフトの複数のセルに一度に数字を入力したいという人はあまりいません。例えばマウスカーソルが1000個表示されていて全部別々に操作して入力できる達人がいれば 1000コアのGPU は活躍するかもしれません。ですが残念ながら多くの人間は1つづつしか処理できません。世の中にはこういう処理が溢れており、「1000個いっぺんに同じ処理がしたい」ほうが本来は稀なのです。

幸い、ビデオ表示処理には、「ディスプレイのピクセル数だけ同じ処理がしたい」という需要があったため、古くからGPUは並列演算の効率化が行われており、3D-CG の為にいろいろやってたところ「大量の積和演算が同時にしたい」というAIの需要と たまたまマッチした 為、今に至るわけです。

また、バイナリ互換の話についても、いろいろなインタプリタ言語や仮想マシンの技術が進歩しても、最後は、移植性のある基盤ソフトが無いとそもそもベアメタルからのパソコンのセットアップがままならないわけで、そもそもBIOSが作れてOSを作れるという前提を作ってくれてるのがこの「バイナリ互換」というものだったりします。 こんなものが何百種類があっても正直困るわけで、群雄割拠な時代もありましたが、なんだかんだで最近は x86 と arm と RISC-V の3つにかなり集約されてきている気がします。おかげでエコシステムも安定してきていますし、これは非常に苦労しつつもバイナリ互換性を保ってくださっているCPU開発者の方々の苦労の賜物なのかと思います。

進化の難易度が年々上がるCPU

そうはいっても年々CPUが得意としている分野の性能向上は苦しくなってきているように思います。

現在のハイエンドCPUの IPC は 10 を超えていたりするわけですが、なまじ汎用レジスタアーキテクチャなんかだったりすると、全部の処理ユニットが全部のレジスタにアクセス可能でなければならず、また処理結果を全部同時に書き戻せないといけません。次のサイクルには次の処理結果がまた IPC の数だけ同時にやってくるのです。 以前にこんな記事を書きましたが、対角線の数だけ規模が爆発していきます。 汎用レジスタやめて専用レジスタに戻すべきじゃないかとすら思ってしまいますが(素人考え)。

OoO の仕組みもより広い範囲で命令順序を入れ替えるためにどんどん複雑化しています。 リオーダーバッファはどんどん深くなり、後で辻褄を合わせるのも大変ですし、後から例外でも発生しようものならそこまで矛盾なく巻き戻せないといけません。

CPUがもっとも得意なのが逐次スカラ処理であり、スカラプロセッサと互換性を持ったまま高性能化しようとしているところにやはり限界を感じます。

しかしながら、そういう処理はそもそも人間というモデルがそうであり、人間の作ったルールを処理したり、人間とコミュニケーションをとる以上永久に続く問題な気がします。

人間が書いた自然言語の小説が10万文字あったとして、伏線や起承転結のある物語の10万文字を同時に読み込んで1サイクルで理解して伏線回収に感動するようなことは、人にも機械にも無理なのは、自然言語がそうなっている以上仕方のないことだと思います。

なお、そういった中でCPUも SIMD などのCPU以外が得意なことも取り込んで性能改善を行っています。 これはもちろんCPUの応用範囲を広げる大変有効なことなのですが、もともとCPUが得意だった逐次スカラ処理分野の高速化には寄与しないあたりが悩ましかったりします。

どのようにプロセッサを使い分けるべきなのか?

御託が続きましたが、我々プログラマは CPU/GPU/NPU/FPGA などのプロセッサをどう使い分けるべきなのでしょうか?

大雑把に言うと、専用ハードウェア(NPUなど)に嵌る処理はまずそこに当てはめ、並列化の余地のない逐次処理はCPU、同じ計算を大量に行う場合はGPU、という事になってくると思います。 最後に、並列化の余地はあるが異なる演算を大量に行い、なおかつ専用ハードウェア化できないぐらい変化が速いか需要が少ない部分が FPGA などに残ることになります。

私はよく Zynq-MP を使うので以前にこんな記事を書いていたりするのですが、Zynq-MP は Linux などの動くアプリケーションプロセッサと、Real-Time OS などが動かせる リアルタイムプロセッサと、FPGA部分と、GPU まで搭載しているなんでもありプロセッサです。 後継の Versal に至っては、XDNA というNPU まで入っており、ほんとに全部乗せ SoC になっています。

私はなるべく、システム全体の処理を、それぞれ得意なプロセッサに割り当てることを心がけています。

そういった中でアルゴリズムが固定されているケースもしばしあるのですが、そういう場合は「そのアルゴリズムがどのプロセッサ向けに作られたか?」でかなり決まってしまうように思います。

一方で、似たような結果が得られるならアルゴリズムごと新規に作ってよい というケースであれば、どのハードウェア向けにアルゴリズムを組むかでかなり話が変わってくるように思います。 GPUがあるならなるべく同じ計算の並列実行が生きてくるアルゴリズムを捻りだそうと悩みますし、特殊な演算器を持ったCPUなどがあればそれを使おうしますし、キャッシュサイズやデータ帯域なんかも考えながらアルゴリズムに手を入れていきます。FPGAをターゲットにしてよいならアルゴリズムの工夫範囲は一気に広がり、かなりいろいろな方法を候補に上げながら落としどころを探すことができます。

案外どのプロセッサでも、それ向けにアルゴリズムを考え直すと、いろんなプロセッサでそこそこ性能が出たりもします。

どんな時にFPGAなのか?

CPUの話をしておいて何なのですが、まあ、当ブログでFPGA に触れないわけが無いので最後に少し触れます。

正直、単純なデータプロセッシングの性能のみで FPGA を選ぶケースはかなり稀だと思います。

  • CPUやGPUに無いような特殊なデータ型での演算を、ヘテロジニアスに大量に行う
  • パイプライン演算がやりやすく、ストリーム処理が行いやすい

のようなケースでしょうか?

一方で、IoT となると話が変わってきます。FPGAプログラマブルでありながら

  • 現実世界とのインターフェースであるI/Oロジックがプログラムできる
  • リアルタイム性が高く、クロック位相などピコ秒単位で調整できることもある

などの特徴があります。

ようするにセンサーやアクチュエータを介して、現実世界とインタラクションできます。

こちらから何か作用すると、現実世界は変化しますので、それをまた取り込むという事を、非常に高いリアルタイム保証の中で組めます。 要するにアルゴリズムのデータループの中に「現実世界」を組み入れてしまう事が出来るわけです。

それこそピタゴラスイッチみたいなことを想像してもらっても良いかもしれません。 このような実世界を巻き込んだアルゴリズムはCPUやGPUではそもそも実行自体が不可能なものが多数ありますので、こういう分野をシステムの一部にでも保有すると計算機システムの面白みが一気に増大していくわけです。

おわりに

今回は、最初に8割ぐらい書いたところで、割り込み作業が入ってしばらく放置していて、最後の部分だけ慌てて書いたこともあってかなり、ちぐはぐなことを書いた気もしますが、いつものポエムという事でご容赦ください。

テストと検証の違いについて考えてみた

はじめに

今回は定期的にやってくる駄文というかポエム回です。

ソフトウェア開発において「テスト(Test)」と言うものは非常に重要です。一方でLSI開発などを含めて、RTL界隈では「検証(Verification)」という言葉をよく聞きます。

業種や人によっても用語の定義が微妙に違ったりもするので一概に定義できない部分もある気がしますが、今日は 主観100% となりますが、私なりの考えでこの二つを考えてみようと思います。 このあたりは一家言ある人が多い気がしているのでマサカリ飛んで来そうで怖いんですが、まあこんな考え方もあるよというレベルで私見として書いておきます。

私の理解として

  • テストはバグがあればそれを証明する試み
  • 検証はバグが無いことを保証しようとする試み

という理解をしております。

もちろん検証が完了したからバグがゼロ個であることを保証できるわけではないのですが、目的として目指しているものが異なるという点は重要かと思います。

そしてこれは、ソフトウェアだからとかハードウェアだからという問題ではないと考えています。実際ソフトウェアでも検証は必要ですし、CPU/GPU/FPGA向けのソフトウェアで低レイヤーの部分では検証が必要になってくるケースは多い気がしています。

機能の確認と、機能の保証の違い

例えば python二次方程式を計算する関数を書いてテストして意図した値が得られたとしましょう。

def func(x):
  return 3 * x**2 + 2 * x + 1

この関数はおそらく下記のようなことは起こりません

  • 何度も実行したら3回目で違う結果が返ってきた
  • Python と一緒に Excel を起動したら計算結果が変わった
  • CPUコア数の違うパソコンで実行したら結果が変わった
  • Windowsでは合うが、Linux では結果が変わった
  • その日の天気で結果が変わった

そのため、Excel と一緒に起動するテストや、晴れの日と雨の人雪の日でそれぞれテストするようなテスト項目を作ったりはしません。

一方で、OSを開発したりベアメタルで開発するなどの低レイヤーの開発の場合以下のようなバグはしばし発生します。

  • ある命令の区間で割り込みが来た場合に限り変数が壊れる
  • たまたまあるスレッドが先に終了したときだけ変数が壊れる
  • マルチコアへのスレッドの割り当て順が特定のケースで変数が壊れる
  • コンパイルオプションで最適化を指定すると結果が変わる
  • メモリバリアを書き忘れるなどして実行順序依存でキャッシュの状態次第で変数が壊れる

何が言いたいかと言うと、先の Python のコードが Python のコードに閉じて正しい機能かどうかだけをテストすれば済んでいるのは、プロセッサがメモリコヒーレンシを保証し、バグのないスピンロックの機構や、メモリ保護や、復帰可能な割り込みや、温度保証などの物理的な保証もしており、OS開発者がコンテキストの継続性を保証できるスレッドを用意し、安全なメモリ割り当てを行い、言語開発者がバグのないインタプリタコンパイラを提供しているから成り立っているわけです。

ものすごく乱暴な言い方をすると、先の Python コードが正しいかを確認するのが「テスト」で、それを保証する環境をのものを担保しているのが「検証」ではないかと思う次第です。

まさに「プログラマをダメにするハードウェア」の上に成り立っているのがテストなんじゃないかとさえ思ってしまうわけです。

テストと検証のやり方の違い

テストの場合いろいろな考え方があって

  • 境界値条件
  • 実行網羅/分岐網羅/条件網羅
  • ディシジョンテーブル
  • 原因結果グラフ

などなど教科書的な話に始まり、如何に効率的に目的の機能を満たすべく目の前のコードのバグを出していくかと言う点に心血が注がれます。

一方で、検証となると、起こりうるすべての事象で同じ機能が満たされること を確認する為、常に 状態の組み合わせ爆発 と戦う事になります。

そもそもとして起こりうる状態をちゃんと、漏れなくリストアップしてすべての組み合わせを把握できているか、もとても重要になります。

よくある「コーナーケースでバグが出た」なんて言うのは結局、状態組み合わせを見通せてなかったか、工数が無くて検査しなかったかのどちらかです。

そういった場合に案外強力なのが

などの考えになってくる気がします。

テストの場合、「境界値をちゃんと考えないランダムなテスト」と言うのは、質の悪いテストと思われがちですが、こと検証の場合は、検証予定の組み合わせパターンの100%網羅が目的ですので、「少ない工数で効率よく100%までもっていく」点でランダムパターンは有効なケースがしばしあります。

ランダムと言っても取りうる状態に条件があるので、複雑な条件を持った複数のオブジェクトの状態組み合わせとなると、多次元空間の探索ですので、それこそモンテカルロ法で使われるギブスサンプリングみたいなものが必要になってくるのではないかなどと思ってしまうわけです。

で、仕様が許す範囲での最大限の多様性を持った外乱を与えつつ、内部設計仕様を満たしていることをプロパティ検証などで見ていくのはなかなか有効な手段であり、いわゆる「ソフトウェアテスト技法」とも少し違ったものを思う次第です。

また、これらとは全く違うアプローチで、フォーマル検証も重要なのだと思います。

こちらも正しく条件を定義するところまでは同じですが、それが組み合わせ爆発の中ですべて満たされるかどうか、数学的に証明しようという試みなので適用可能なシーンでは非常に強力な武器になりそうな気はします。生憎なかなか簡単に使えるツールでもないので経験は無いのですが、興味深く思います。

テストと検証で似ているところ

ブラックボックス(外部仕様)/ホワイトボックス(内部設計)での区分けとか、

みたいに、階層化して問題に対処していくあたりは両者似ているなと思ってみたりもします。

TDD のように、先にテストや検証を定義してから、実装設計を進めるのも両者ともに有効だと思います。

境界はあるのか

ちなみに実務的にはテストと検証の境界は案外曖昧な気もしています。

ソフトウェアテストであっても、組み合わせ全網羅みたいなことをすることはありますし、検証であっても全部扱えないので検証項目を何らかのルールで絞ることも多いです。

感覚的に、低レイヤーは検証寄りの考えが重要になりがちで、上位レイヤーほどテスト技法が有効に機能する気がしています。

また、全部テスト/検証しきれないときに費用対効果を考えて、項目を落としていくビジネス観点でのセンスが必要なこともあるでしょう。

なかなかこれはテストをしているのか検証をしているのか、混ざっているのか、曖昧なケースは多い印象はあります。

研究開発などのプロトタイピングにおける検証

私は長らくそういうポジションでの開発が多いのですが、プロトタイピングで重要なのは 脳内設計だけで一発でバグのないコードを書く ところに達するまでひたすら修行することじゃないかと思っていたりもします。

この過程で重要なのは、「仮説を立てた事象が正しいかどうかの検証」だけなので、それができればどうだっていいわけです。

が、まあ、「しばし DMA転送が時々途中で固まって、実験が止まる」なんてことはよくあるわけで、そこで検証の出番となるわけです。

  • 疑うところを間違わない(手を抜いたところ、実績が無いところ)
  • 疑わしいところに絞って検証してバグ落としする
  • 場合によっては姑息な手法で暫定回避する

などにもセンスが問われます。

しばし試作システムでバグのモグラ叩きをはじめてしまい、全く研究が進まない人が居ますが、研究とかプロト開発のフェーズでは、それらはどれだけ頑張っても何一つ成果として認められないので、まあ、適当にさっさと何とかする 必要があったりします。

そして、「適当にさっさと何とかする」には「ちゃんとしたテスト技法や検証論の知識」がとても重要だったりするなと思う次第です。