aboutsummaryrefslogtreecommitdiffstats
path: root/docs/research
diff options
context:
space:
mode:
Diffstat (limited to 'docs/research')
-rw-r--r--docs/research/137-batch-executor-stage-four.md66
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).