diff options
Diffstat (limited to 'docs/research')
| -rw-r--r-- | docs/research/137-batch-executor-stage-four.md | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/docs/research/137-batch-executor-stage-four.md b/docs/research/137-batch-executor-stage-four.md new file mode 100644 index 0000000..b391ccc --- /dev/null +++ b/docs/research/137-batch-executor-stage-four.md @@ -0,0 +1,66 @@ +# 137 — 묶음 실행기 4단계: 열을 제자리에서 읽고, 비교가 레인을 센다 + +2026-10-08. [025](../design/025-batch-programs.md)의 4단계다. knapsack의 훑기 여섯 가운데 둘(열을 레인 배열로 옮기기 둘)과 하나(가르기의 +세기)를 없앴다. 코드는 `d740ff3`(열 보기)와 `43854e9`(비교가 1을 센다)이고, 같은 방법으로 쟀다(`b15`, `b16`; 번갈아 다섯 번씩, b9와 +세 번씩; 명령 수). + +## 쉬운 말로 + +- **막대를 넘었다.** knapsack은 10.07에서 8.25 ms다(막대 ≤ 8.6). b9의 11.46에서 −28%이고, 기계어(7.9)의 1.04배다. +- **남은 차는 커널이 아니라 묶음마다다.** 지금 knapsack 8.25 ms는 대략 커널 약 4 ms(더하기 1.7, 비교 1.7, 가린 쓰기 0.55), 묶음마다 + 약 3 ms(0.6 µs × 4,886), 표 만들기 약 1 ms다. 더하기와 비교는 레인당 약 0.8 사이클씩이다. 둘을 한 루프로 합치면 같은 열을 두 번 + 읽지 않겠지만, 이 설계는 합친 연산을 두지 않는다(133). 기계어에 닿거나 넘으려면 묶음마다의 해석(135가 이 꼴의 바닥이라 한 것)을 + 줄여야 하고, 그것은 루프마다 미리 짠 프로그램의 일이다. +- **다른 일은 그대로다.** 명령 수로 roots, join, BFS, matmul이 같다. matmul 25.84 → 26.27(+1.7%), sort 57.0 → 58.8(+3.2%), words + 215.3 → 219.0(+1.8%)은 명령이 같거나 이 단계가 닿지 않는 일이라 놓인 자리다. + +## 만든 것 + +- **열 보기**(`cells_at`). 아핀 행이 메모리의 차례(보폭 1; 거꾸로 가는 루프는 레인을 거꾸로 매겨 그렇게 된다)이고 열이 4바이트나 8바이트면, + 읽기는 복사하지 않고 열 자체를 레인으로 가리킨다(`view`, `temp` 아님). `pass` 동안 리스트는 바뀌지 않으므로(136의 grep) 보기는 그 동안 + 맞다. 연산은 피연산자의 레인에 쓰지 않는다(grep: 레인을 읽는 곳은 모두 `const`, 쓰기는 모두 새 버퍼). `pass`를 넘어 남는 것 여섯(지역 + 변수, 미룬 쓰기의 행과 값, 덧붙이기의 칸, 칸에 더하기의 행과 e, 걸러내기의 키, 읽기의 기록)은 보기를 복사한다(`own`). 묶음 끝의 쓰기가 + 열을 바꾸거나 넓히기(`widen`은 열을 다시 잡는다) 때문이다. + - 고정 소스 `VIEW_SOURCE`를 더했다: 지역 변수가 묶음이 쓰는 필드를 쥔 채(마지막 값을 쓰기 뒤에 되씀), 같은 열의 세 행 너머를 읽는 + 쓰기를 읽는 것을 덮어쓰는 차례로, 보기를 쥔 채 열을 8바이트로 넓히는 쓰기. 복사를 빼면 같은 메시지에서 답이 달라지고, sanitized + `pure-run`이 `memcpy`의 겹침을 잡는다. 복사가 있으면 세 길이 같고 sanitized도 깨끗하다. + - knapsack 명령 −4.0%, 사이클 −7.0%, 10.09 → 8.95 ms(셈 약 1.1 ms와 같다). +- **비교가 레인을 센다**(`TEST`, `ones`). 4바이트 비교가 1을 같은 루프에서 세고(벡터 덧셈 하나, 레인 넷에 명령 8개), 값이 그 수를 + 가진다. 모든 레인이 도는 가르기는 다시 세지 않는다. 레인을 그대로 두고 레인 수가 다른 공간으로 넘기는 길은 없다(`gather`, `expand`, + `outer_*`는 레인 값이면 늘 새 값을 만든다). knapsack 명령 −3.1%, 사이클 −4.5%, 8.96 → 8.25 ms. + +## 잰 것 + +| 일 | b9 | b14 (3단계 끝) | b15 (보기) | b16 (세기) | 기계어 | C | +|---|---:|---:|---:|---:|---:|---:| +| knapsack | 11.46 ms | 10.09 | 8.96 | **8.25** | 7.9 | 6.25 | +| matmul | 39.99 | 25.98 | 25.84 | 26.27 | 14.2 | 7.6 | +| roots | 8.97 | 8.29 | 8.31 | 8.28 | 9.57 | 6.86 | +| join | 117.5 | 115.9 | 116.5 | 116.2 | 84.6 | 31.7 | +| BFS | 24.18 | 24.15 | 24.08 | 24.06 | 7.7 | 9.9 | + +- 명령(b9 → b16, 묶음 길): knapsack −12.2%, matmul −25.5%, roots −7.4%, join −1.3%, BFS −0.2%. 실행기만의 길은 다섯 일 모두 같다. +- join의 실행기만의 길은 빌드마다 같은 명령에서 사이클이 ±10% 오간다(136의 +11%, 이번 b15의 −9%). 그 길의 잣대는 명령 수다. + +원본: `041-batches/2026-10-08-pairs.jsonl`, `2026-10-08-counts.jsonl`. + +## 뜻과 맞음 + +- 커밋마다 시드 1, 2, 3, 5, 23의 무작위 프로그램(기본과 `PURE_SELECT=all`), 고정 소스의 세 길(두 모드; 보기는 sanitized로도), 단위 + 시험이 지났다. +- 단계의 끝(`43854e9`)에서 단위 시험 세 모드, ASan 단위 시험(기본과 실행기 모드), sanitized `pure-run`의 고정 소스(두 모드, `VIEW_SOURCE` + 포함)와 시드 23의 프로그램(두 모드), aup의 검사 두 모드가 지났다. Pure의 `make check`는 처음에 `server_view_workers`가 모듈을 바꾼 뒤의 + 흐름을 10초 기다리다 멈췄다(기억해 둔 시간 검사의 흔들림). 홀로 세 번 돌려 세 번 지났고, 다시 돈 전체 `make check`가 지났다. +- 은행 질의의 명령 수는 b9와 ±0.1% 안이다. TPC-C(번갈아 여섯 번)는 b9 117.4만 대 지금 117.0만 신규 주문/분(−0.3%)이다. + +## 스위트의 자리와 남은 두 틈 + +4단계 뒤의 묶음 실행기(기계어 없이)와 기계어: knapsack 8.25 대 7.9(1.04배), matmul 26.3 대 14.2(1.85배), roots 8.28 대 9.57(기계어보다 +빠름), join 116 대 85(1.37배), BFS 24.1 대 7.7(3.1배). 큰 틈은 둘이다. + +1. **matmul의 안쪽 회차마다의 해석(약 14 ms).** 몸체를 회차마다 명령 하나씩 해석하는 값이고, 135가 이 해석기 꼴의 바닥이라 한 것이다. + 줄이려면 루프마다 미리 짠 프로그램(값의 꼴, 리스트의 사실, 의존 검사를 다 미리 정한 것)이 있어야 한다. 다른 값과 위험이다. +2. **BFS의 후보 꼬리(132의 E).** 걸러내기 뒤 후보 하나에 약 250 명령(간선당 26)이다. 리스트 쪽에서 폭 검사를 한 번에, 비트와 칸을 + 함께 하면 줄어든다. 5단계이고 다른 단계와 독립이다. + +어느 쪽으로 갈지(그리고 기계어를 걷어낼지)는 사용자의 몫이다(131). |
