dotFly——C#でシミュレートされたショウジョウバエの脳 | Konrad “Dev Nerd” Kokosa

GoogleとJaneliaがMaleCNSショウジョウバエコネクトームを公開、166,700個のニューロンをノートPC上でC#によりリアルタイムシミュレーション、ただしデモは本物の脳ではない。

日本語
コピー
dotFly - a fruit fly's brain, simulated in C# | Konrad 'Dev  的题图

上で見たのはこうだ。リビングを飛び回るショウジョウバエが匂いの雲を追い、砂糖壺に着陸して吻を伸ばして食べる。障害物を避けるにはどちらへ曲がればいいのか、匂いは濃くなっているのか薄くなっているのか、風はどちらから吹いているのか、降り立ったこれは砂糖の味がするのか——これらすべてを、本物のショウジョウバエ1匹の中枢神経系まるごとが制御している。166,700 個のニューロン、2,490 万個のシナプス、配線は電子顕微鏡で観察されたとおりに再現され、それをノート PC 上で純粋な C# によりリアルタイムでシミュレートしている。まあ……だいたいは。そしてこの「だいたい」こそが本稿の主題だ。

この騒ぎは一体どういうことなのか

2026 年 9 月 3 日、Google Research と HHMI Janelia が MaleCNS コネクトームを公開した。成体雄のキイロショウジョウバエの脳および「腹神経索」(脳と体の間で信号をやり取りする部分)の完全な配線図である。数日のうちに、インターネットはインターネットらしいことをした。ハエの脳が Doom を遊び、Super Mario 64 を遊び、サボテンを飛び越え、ブラウザの中を歩き、Mac のデスクトップに座り始めたのだ。私も釣られた。以前 dotLLM に対してそうしたように、中で何が起きているのかを突き止めたくなった。AI に関して本当に理解する最良の方法は、自分の手で作ってみることだからだ。そうして作ったのが dotFly——ネイティブ .NET のショウジョウバエ・コネクトーム「推論エンジン」で、Godot のゲームループに収まる程度には速い。Python なし、ネイティブライブラリのラッパーなし、純粋な CPU のみ。本稿では、コネクトームとは何か、どうやって作られたのか、みんなが動かしている「ハエ脳モデル」とは何か(そしてもっと重要な、何ではないか)、あのデモが何をしているのか、dotFly を C# でどう実装したか(ベンチマーク付き)、最後にこの話全体の限界について正直に述べる。

待って、これって倫理的に大丈夫なのか

細部に入る前に、すぐ浮かぶ疑問がある。これが本当に本物の脳のシミュレーションなら、そもそもやっていいのか。Mario の中で壁にぶつかるハエは苦しんでいるのか。r/AskScienceDiscussion でも Hacker News でもそう訊かれていて、あるコメントはこう書いていた。「このプログラムの役に立つ度合いは、我々が自信を持って作ったこれがおそらく最も残酷な機械である確率 10% を賭けるに値するのか?」 我々は「本物の生命」を作り出し、それを仮想環境で拷問しているのか。SF じみて聞こえても、もっともな問いだと思うし、軽く流すつもりはない。ただ正直に答えるには、まずシミュレートされているものは何なのかを理解する必要がある。手短に言えば、ある意味では確かに本物の脳をシミュレートしている——配線は実在の動物からニューロン1個、シナプス1個単位で計測されたものだ——同時に、生きた脳からはほど遠い。脳の化学の大部分とニューロン間通信の細部は省かれ、各ニューロンの内部で起きていることも無視されている。ホルモンも、内部状態も、学習もない。2,500 万個のシナプスがすべて1つの重みを共有する、といった単純化だけがある。あのデモが「ゲームを遊べる」のは手書きのアダプタのおかげで、非線形力学系なら何でも入れ替えればゲームを遊んでいるように見える。このモデルには、スキャンされた個体やその記憶、あるいは体験に類する何かが保存されていることを示すものは何もない。だから私は、我々が「ありうる最も残酷な実験」を作ったとは思わない。うん、今のところは。だがこの居心地の悪さは有用な注意喚起でもあると思う。あのデモが正確には何なのかを言い切ること——本稿の残りはそれを目指す。

基礎から——コネクトームとは何か

この先を理解するには用語が3つあればいい。

  • コネクトーム——再構築された「配線」図。どのニューロンがどこに繋がり、シナプス接触がいくつあり、どの神経伝達物質を使うか
  • 神経モデル——その配線を動かす方程式(コネクトーム自体は何も計算しない。ただのグラフだ)
  • 身体化——モデルと身体、ゲーム、世界の間の工学的な「インターフェース」

インターネットはその配線図(connectome)をダウンロードし、そこにダイナミクスとインターフェースを付け足した。ダウンロードしたのは、生きたハエの凍結された実行ファイルではない。

どうやって作られたのか

話を「Google が9月にハエの脳の地図を描いた」とまとめるのは簡単だ。実際は何年にもわたる研究の積み重ねである。

  • 2018——Zheng らが成体雌のハエ脳の最初の完全な電子顕微鏡ボリューム(FAFB データセット)を発表。画像だけ——約 100 TB の切片スタック
  • 2024——FlyWire コンソーシアムがその脳の完全な再構築を発表。約 140,000 ニューロン、50 M シナプス(Dorkenwald ら、Nature)
  • 2024——Shiu ら(Nature)がその脳全体の最初の計算モデルを発表し、実際の実験で検証した。これが今みんなが動かしている神経モデルだ
  • 2025-2026——MaleCNS。生後5日の成体雄(標本 Z0720-07m)のコネクトームで、脳+頸部+腹神経索をまとめて解剖した。アルデヒドで固定し、重金属で染色し、樹脂に包埋し、熱したナイフで約 20 µm 厚の 66 枚の切片に切り、強化集束イオンビーム SEM で 8×8×8 nm の解像度で撮像した。ガリウムイオンビームで薄く削り、SEM が新しい断面を撮像し、これを繰り返す。特注装置7台、約 160 兆ボクセル、撮像に約 13 か月。その後 Google の flood-filling networks がニューロンを分割し、自動検出器がシナプスを見つけ、ResNet50 が EM の近傍から神経伝達物質を分類し、29 名の専門校正者が約 44 人年をかけて修復と注釈付けを行った。結果は 166,700 ニューロン、11,710 細胞種、25.6 M 本の有向辺、124 M 個のシナプス接触。2026 年 9 月 3 日に Cell に掲載(Berg、Beckett、Costa、Schlegel ら)。v1.0 データは6月から利用可能だった。

何ではないか

コネクトームは、死んで切片にされ、金属染色された脳の「写真」だ。生きた脳の fMRI でも電極記録でもない。計測していないもの——

  • 膜電位や活動電位などの活動
  • シナプスの機能的強度(接触がいくつあるかしか測っていない)
  • ホルモンの影響
  • そのとき学んだこと、覚えたこと、感じたこと(まあ、ハエは死んでいるのだが……) 配線図だ——非常によくできた配線図だが——各ニューロンには予測された神経伝達物質のラベルが付いている。

「入力」と「出力」は何か

図が ID 付きの 166,700 ニューロンにすぎないなら、目がどこにあるかどう分かるのか。ここで1世紀にわたるショウジョウバエ遺伝学と神経解剖学が効いてくる。モデル内の各ニューロンには注釈が付いている——細胞種(LC4、T4a、MN9、DNp04……)、カテゴリ、左右——校正者が形態、位置、接続性から割り当て、文献と照合したものだ。そして文献は膨大で、たとえばすでに分かっていること——

  • LC4 ニューロンは近づいてくる物体(接近/拡大する物体)に反応する(カルシウムイメージング、光遺伝学、行動から)
  • T4a-d は4方向の運動に反応する
  • ORN_DM1 は特定の匂い/味に反応する
  • いわゆる糖味覚受容ニューロン(GRNs)は糖に反応する
  • MN9 は吻を伸ばす運動ニューロン
  • DNp04 と Giant Fiber は神経索へ下行する逃避下行ニューロン(「出力」) つまり感覚ニューロンが入力で、たとえば光受容体、嗅覚・味覚の感覚ニューロン、ハエの「触角」の運動・触覚の感覚ニューロンなどだ。そして下行ニューロンと運動ニューロンが出力——約 1,300 個の下行ニューロンが脳の命令を神経索へ伝え、運動ニューロンが筋肉を駆動する。これはモデルの仮定ではなく、解剖学的な事実だ。信号を1つ追ってみよう。ハエの最も単純な反射——何かがこっちに来た、逃げろ——
graph LR
 A["a dark spot grows
in the left eye"] --> B["photoreceptors
R1–R6"]
 B --> C["lamina, medulla
<small>the optic lobe</small>"]
 C --> D["LC4 (left)
<small>71 neurons:
'something is looming'</small>"]
 D --> E["DNp04, DNp02, DNp11,
Giant Fiber
<small>descending neurons</small>"]
 E --> F["ventral nerve cord
→ wing & leg motor neurons"]
 F --> G["take off,
turn away"]

同じことを実験にしてみる。MaleCNS のグラフを取り、左側の LC4 ニューロン 71 個を 120 Hz のランダムパルスで1秒間駆動する——これが「左目の中で物体が膨張している」という状態が脳から見てどう映るかだ——そして誰が発火するかを記録する。dotfly run --stimulate type:LC4@L --hz 120 の後——

ニューロン種類正体発火率
531898DNp04(左側)脱出下行ニューロン308 Hz
10010DNp01Giant Fiber——ショウジョウバエの「ジャンプ」指令276 Hz
10197DNp02脱出下行ニューロン256 Hz
10259DNp11脱出下行ニューロン244 Hz
10752DNp03脱出下行ニューロン220 Hz

合計 4,792 個のニューロンが活性化した(総数 166,700 個)。そして首位に立ったのは、まさに文献が記述していた脱出経路だった——しかも刺激した眼と同側にある。モデルは LC4 と DNp04 がつながっているなどとは教えられていない。この「接続」はもともと存在していた。入力を活性化すれば、出力が点灯する。遊び方はこれだけだ。入力を活性化し、出力を見る。

みんなが使っているモデル:Shiu et al. 2024

この図はそれ自体では何もしない。Shiu らは、最も粗削りだが動く方法でこれを動かした。各ニューロンは漏れ積分発火(LIF)点ニューロンである。ニューロンの形も樹状突起もイオンチャネルも忘れていい。残るのは一つの数値——その「膜電位」だけだ。入力スパイクがそれを押し上げたり押し下げたりし、静止値へ漏れていき、閾値を越えた瞬間にニューロンは自身のスパイクを発してリセットする。それだけのことだ。

発火させるのにどれだけの入力が必要かに注目してほしい。90 個のシナプス接触を持つニューロンから来る 3 本のスパイクが、数ミリ秒以内に必要で——単一の入力ニューロンの 1 本のスパイクだけでは何も起きない(それには約 162 個の接触が要る)。発火は収束の結果である。スパイクがどれだけ強く押せるか——ここがコネクトームが方程式に入ってくる唯一の入口だ。ニューロン i からニューロン j への各辺には重みがある:

wij=sign⁡(NTi)⋅nij⋅wsyn

nij は 2 つのニューロン間のシナプス接触数——顕微鏡で数えたものだ。wsyn は 2,500 万個のシナプスすべてで同じ値、1 接触あたり 0.275 mV。これがモデル全体で唯一較正されたパラメータである。Shiu らはこれをフィッティングして、感糖ニューロンの刺激が現実的な強さの吻伸展反応を生むようにし、そこで止めた。残りすべて——時定数、閾値、不応期、シナプス遅延——は先行する電気生理学研究から来ている。

sign⁡(NTi) の符号は、私のような生物学者でない者には説明が要る。ニューロンはシナプスで化学物質——神経伝達物質——を放出して信号をやり取りし、各ニューロンは(たいてい)1 種類しか使わない。ある伝達物質は受け手のニューロンを興奮させ、電位を閾値へ押し上げる。別のものは抑制し、電位を押し下げる。コネクトームもまた、各ニューロンがどの化学物質を使うかは測っていない——電子顕微鏡画像でのシナプスの見え方から分類器が予測したものだ。モデルはその後、化学機構のすべてを 1 ビットに圧縮する。ショウジョウバエではアセチルコリンが主要な興奮性伝達物質なので +1。GABA とグルタミン酸は抑制性なので -1。残る 3 つ——ドーパミン、オクトパミン、セロトニン——は実際には調質である。他のシナプスの振る舞いを変え、報酬や覚醒といった信号を運ぶが、LIF モデルはそれを表現しようがない。Shiu らはそれらを単に興奮性として扱った、+1。これは生理学的事実ではなくモデリング上の約束事だ。ドーパミンニューロンに +1 を与えても、報酬や学習は実装されない。

研究者たちはこのモデルで予測を立て——「これらのニューロンを活性化すれば、あれらが発火するはずだ」——そのうち 164 件を光遺伝学とカルシウムイメージングで本物のハエに対して検証した。論文は 91% 一致と述べている。これは文字通りの意味だ。164 件の予測のうち 91% が摂食とグルーミングの回路で成立した。ハエの行動全体の 91% ではない。

コネクトームは固定——私たちはそれを訓練しない

ここが肝心だ。重みは固定で、各ニューロン対の間の接続数から来ている。誰もこのネットワークを訓練して Mario を遊ばせたりしないし、すべきでもない。25M 個の重みをゲームのスコアに当てはめ始めたら、それはもう「ハエの脳」ではなく、たまたまハエの形をしたグラフから出発しただけのニューラルネットワークだ。元のモデルには可塑性則が一切入っていない。だから「遊び」はやはりこうなる。入力を活性化し、出力を見る。糖ニューロンを 150 Hz のポアソン スパイクで駆動し、残り 127,000 個のニューロンのうちどれが発火し始めるかを見る。あるニューロンを黙らせて、何が変わるかを見る。これこそがこのモデルの価値だ——プログラム可能で検証可能な神経回路モデルであり、ここでは仮説が 1 回の実行になる。

では、これらのデモは実際に何をしているのか?

「ハエの脳が X を遊ぶ」というデモは、私が作ったものも含めてどれも、3 つの層が重なっている:

graph LR
 W["World / game"] -->|"encoder
<small>engineered</small>"| I["Input neurons
<small>measured identity</small>"]
 I --> B["Connectome + LIF dynamics
<small>measured wiring, one calibrated weight</small>"]
 B --> O["Readout neurons
<small>measured identity</small>"]
 O -->|"decoder
<small>engineered (fixed or trained)</small>"| W

配線とダイナミクスは共通だ。各デモを実際に差別化しているのはアダプタであり、表面的な知能の大半もここから来ている。ピクセルやその他の状態を発火率に変換するエンコーダ(例えば視覚ニューロン——具体的にどれで、何 Hz が何に対応するのか?)、そして発火率(下行ニューロン、つまり脳の「運動指令」細胞から来る)をキー入力や身体動作に変換するデコーダだ。いくつか例を見てみよう。Xenova のハエシミュレーション——完全な 166,700 ニューロンの MaleCNS LIF がブラウザで WebGPU 上を走り、3D のハエの身体を駆動する。ニューロンに刺激を塗りつけたり、プリセットを使ったりできる。「walk」は両側の LC9 を刺激し、「turn left」は左側の LC9 と左側の DNa02 を、「fly」は両側の LC4 を刺激する。LC4 と LC9 は視覚投射ニューロンで、各 LC タイプは検出器であり、ある種の視覚事象を中央脳へ報告する(LC4:「何かがこちらへ拡大してくる」)。DNa02 は下行ニューロンで、実験がそれが旋回を駆動することを示している。出力側では、このデモは少数の下行ニューロンを読む。DNp09/DNg100/DNg97 が歩行速度、DNa02/DNa11/DNg13 が左折か右折か、MDN(「moonwalker」後退ニューロン)がジャンプ、DNp01(Giant Fiber)が脱出飛行——それぞれに手で選んだゲイン(8 mm/s、3.8 rad/s……)が付き、その model.json に記録されている。ここは評価したい。一つ注意すべきは、「turn」プリセットが出力ニューロン DNa02 を直接刺激していることで、視覚入力だけではない。著者は理由を説明している——視覚入力だけでは DNa02 の活性化が弱すぎる——が、これは脳内部の接続をすべて切ってもハエが旋回し続けることを意味する。それでも、厚いアダプタを被せずに本物の回路活動を見せようとするツールであることは変わらない。Fly Dino——まったく別のアプローチだ。脳全体ではなく、80 ニューロンの部分回路である。32 個の視覚検出ニューロン(LC4、LC11、LPLC2……同じ「何か来た」ファミリー)と 16 個の下行ニューロンで、コネクトーム内で「視覚事象」から「運動指令」への接続が最も強い経路を構成するという基準で選ばれ、さらに中間の細胞が加わる。Shiu のスパイク LIF ではなく、段階的レートモデル(tanh)で動く。8 つのゲーム特徴(障害物までの距離、大きさ、速度……ピクセルではない)が視覚ニューロンに注入される。次にデコーダのアダプタだ。16 個の出力ニューロンの活動が極小のニューラルネットワーク——合計 243 個の数値——に入り、それが Run、Jump、Duck を選ぶ。この小さなネットワークは 15,680 局のゲームで試行錯誤によって訓練された。ハエの回路自体は一度も変わっていない。つまりここで起きているのは、部分的な回路活動を読み取り、ゲームの動作に翻訳する出力アダプタを訓練したということだ。これはリザバーコンピューティングである。脳は固定された複雑な変換として使われ、「どの動作を選ぶか」という最後の層の写像だけが訓練からフィッティングされる。良いのは対照実験だ。ハエの回路を切って訓練済みアダプタを残すと、スコアは 2,886 から 41 に落ちる。つまり回路は確かに何かをしている——入力の固定された非線形変換として働き、あの小さなネットワークがそれを読むことを学んだのだ。「Fly Mario」的なデモ(Fly64、fly-games)——完全な MaleCNS LIF を粗い時間刻み(20 ms)で進め、ゲームのフレームを視覚検出器の特徴に変換する(LC4:脅威、LPLC2:何かが近づいている、LC10a:追うべき何か)。出力側はニューロンからキーへの写像だ。十数個の下行ニューロングループ——DNa02 の左/右が旋回、DNp09 が前進、など——各グループが閾値付きで 1 つのキーに写像される。Fly64 ではこの写像は手作業だ(「左の DNa02 が右より多く発火していれば Left を押す」)。fly-games では、記録したプレイ例から小さな線形回帰でフィッティングされる。これもまたリザバーコンピューティングだ。一度も見たことのない記録クリップ上で、正しいキーを 90% の精度で予測できる——それでもリアルタイムのプレイではハエはすぐ死ぬ。リアルタイムの状況が記録データから外れていくからだ。Mario は壁にぶつかってそこで止まる。これは批判ではない。どれも誠実な実験だ。要点はこうだ——アダプタは極めて重要であり、動く身体は、対照実験——脳内部の接続を切る、そして/または入力を切る——を併せて走らせない限り、回路が何に寄与したかの証明にはならない。

そこから生まれた dotFly

dotFly はまずライブラリだ。fly-connectome のスパイキングモデル向けの .NET 推論エンジンで、Godot、コンソールアプリ、テスト、ベンチマークがインプロセスでリンクする。MaleCNS と FlyWire のリリースからメモリマップドチェックポイントを構築し、その上で Shiu らのモデルを動かす。正確さ(float64 バックエンドは Brian2 とスパイク単位で一致する)と速さ(float32 SIMD バックエンドはノート PC 上で MaleCNS 全体をリアルタイム実行する)を両立し、刺激を入力し、スパイクと発火率を出力し、記録と再生、因果スイッチを提供する。ルームデモはただのデモだ。薄い身体化がショウジョウバエ自身の感覚を保ったまま、大量の「アダプタ」を必要とするかどうかを見るために作った。

ルームデモ

Godot 4(.NET)の 3D シーン。日当たりのいいリビング、ハエが一匹、テーブルの上に砂糖、そして数か所から風下に流れてくる「匂いの雲」。MaleCNS コネクトームが dotFly 上で動き、彼女の感覚と行動をつなぐ唯一の経路になっている。各パネルの意味はこうだ。

image

感覚 → 入力(エンコーダ、固定)——複眼ごとに 1 台、計 2 台のカメラが 32×32 の輝度画像を描画する。各眼について、暗部の割合とその増加が LC4(迫近)レートになる。画像の水平・垂直変位が T4a-d(オプティカルフロー)レートになる。2 本の触角の匂い濃度が ORN_DM1 レート、風向が JO-C/E(Johnston 器官)レートになり、着地時の砂糖接触が脚と口の味覚感覚ニューロンを駆動する。入力ニューロンは合計 7,524 個。コネクトーム(実測)——166,700 個のニューロンすべてを実際の位置に描画し、実際のスパイクで光らせる。ここにスクリプト由来のものは何もない。読み出し(実測回路)——読み出す回路はすべて、仮定ではなく CLI でチェックポイントの中から見つけたものだ(dotfly inspect --upstream-of、dotfly run --stimulate)。13 グループ、計 38 ニューロン。

  • LC4 → DNp04 L/R, Giant Fiber——逃避
  • T4a → HS、T4b → H2、T4c → VS——オプティカルフロー
  • ORN_DM1 → DM1 projection neurons——匂いの量
  • JO-C/E → AMMC012——風向
  • GRN → MN9——摂食

デコーダ(固定、手書き)——消費する読み出しの隣に画面へ表示され、そこにある数字は一つ一つが選択だ。

脳信号(読み出し)規則行動
DNp04 左 vs 右yaw += 1.2 · (DNp04_L − DNp04_R)迫近してくる側から離れるよう旋回
HS + H2 左 vs 右yaw += 0.2 · ((HS_R + H2_L) − (HS_L + H2_R))回転に対抗して逆に旋回(視運動反応)
HS 左 vs 右yaw −= 0.3 · (HS_R − HS_L)壁の間で中央に寄る
DNp01(ジャイアントファイバー)speed = 120 + DNp01 体長/秒巡航、逃避時はバースト(実際のハエ:100–170 BL/s)
DM1_lPN(匂いの量)> 110 Hz → 上昇中はダッシュ、下降中はタンブル、ロストで方向転換してから掃引、> 270 Hz → 下降して着地匂い探索
AMMC012 左 vs 右(風)ダッシュ中:yaw −= 0.6 · (wind_L − wind_R)向風飛行
MN9(0.3 秒で平滑化)> 15 Hz → 摂食、停止 → 離陸摂食

面白い発見は、匂いの方向がどの読み出しからもまったく導けないことだった(どちらの触角を刺激しても、DM1 の候補ニューロン 2 個は同じ反応をする)。だからアダプタに少し「ロジック」を足して、匂いが強まると前へ飛んで探索し、弱まると方向転換するようにした。風の信号は脳から来る。

dotFly の内部:C# のパフォーマンス

dotFly は規約も精神も dotLLM の兄弟だ。メモリマップドのモデルファイル、アンマネージド状態、SIMD カーネル、ホットパス上のゼロアロケーション。同じ階層レイアウトで、各プロジェクトが NuGet パッケージになっている。

src/DotFly.Core .dfb checkpoint reader (mmap), graph tables, NeuronModel, RNG, IBackend
src/DotFly.Data MaleCNS / FlyWire release readers
src/DotFly.Cpu SIMD LIF kernel, compute thread pool
src/DotFly.Engine Simulation, input/output ports, real-time driver, recorder, adapters
src/DotFly.Adapters.* ONNX Runtime / ML.NET readout adapters
src/DotFly.Cli dotfly build | inspect | run | bench | explore

API デモが対象とするプログラム:

// Neurons are addressed by their exact 64-bit IDs from the connectome release (FlyWire root IDs
// or MaleCNS body IDs)
ulong[] sugarGrnIds = [720575940624963786, 720575940630233916, /* 21 sugar GRNs from Shiu et al. */];
const ulong Mn9 = 720575940660219265; // MN9, the proboscis motor neuron (FlyWire v630 root ID)

using Brain brain = Brain.Open(".data/shiu2024/flywire-v630.dfb");
using Simulation sim = brain.CreateSimulation(new SimulationOptions { Seed = 1 });

NeuronSet sugar = brain.ByBodyIds("sugar_GRN_R", sugarGrnIds);
sim.Input(sugar, InputKind.PoissonToV).Fill(150f); // Poisson drive, 150 Hz each
OutputPort mn9 = sim.Output(brain.ByBodyId(Mn9), OutputKind.Rate(50.Ms()));

sim.Run(1.Seconds()); // neural time
Console.WriteLine($"MN9 {mn9.Snapshot.Mean():F1} Hz at {sim.Clock.RealTimeFactor:F1}× real time");

Shiu らの砂糖実験を 10 行で書くとこうなる。砂糖を感知する味覚ニューロン 21 個を駆動し、吻の運動ニューロンを読む。完全なサンプル(samples/DotFly.Sample.SugarExperiment)は論文の 30 試行とその沈黙実験を実行し、公表された結果と比較する。

flywire-v630: 127,400 neurons, 14,687,178 edges. Sugar GRNs: 21, MN9 index 127193.
30 trials × 1 s in 3.0 s wall (10.1 simulated s per wall s).

Active neurons (mean over trials): 433. Top 10:
 720575940621502051 152.3 Hz (sugar GRN)
 720575940632425919 150.7 Hz (sugar GRN)
 ...
MN9 (720575940660219265): 83.3 Hz mean over 30 trials.

Silencing experiments (outgoing synapses zeroed; the neuron still spikes):
 silence 720575940621502051: MN9 83.3 Hz (intact 83.3 Hz)
 silence 720575940632425919: MN9 78.7 Hz (intact 83.3 Hz)
 silence 720575940633143833: MN9 79.6 Hz (intact 83.3 Hz)

Comparison with published results/example/sugarR.parquet (Brian2 2.5.1, 30 trials):
 active neurons: 448 vs 433 (Jaccard 0.949); rate correlation 0.9946; spike-count ratio 0.803
 MN9: 93.3 Hz vs 83.3 Hz

127,400 ニューロンの脳で 1 秒の試行を 30 回動かして 3 秒。論文が得た結果も同じで、砂糖を入力すると吻の運動ニューロンが約 80 Hz で出力する。集団単位なら通常はアノテーションで引く——brain.Query(type: "LC4", side: Side.Left)、brain.Query(cls: "Kenyon_Cell")——生の ID は論文を再現したり、名前の付いた個々の細胞を読むときに使う。ゲームループなら、new RealtimeDriver(sim).Start() がネットワークを専用スレッドで動かし、ゲームスレッドはロックなしで InputPorts に書き、OutputPort.Snapshot フレームを読む。

効いてくる設計上の判断がいくつかある。

  • チェックポイントはメモリマップドファイル(.dfb、dotFly の GGUF)——グラフは圧縮疎行(CSR)形式で格納する——rowPtr[N+1]、col[E]、w[E](int16 接触カウント、符号付き)——にアノテーション、位置情報、そしてデータバージョン・フィルタ・符号ポリシーを記録したヘッダが付く。1 GB の Arrow リリースから構築するのに約 10 秒、開くのは数ミリ秒
  • アンマネージド、64 バイト境界に整列した配列構造(SoA)状態——v[N]、g[N] は float32 にあり、不応期カウントダウン、19 個のスパイクリストからなるリング。MaleCNS 全体で約 2 MB——L2 に収まる
  • LIF カーネルは Vector256——スパイク索引は TrailingZeroCount で圧縮する。カーネルは TFloat : IBinaryFloatingPointIeee754 でジェネリック化されているので、double(Brian2 と 1e-11 mV まで一致する参照実装)と float(高速パス)が同じ実装を共有する
  • 各ステップメソッドに [MethodImpl(MethodImplOptions.AggressiveOptimization)]——これが一番の意外だった。これがないと、階層化 JIT がカーネルとバッチループを短い実行の大半で tier-0/OSR に留めてしまう。1 ステップ 6 µs ではなく 21 µs になる。

ベンチマーク

8コアのノートPC(Ryzen 7 5800HS、AVX2)上でdotfly benchをエンドツーエンドで実行した結果:

シナリオニューロン数リアルタイム倍率ステップ/秒
FlyWire v630、21個のsugar GRN @ 150 Hz(Shiuの実験)127,40019.6×196,000
MaleCNS v1.0、入力なし166,70014.5×145,000
MaleCNS v1.0、1,684個のT4aニューロン @ 150 Hz(0.5 M spikes/s、0.9 G 投递/s)166,7006.2×62,000

Python、JavaScript、C#

他の人が動かしているものと比べてどうなのか、見ずにはいられない。参照点は3つ、どれも簡単に特定できる。PythonはBrian2——発表済みのモデルが動いている汎用のスパイキングニューラルネットワークシミュレータだ。JavaScriptとWebGPUはどちらもXenovaのブラウザデモで、そのCPUコア、つまりsrc/brain.jsのBrainCPUは100行の素直で無駄のないJSで、同じモデルを実装している——正確なLIF積分、dt = 0.1 ms——そしてBrainGPUは同じものをWGSLコンピュートシェーダーとして動かす。Node 24でJavaScriptコアを、ヘッドレスChromeでXenovaのブラウザデモを、同じMaleCNSグラフ(専用のデータファイル、25.6 Mエッジ)で、刺激はdotfly benchと同じにして、同じノートPC上で続けて実行した。各実装のスパイク数はRNGの範囲内で一致しており(T4aシナリオはどの実装でも534〜539 k)、同じ仕事をしている:

実装シナリオステップ/秒リアルタイム倍率
Shiuらの論文、Brian2(論文の報告値、CPUスレッドあたり)v630、sugar GRN @ 150 Hz~330.003×
Brian2 2.9、numpyバックエンド、Python(このノートPC)v630、sugar GRN @ 150 Hz~4000.04×
Xenova BrainCPU、Chrome worker内のJavaScript、1スレッドMaleCNS、1,684 T4a @ 150 Hz6280.06×
Xenova BrainCPU、Node 24内のJavaScript、1スレッドMaleCNS、1,684 T4a @ 150 Hz8510.09×
Xenova BrainGPU、統合GPU Radeon(Vega 8)上のWebGPUMaleCNS、1,684 T4a @ 150 Hz2,4090.24×
Xenova BrainGPU、RTX 3050 Ti Laptop GPU上のWebGPUMaleCNS、1,684 T4a @ 150 Hz5,3830.54×
dotFly、C#、1スレッドMaleCNS、1,684 T4a @ 150 Hz10,7401.07×
dotFly、C#、8スレッドMaleCNS、1,684 T4a @ 150 Hz43,6564.37×
dotFly、C#、8スレッドv630、sugar GRN @ 150 Hz196,00019.6×

同じスレッド数で、C#はJSリファレンス実装より約11倍速い。これはJavaScriptがこの用途で遅いからではない(V8のtyped arrayの扱いはかなりまともだ)。JITがただでは与えてくれないものを、Vector256では1命令で8ニューロン処理し、状態レイアウトはL2に収まり、scatterは境界チェックなし、そして投递ループはgの自分の常駐キャッシュのスライスにしか触れないからだ。

この表に含まれていないもの:dt = 20 msステップで動くデモ(Fly64、fly-games)。ステップ数が200分の1で、本質的に安上がりだが、その代償としてShiuモデルではなくなっている。

限界——そして次にどこへ向かうか

ここからは正直な話をしよう。モデル自体には2つの大きな限界があり、それはconnectomeを直接使うことと、入力/出力デコーダを補うことのトレードオフをちょうど表している。

視覚の境界の引き方が間違っている——今日C#が計算しているのは「視葉」が計算すべきものだ。網膜エンコーダが画像の並進と拡大を直接T4とLC4の信号に変える——先ほどのloomingの図の最初の4つのボックスを飛ばしている。ショウジョウバエの目は約800個の微小な視覚ユニットと視葉全体(脳のニューロンのかなりの割合を占める!)から成り、その役割こそ光受容体の信号から運動とloomingを計算することにある。次のマイルストーンは光を直接光受容体に送り込み、中間の接続が自力で運動とloomingを計算できるかどうかを見ることだ——できればエンコーダは「各目の輝度」に縮み、残りはconnectomeに任せられる。できなければ、退路はハイブリッド方式で、Flyvis風の訓練済み視葉を使うことになる。

ショウジョウバエ自身のナビゲーション回路は沈黙している——ここが最も重要な点だ。デモの中で、どこへ向かうか——向かい風にダッシュする、回転する、歩を進める、着地する——を決めているのは私のデコーダーである。本物のハエはこの意思決定を自分の脳の中で行っており、その回路はコネクトームの中に隠れている。ショウジョウバエの針路を追跡し、それを風や匂いと組み合わせ、旋回ニューロン DNa02 を駆動して左か右へ向かわせるニューロンが存在する。風と匂いの入力をオンにしても、これらのニューロンはどれも発火しない。できあがったハエは匂いを嗅げるし風も感じるが、旋回しない。理由はこの回路が循環しているからだ——自分自身へフィードバックする。その活動が維持されるのは、活動中のニューロンが隣人を興奮させ続け、同時に残りを抑制しているからにすぎない。現在の Shiu モデルはこれを表現できず、より複雑な「循環型」神経モデルのサポートが必要だ。

結び

ここでもまた二つのことが同時に成り立つ。プラットフォームの面では、.NET は 166,700 ニューロン、2,500 万シナプスのスパイキングネットワークをノート PC 上でリアルタイムに動かし、スレッド数が変わってもビット単位で一致し、科学向けのリファレンス実装とも合致する——Vector256、NativeMemory、メモリマップドファイル、そして手書きのスレッドプールで十分だ(🔥)。科学の面では、コネクトームは素晴らしい測定であり、LIF モデルは素晴らしい出発点であり、今日ハエに「ゲームを遊ばせて」いるものはすべてアダプターだ——それらは画面上に表示されるべきであり、対照実行ではオフにされるべきである。

dotFly は GPLv3 を採用している——データ(MaleCNS、FlyWire)は CC BY 4.0 で、別途ダウンロードが必要だ。.NET 開発者で C# を使って本物の脳をつついてみたい人、あるいは神経科学者でリファレンス実装より三桁速い内側のループが欲しい人は、試してみるといい。何かを刺激する。何かを沈黙させる。そしてどのニューロンが発火したか教えてほしい。

出典: Konrad Kokosa's Blog← ホームへ戻る