当時の開発ログを見返しながらのメモ。
3月22日の README の未実装リスト(Phase 10)に、Raft、分散 Attention、MoE、「自己増殖 — 新ノードが接続された瞬間に OS カーネルを自動プッシュ転送」が並んでいた。
4月4日の夜に raft.c・spawn.c・moe.c を追加。合わせて1250行くらい。
■Raft
何台かの中から1台のリーダーを多数決で選ぶ仕組み。
リーダーからのハートビートがしばらく来ないと立候補。1回の任期(term)で投票できるのは1票だけ。過半数の票を取れたらリーダーになって、100ms ごとにハートビートを出す。
本来の Raft は立候補までの待ち時間をランダムにして同時立候補を避けるけど、ここでは「300ms + ノード番号 × 50ms」と番号でずらしていた。
なので一番せっかちなのは node0。コミットに「node0 が term=1 で LEADER に就任することを QEMU で確認済み」とあるけど、ある意味予定どおり。
リーダーが配る「ログ」は、数字の key と value が最大16個で、受け取ったら表示するだけ。
■MoE
名前は大きいけど、中身はセンサーの温度を 20度未満・35度未満・それ以上 の3クラスに分けて、そのクラスで一番成績のいいノードに推論を回すだけ。成績は K-DDS の "moe/score" で共有。
■自己増殖(のつもりだった)
spawn.c がやっていたのは、新しいノードにクラスタの状態(任期、リーダー、各ノードの生死)を送ることだけ。カーネル本体は配っていない。README も「クラスタ状態を自動 push」に書き直した。
本当にカーネルを配れたのは翌朝の「ネットブート自己複製」。向きが逆で、ディスクのない新しい機械が小さなローダで起動して「カーネルください」と叫ぶと、動いているノードの kserve が kernel.elf を 1KB ずつ送り返す。
新ノード → "KLRQ"(ください)
kserve → "KLRS"(始めます)
→ "KLRD" × N(1KB ずつ)
→ "KLRE"(終わり)
ディスクなしのノードが起動して、組み込みの自己テストも 5/5。
押しつけるより、欲しい側が頼みに来る方に落ち着いた。
■16バイトのずれ
翌々日、ネットワーク越しにカーネルを受け取る途中で止まる問題を修正。
NIC(RTL8139)のリング状の受信バッファを 8192+16 で折り返していたのが原因。実物は 8192 で折り返すので16バイトずれていた。直したら約9MB 受け取って起動できた。
※リポジトリ: https://github.com/monyuonyu/p-kernel
※この記事は、p-kernel の開発を手伝ってもらっている AI(Claude)と一緒に書いています。