rabukasim / docs /plans /bytecode_extension_analysis.md
trioskosmos's picture
chore: remove large files for HF Space
9bd4ce5

バイトコード拡張案の分析: 5x32 vs 64bit vs 現状維持

概要

ユーザーからの技術的異議を受けて、3つのアプローチを比較検討します:

  1. 現状維持 (4x32): [op, v, a, s] - 4整数 x 32ビット
  2. 5x32拡張: [op, v, s, a_low, a_high] - 5整数 x 32ビット
  3. 64bit拡張: [op, v, a64, s] - aのみ64ビット

1. ユーザーの懸念点 (正当性の評価)

1.1 v への Color Filter 移動の問題

懸念 評価 理由
Card ID > 65535 での破損 正当 プロモカード等で ID が 70050+ になる可能性あり
AI学習の複雑化 正当 「opcode が X の場合は v から色を探す」という条件分岐は NN に負担

1.2 Assembly-Style Unrolling の問題

懸念 評価 理由
MCTS深度爆発 正当 1効果 = 3-4ステップ は状態空間を不必要に拡大
部分状態の探索 正当 「フィルタ済みだが選択未完了」の中間状態が増加

1.3 拡張性の欠如

懸念 評価 理由
将来のメカニクス対応 正当 学年フィルタ、ブレードサイズ等の新規フィルタで即座に限界

2. パフォーマンス影響の分析

2.1 Rust での影響

現状 (4x32)

// bytecode: Vec<i32>
for chunk in bytecode.chunks(4) {
    let (op, v, a, s) = (chunk[0], chunk[1], chunk[2], chunk[3]);
    // 処理
}

5x32拡張

// bytecode: Vec<i32>
for chunk in bytecode.chunks(5) {
    let (op, v, s, a_low, a_high) = (chunk[0], chunk[1], chunk[2], chunk[3], chunk[4]);
    let a = ((a_high as u64) << 32) | (a_low as u64);
    // 処理
}

影響:

  • メモリ: +25% 増加
  • キャッシュミス率: 若干増加 (1命令あたり 20bytes → 25bytes)
  • CPUサイクル: ほぼ変わらず (ビットシフトは高速)

64bit拡張

// bytecode: Vec<i64> または混合型
for chunk in bytecode.chunks(4) {
    let (op, v, a, s) = (chunk[0] as i32, chunk[1] as i32, chunk[2], chunk[3] as i32);
    // a は i64
}

影響:

  • メモリ: +25% 増加 (4x32=128bit → 2x32+1x64+1x32=160bit)
  • キャッシュミス率: 若干増加
  • CPUサイクル: ほぼ変わらず (64bit演算は現代CPUで高速)

2.2 WGSL (GPU) での影響

現状 (4x32)

@group(0) @binding(2) var<storage, read> bytecode: array<i32>;

fn get_instruction(ip: u32) -> vec4<i32> {
    return vec4<i32>(
        bytecode[ip],
        bytecode[ip + 1u],
        bytecode[ip + 2u],
        bytecode[ip + 3u]
    );
}

5x32拡張

@group(0) @binding(2) var<storage, read> bytecode: array<i32>;

fn get_instruction(ip: u32) -> vec5<i32> {  // vec5 は存在しない!
    // WGSL には vec5 がないため、個別にロードが必要
    let op = bytecode[ip];
    let v = bytecode[ip + 1u];
    let s = bytecode[ip + 2u];
    let a_lo = bytecode[ip + 3u];
    let a_hi = bytecode[ip + 4u];
    let a = (u32(a_lo) | (u32(a_hi) << 32u));  // u64 として結合
    // ...
}

影響:

  • 重大: WGSL に vec5 が存在しないため、個別ロードが必要
  • メモリアクセス: 5回/命令 (現状は4回)
  • レジスタ圧力: 若干増加

64bit拡張

@group(0) @binding(2) var<storage, read> bytecode: array<i64>;  // または混合

fn get_instruction(ip: u32) -> vec4<i64> {  // 一部が i64
    // WGSL は型統一が必要
    return vec4<i64>(
        bytecode[ip],
        bytecode[ip + 1u],
        bytecode[ip + 2u],
        bytecode[ip + 3u]
    );
}

影響:

  • WGSL は array<i64> をサポート
  • ただし、op, v, s も 64bit になるためメモリ無駄
  • 混合型は WGSL で複雑化

3. 推奨アプローチ: 5x32 拡張

3.1 理由

基準 4x32 (現状) 5x32 64bit
メモリ効率 ✅ 最良 🟡 +25% 🟡 +25%
WGSL互換性 ✅ 最良 🟡 個別ロード必要 🟡 型統一必要
拡張性 ❌ 不十分 ✅ 64bit属性 ✅ 64bit属性
AI学習 ❌ 複雑な条件 ✅ クリーン ✅ クリーン
実装コスト - 🟡 中程度 🔴 高い

3.2 新しいレイアウト (5x32)

[op, v, s, a_low, a_high]

op (i32): Opcode
v  (i32): Value/Count (16bit) + Color Mask (6bit) + Flags (10bit)
s  (i32): Slot/Zone (24bit) + Flags (8bit)
a  (i64): Attribute Filter (64bit完全使用可能)

3.3 64bit a ワードの新しいレイアウト

┌─────────────────────────────────────────────────────────────────┐
│ Bit  0     : IS_OPTIONAL                                       │
│ Bit  1     : DYNAMIC_VALUE                                     │
│ Bits 2-3   : Card Type (0=Any, 1=Member, 2=Live)               │
│ Bits 4-7   : Group ID (4 bits = 16 groups)                     │
│ Bits 8-12  : Unit ID (5 bits = 32 units)                       │
│ Bits 13-17 : Cost Threshold (5 bits = 0-31)                    │
│ Bit  18    : Cost Mode (0=GE, 1=LE)                            │
│ Bit  19    : Tapped Filter                                     │
│ Bit  20    : Has Blade Heart                                   │
│ Bit  21    : Not Has Blade Heart                               │
│ Bits 22-28 : Color Mask (7 bits = 7 colors)                    │
│ Bits 29-35 : Character ID 1 (7 bits = 128 chars)               │
│ Bits 36-42 : Character ID 2 (7 bits)                           │
│ Bits 43-49 : Character ID 3 (7 bits)                           │
│ Bits 50-56 : Special Filter ID (7 bits)                        │
│ Bits 57-63 : Reserved for future use                           │
└─────────────────────────────────────────────────────────────────┘

改善点:

  • Color Mask が a 内に配置 (v から分離)
  • Character ID が 64bit 内に収まる (切り捨て問題解決)
  • 将来の拡張用に 7ビット予備

4. 実装ステップ

Phase 1: Rust インタープリタの更新

  1. バイトコードストレージの変更

    // Before
    pub bytecode: Vec<i32>
    
    // After
    pub bytecode: Vec<i32>  // 5要素ごとに1命令
    
  2. チャンク処理の変更

    // Before
    for chunk in bytecode.chunks(4) { ... }
    
    // After
    for chunk in bytecode.chunks(5) {
        let op = chunk[0];
        let v = chunk[1];
        let s = chunk[2];
        let a = if chunk.len() >= 5 {
            ((chunk[4] as u64) << 32) | (chunk[3] as u64)
        } else { 0 };
        // ...
    }
    

Phase 2: Python コンパイラの更新

  1. compile() メソッドの変更
    def compile(self) -> List[int]:
        bytecode = []
        # ... 既存のロジック ...
        # 各命令に a_high を追加
        for i in range(0, len(bytecode), 4):
            a = bytecode[i+2]
            a_low = a & 0xFFFFFFFF
            a_high = (a >> 32) & 0xFFFFFFFF
            bytecode[i+2] = a_low
            bytecode.insert(i+3, a_high)
        return bytecode
    

Phase 3: WGSL シェーダーの更新

  1. 命令読み込みの変更
    fn get_instruction(ip: u32) -> (i32, i32, i32, u64) {
        let op = bytecode[ip];
        let v = bytecode[ip + 1u];
        let s = bytecode[ip + 2u];
        let a_lo = bytecode[ip + 3u];
        let a_hi = bytecode[ip + 4u];
        let a = (u32(a_lo) | (u32(a_hi) << 32u));
        return (op, v, s, a);
    }
    

5. パフォーマンス予測

5.1 メモリ使用量

項目 現状 (4x32) 5x32 増加率
1命令あたり 16 bytes 20 bytes +25%
全カードのバイトコード ~1.5 MB ~1.9 MB +25%
GPU VRAM ~2 MB ~2.5 MB +25%

5.2 実行速度

環境 予測影響
Rust (CPU) < 1% 遅延 (メモリ帯域幅依存)
WGSL (GPU) 1-3% 遅延 (メモリアクセス増加)
AI訓練 改善 (状態空間の削減)

5.3 AI訓練への影響

側面 影響
状態空間 削減 (Unrolling回避)
MCTS深度 削減 (1効果 = 1ステップ)
NN入力エンコーディング 簡素化 (レジスタ意味が明確)

6. 結論

推奨: 5x32 拡張アプローチ

理由:

  1. 64bit 属性フィルタで全ての情報を1命令に収容
  2. AI訓練にとって最適 (状態空間削減)
  3. 実装コストが中程度
  4. 将来の拡張性を確保

次のステップ:

  1. ユーザーの承認
  2. Codeモードでの実装開始