Files
hakmem/archive/phase2/IMPLEMENTATION_ROADMAP.md

468 lines
12 KiB
Markdown
Raw Normal View History

# hakmem 実装ロードマップ(ハイブリッド案)(2025-11-01)
**戦略**: ハイブリッドアプローチ
- **≤1KB (Tiny)**: 静的最適化P0完了、学習不要
- **8-32KB (Mid)**: mimalloc風 per-thread segmentMT性能最優先
- **≥64KB (Large)**: 学習ベースELO戦略が活きる
**基準ドキュメント**:
- `NEXT_STEP_ANALYSIS.md` - ハイブリッド案の詳細分析
- `P0_SUCCESS_REPORT.md` - P0実装成功レポート
- `docs/analysis/CHATGPT_PRO_ULTRATHINK_RESPONSE.md` - ChatGPT Pro 推奨
---
## 📊 現在の性能状況P0実装後
| ベンチマーク | hakmem (hakx) | mimalloc | 差分 | 状況 |
|------------|---------------|----------|------|------|
| **Tiny Hot 32B** | 215 M ops/s | 182 M ops/s | **+18%** ✅ | 勝利P0で改善|
| **Random Mixed** | 22.5 M ops/s | 25.1 M ops/s | **-10%** ⚠️ | 負け |
| **mid_large_mt** | 46-47 M ops/s | 122 M ops/s | **-62%** ❌❌ | 惨敗(最大の課題)|
**P0成果**: Tiny Pool リフィルバッチ化で +5.16%
- IPC: 4.71 → 5.35 (+13.6%)
- L1キャッシュミス: -80%
- 命令数/op: 100.1 → 101.8 (+1.7%だが実行効率向上)
---
## ✅ Phase 0: Tiny Pool 最適化(完了)
### 実装内容
-**P0: 完全バッチ化**ChatGPT Pro 推奨)
- `core/hakmem_tiny_refill_p0.inc.h` 新規作成
- `sll_refill_batch_from_ss()` 実装
- `ss_active_inc × 64 → ss_active_add × 1`
### 成果
- ✅ Tiny Hot: 202.55M → 213.00M (+5.16%)
- ✅ IPC向上: 4.71 → 5.35 (+13.6%)
- ✅ L1キャッシュミス削減: -80%
### 教訓
- ❌ 3層アーキテクチャ失敗: ホットパス変更で -63%
- ✅ P0成功: リフィルのみ最適化、ホットパス不変で +5.16%
- 💡 **ホットパスは触らない、スローパスだけ最適化**
詳細: `P0_SUCCESS_REPORT.md`, `3LAYER_FAILURE_ANALYSIS.md`
---
## 🎯 Phase 1: Mid Range MT最適化最優先、1週間
### 目標
- **mid_large_mt**: 46M → **100-120M** (+120-160%)
- mimalloc 並みのMT性能達成
- 学習層への影響: **なし**64KB以上は無変更
### 問題分析
**現状の処理フロー**:
```
8-32KB → L2 Pool (hakmem_pool.c)
ELO戦略選択オーバーヘッド
Global Poolロック競合
MT性能: 46M ops/smimalloc の 38%
```
**mimalloc の処理フロー**:
```
8-32KB → per-thread segment
TLSから直接取得ロックフリー
MT性能: 122M ops/s
```
**根本原因**: ロック競合 + 戦略選択オーバーヘッド
### 実装計画
#### 1.1 新規ファイル作成
**`core/hakmem_mid_mt.h`** - per-thread segment 定義
```c
#ifndef HAKMEM_MID_MT_H
#define HAKMEM_MID_MT_H
// Mid Range size classes (8KB, 16KB, 32KB)
#define MID_NUM_CLASSES 3
#define MID_CLASS_8KB 0
#define MID_CLASS_16KB 1
#define MID_CLASS_32KB 2
// per-thread segment (mimalloc風)
typedef struct MidThreadSegment {
void* free_list; // Free list head
void* current; // Current allocation pointer
void* end; // Segment end
size_t size; // Segment size (64KB chunk)
uint32_t used_count; // Used blocks in segment
uint32_t capacity; // Total capacity
} MidThreadSegment;
// TLS segments (one per size class)
extern __thread MidThreadSegment g_mid_segments[MID_NUM_CLASSES];
// API
void* mid_mt_alloc(size_t size);
void mid_mt_free(void* ptr, size_t size);
#endif
```
**`core/hakmem_mid_mt.c`** - 実装
```c
#include "hakmem_mid_mt.h"
#include <sys/mman.h>
__thread MidThreadSegment g_mid_segments[MID_NUM_CLASSES] = {0};
// Segment size: 64KB chunk per class
#define SEGMENT_SIZE (64 * 1024)
static int size_to_mid_class(size_t size) {
if (size <= 8192) return MID_CLASS_8KB;
if (size <= 16384) return MID_CLASS_16KB;
if (size <= 32768) return MID_CLASS_32KB;
return -1;
}
static void* segment_alloc_new(MidThreadSegment* seg, size_t block_size) {
// Allocate new 64KB segment
void* mem = mmap(NULL, SEGMENT_SIZE,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) return NULL;
seg->current = (char*)mem + block_size;
seg->end = (char*)mem + SEGMENT_SIZE;
seg->size = SEGMENT_SIZE;
seg->capacity = SEGMENT_SIZE / block_size;
seg->used_count = 1;
return mem;
}
void* mid_mt_alloc(size_t size) {
int class_idx = size_to_mid_class(size);
if (class_idx < 0) return NULL;
MidThreadSegment* seg = &g_mid_segments[class_idx];
size_t block_size = (class_idx == 0) ? 8192 :
(class_idx == 1) ? 16384 : 32768;
// Fast path: pop from free list
if (seg->free_list) {
void* p = seg->free_list;
seg->free_list = *(void**)p;
return p;
}
// Bump allocation from current segment
void* current = seg->current;
if (current && (char*)current + block_size <= (char*)seg->end) {
seg->current = (char*)current + block_size;
seg->used_count++;
return current;
}
// Allocate new segment
return segment_alloc_new(seg, block_size);
}
void mid_mt_free(void* ptr, size_t size) {
if (!ptr) return;
int class_idx = size_to_mid_class(size);
if (class_idx < 0) return;
MidThreadSegment* seg = &g_mid_segments[class_idx];
// Push to free list
*(void**)ptr = seg->free_list;
seg->free_list = ptr;
seg->used_count--;
}
```
#### 1.2 メインルーティングの変更
**`core/hakmem.c`** - malloc/free にルーティング追加
```c
#include "hakmem_mid_mt.h"
void* malloc(size_t size) {
// ... recursion guard etc ...
// Size-based routing
if (size <= TINY_MAX_SIZE) { // ≤1KB
return hak_tiny_alloc(size);
}
if (size <= 32768) { // 8-32KB: Mid Range MT
return mid_mt_alloc(size);
}
// ≥64KB: Existing L2.5/Whale (学習ベース)
return hak_alloc_at(size, HAK_CALLSITE());
}
void free(void* ptr) {
if (!ptr) return;
// ... recursion guard etc ...
// Determine pool by size lookup
size_t size = hak_usable_size(ptr); // Need to implement
if (size <= TINY_MAX_SIZE) {
hak_tiny_free(ptr);
return;
}
if (size <= 32768) {
mid_mt_free(ptr, size);
return;
}
// ≥64KB: Existing free path
hak_free_at(ptr, 0, HAK_CALLSITE());
}
```
#### 1.3 サイズ検索の実装
**`core/hakmem_mid_mt.c`** - segment registry
```c
// Simple segment registry (for size lookup in free)
typedef struct {
void* segment_base;
size_t block_size;
} SegmentInfo;
#define MAX_SEGMENTS 1024
static SegmentInfo g_segment_registry[MAX_SEGMENTS];
static int g_segment_count = 0;
static void register_segment(void* base, size_t block_size) {
if (g_segment_count < MAX_SEGMENTS) {
g_segment_registry[g_segment_count].segment_base = base;
g_segment_registry[g_segment_count].block_size = block_size;
g_segment_count++;
}
}
static size_t lookup_segment_size(void* ptr) {
for (int i = 0; i < g_segment_count; i++) {
void* base = g_segment_registry[i].segment_base;
if (ptr >= base && ptr < (char*)base + SEGMENT_SIZE) {
return g_segment_registry[i].block_size;
}
}
return 0; // Not found
}
```
### 作業工数
- Day 1-2: ファイル作成、基本実装
- Day 3-4: ルーティング統合、テスト
- Day 5: ベンチマーク、チューニング
- Day 6-7: バグ修正、最適化
### 成功基準
- ✅ mid_large_mt: 100+ M ops/smimalloc の 82%以上)
- ✅ 他のベンチマークへの影響なし
- ✅ 学習層64KB以上は無変更
### リスク管理
- サイズ検索のオーバーヘッド → segment registry で解決
- メモリオーバーヘッド → 64KB chunkmimalloc並み
- スレッド数が多い場合 → 各スレッド独立、問題なし
詳細設計: `docs/design/MID_RANGE_MT_DESIGN.md`(次に作成)
---
## 🔧 Phase 2: ChatGPT Pro P1-P2中優先、3-5日
### 目標
- Random Mixed: 22.5M → 24M (+7%)
- Tiny Hot: 215M → 220M (+2%)
### 実装項目
#### 2.1 P1: Quick補充の粒度可変化
**現状**: `quick_refill_from_sll` は最大2個
```c
if (room > 2) room = 2; // 固定
```
**改善**: `g_frontend_fill_target` による動的調整
```c
int target = g_frontend_fill_target[class_idx];
if (room > target) room = target;
```
**期待効果**: +1-2%
#### 2.2 P2: Remote Freeしきい値最適化
**現状**: 全クラス共通の `g_remote_drain_thresh`
**改善**: クラス別しきい値テーブル
```c
// Hot classes (0-2): 高しきい値(バースト吸収)
static const int g_remote_thresh[TINY_NUM_CLASSES] = {
64, // class 0: 8B
64, // class 1: 16B
64, // class 2: 32B
32, // class 3: 64B
16, // class 4+: 即時性優先
// ...
};
```
**期待効果**: MT性能 +2-3%
### 作業工数
- Day 1-2: P1実装、テスト
- Day 3: P2実装、テスト
- Day 4-5: ベンチマーク、チューニング
---
## 📈 Phase 3: Long-term Improvements長期、1-2ヶ月
### ChatGPT Pro P3: Bundle ノード
**対象**: 64KB以上の Large Pool
**実装**: Transfer Cache方式tcmalloc風
```c
// Bundle node: 32/64個を1ードに
typedef struct BundleNode {
void* items[64];
int count;
struct BundleNode* next;
} BundleNode;
```
**期待効果**: MT性能 +5-10%CAS回数削減
### ChatGPT Pro P5: UCB1自動調整
**対象**: パラメータ自動チューニング
**実装**: 既存 `hakmem_ucb1.c` を活用
- Frontend fill target
- Quick rush size
- Magazine capacity
**期待効果**: +3-5%(長期的にワークロード適応)
### ChatGPT Pro P6: NUMA/CPUシャーディング
**対象**: Large Pool64KB以上
**実装**: NUMA node単位で Pool 分割
```c
// NUMA-aware pool
int node = numa_node_of_cpu(cpu);
LargePool* pool = &g_large_pools[node];
```
**期待効果**: MT性能 +10-20%(ロック競合削減)
---
## 📊 最終目標Phase 1-3完了後
| ベンチマーク | 現状 | Phase 1後 | Phase 2後 | Phase 3後 |
|------------|------|-----------|-----------|-----------|
| **Tiny Hot** | 215 M | 215 M | 220 M | 225 M |
| **Random Mixed** | 22.5 M | 23 M | 24 M | 25 M |
| **mid_large_mt** | 46 M | **110 M** | 115 M | 130 M |
**総合評価**: mimalloc と同等~上回る性能を達成
---
## 🎯 実装優先度まとめ
### 今週(最優先)
1. ✅ ドキュメント更新(完了)
2. 🔥 **Phase 1: Mid Range MT最適化**(始める)
- Day 1-2: 設計ドキュメント + 基本実装
- Day 3-4: 統合 + テスト
- Day 5-7: ベンチマーク + 最適化
### 来週
3. Phase 2: ChatGPT Pro P1-P23-5日
### 長期1-2ヶ月
4. Phase 3: P3, P5, P6
---
## 🤔 設計原則(ハイブリッド案)
### 1. 領域別の最適化戦略
```
≤1KB (Tiny) → 静的最適化(学習不要)
P0完了、これ以上の改善は限定的
8-32KB (Mid) → MT性能最優先学習不要
mimalloc風 per-thread segment
≥64KB (Large) → 学習ベースELO戦略
ワークロード適応が効果的
```
### 2. 学習層の役割
- **Tiny**: 学習しないP0で最適化完了
- **Mid**: 学習しないmimalloc風に移行
- **Large**: 学習が主役ELO戦略選択
→ 学習層のオーバーヘッドを最小化、効果的な領域に集中
### 3. トレードオフ
**mimalloc 真似(全面)**:
- ✅ MT性能最高
- ❌ 学習層が死ぬ
- ❌ hakmem の差別化ポイント喪失
**ChatGPT Pro全面**:
- ✅ 学習層が活きる
- ❌ MT性能が届かない
**ハイブリッド(採用)**:
- ✅ MT性能最高8-32KB
- ✅ 学習層保持≥64KB
- ✅ 段階的実装
-**両者の良いとこ取り**
---
## 📚 参考資料
- `NEXT_STEP_ANALYSIS.md` - ハイブリッド案の詳細分析
- `P0_SUCCESS_REPORT.md` - P0実装成功レポート
- `3LAYER_FAILURE_ANALYSIS.md` - 3層アーキテクチャ失敗分析
- `docs/analysis/CHATGPT_PRO_ULTRATHINK_RESPONSE.md` - ChatGPT Pro 推奨
- `docs/design/MID_RANGE_MT_DESIGN.md` - Mid Range MT設計次に作成
---
**最終更新**: 2025-11-01
**ステータス**: Phase 0完了P0、Phase 1準備中Mid Range MT
**次のアクション**: Mid Range MT 設計ドキュメント作成 → 実装開始