aboutsummaryrefslogtreecommitdiffstats
path: root/docs/research/002-checkpoint-results.md
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-24 17:14:54 +0100
committereunhhu <[email protected]>2026-09-24 17:14:54 +0100
commitb1ce1927022d374198441afafeb27199fc8a052a (patch)
tree6021f175f4c67ed03b44240eaa2f90d846f12f6f /docs/research/002-checkpoint-results.md
parentd34f9426d5317a1948f12f229439946728bc342a (diff)
downloadpure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz
pure-b1ce1927022d374198441afafeb27199fc8a052a.zip
Establish native micro runtime checkpoint
Diffstat (limited to 'docs/research/002-checkpoint-results.md')
-rw-r--r--docs/research/002-checkpoint-results.md174
1 files changed, 174 insertions, 0 deletions
diff --git a/docs/research/002-checkpoint-results.md b/docs/research/002-checkpoint-results.md
new file mode 100644
index 0000000..88c1354
--- /dev/null
+++ b/docs/research/002-checkpoint-results.md
@@ -0,0 +1,174 @@
+# Pure 연구 보고서 002: 중간 결과를 얼마나 보관해야 하는가
+
+작성·측정일: 2026-09-22
+상태: **첫 합성 실험 완료. 제품 성능이나 새로운 알고리즘의 입증은 아님.**
+
+후속: [실행 중 규칙 변경 데모와 보관 공간 보고서](003-live-rules.md)를 추가했다.
+
+## 먼저 읽을 내용
+
+중간 계산 결과를 모두 기억하면 수정 후에 다시 계산할 일이 줄어든다.
+일부만 기억하면 메모리를 아끼지만, 수정한 위치에 따라 더 많이 계산해야 한다.
+이번에는 이 관계를 확인할 작은 실행기와 재현 가능한 측정 도구를 만들었다.
+
+16,384개 연산으로 구성한 모델에서, 결과를 매 연산마다 저장하던 것을
+16개마다 저장하도록 바꾸자 **코어의 지속 보관 공간이 262,456바이트에서
+139,576바이트로 46.8% 줄었다.** 이는 자료 구조의 크기를 합산한 값이다.
+프로세스 전체 RAM을 측정한 값은 아니다.
+
+수정이 끝부분에 집중되면 처리 시간은 **67.03ns에서 88.98ns로 약 33% 늘었다.**
+다른 수정 패턴에서는 두 방식의 시간이 비슷하거나, 덜 저장하는 쪽이 짧았다.
+즉, 메모리를 줄이는 것과 모든 작업을 빠르게 하는 것은 각각 확인해야 한다.
+
+이 차이가 사용자가 느끼는 반응 속도에 어떤 영향을 주는지는 아직 모른다.
+위 숫자는 화면·입력 큐·편집기가 없는 작은 계산 실험의 처리 시간이다.
+약 22ns의 차이 자체를 사용자가 느끼는 지연으로 해석하면 안 된다.
+
+이번 결정은 **저장 간격을 제품 기본값으로 정하지 않고, 비교 가능한 선택지로
+유지한다**는 것이다. 실제 앱에서 어떤 정보를 보관해야 하는지 먼저 확인한다.
+
+## 사용자가 확인할 경험
+
+이번 산출물은 명령행 실험이어서 아직 직접 조작할 화면은 없다.
+지금 사용자에게 저수준 실행 방식의 선택이나 성능 수치의 해석을 요구하지 않는다.
+
+다음 사용 경험 검증의 첫 작업은 앞서 제안한 작은 공룡 게임을 실행하면서
+점프 조건을 바꾸고, 바꾼 규칙과 현재 상태를 확인하는 것이다.
+"바꾼 곳을 찾기 어려웠다", "수정하자 진행 상태가 사라졌다",
+"왜 점프하지 않는지 확인할 수 없었다"처럼 구체적인 관찰을 받는다.
+이를 위해 무엇을 상주시켜야 하는지, 무엇을 다시 계산할 수 있는지 분석하는 일은
+Codex가 맡는다. 이번에 이 데모까지 구현한 것은 아니다.
+
+## 무엇을 비교했는가
+
+서로 연결되지 않은 16개의 계산 사슬을 만들었다. 각 사슬은 앞 연산의 결과를
+다음 연산이 사용한다. 길이는 256개와 1,024개를 각각 시험했다.
+연산은 덧셈·XOR·홀수 곱셈·회전/XOR이며, 값은 64비트 부호 없는 정수다.
+오버플로는 정해진 정수 규칙으로 처리한다. 관측하는 값은 각 사슬의 최종 결과다.
+
+연산의 종류·상수와 최초 입력은 실행 중 바꿀 수 있다. 연결 구조는 고정이다.
+이는 앞선 연구 의제 전체를 검증하기 전에 계산·보관 비용만 분리한 실험이다.
+상태 전이, 그래프 연결 편집, 센서, 외부 출력은 아직 포함하지 않았다.
+
+| 방식 | 기억하는 결과 | 수정 시 하는 일 |
+|---|---|---|
+| 전체 재계산 | 사슬의 최종 결과만 | 변경된 사슬을 처음부터 계산 |
+| 매 연산 저장 | 모든 연산의 결과 | 첫 변경 지점부터 필요한 부분 계산 |
+| 일정 간격 저장 | 4·16·64개 연산마다 결과 | 첫 변경 지점 앞의 저장 위치에서 계산 재개 |
+
+모든 방식이 같은 모델·연산·변경 기록을 사용한다. 변경되지 않은 사슬은 모두
+건너뛴다. 저장된 값과 같아져도, 같은 처리 단계에 적용된 마지막 변경 지점을
+지나기 전에는 계산을 멈추지 않는다. 전체 재계산과 매 연산 저장에는 전용 반복문을
+사용해, 저장 간격을 처리하는 일반 반복문의 비용을 불필요하게 부과하지 않았다.
+
+이 실험은 C17로 작성한 측정 장치다. Pure 제품의 언어를 Zig에서 C로 바꾸는 결정은 아니다.
+
+## 공간 결과: 캐시와 전체 보관 공간을 구분한다
+
+아래는 사슬 16개 × 길이 1,024개인 경우다. KiB는 1,024바이트다.
+
+| 저장 간격 | 결과 캐시 | 코어 지속 보관 공간 | 매 연산 저장 대비 감소 |
+|---|---:|---:|---:|
+| 1개 | 128 KiB | 262,456 B | 기준 |
+| 4개 | 32 KiB | 164,152 B | 37.5% |
+| 16개 | 8 KiB | 139,576 B | 46.8% |
+| 64개 | 2 KiB | 133,432 B | 49.2% |
+| 1,024개: 최종 결과만 | 0.125 KiB | 131,512 B | 49.9% |
+
+16개마다 저장하면 캐시는 16분의 1이 된다. 하지만 연산 정의 131,072바이트,
+입력·변경 범위 256바이트, 실행기 구조체 56바이트는 그대로 필요하다.
+따라서 전체 보관 공간은 16분의 1이 되지 않는다.
+
+측정한 공간은 실행기 구조체 크기와 살아 있는 코어 배열의 요청 크기를 합산한 것이다.
+계산식과 실제 할당 배열은 [실험 설명](../../research/experiments/001-checkpoint-granularity/README.md)에 있다.
+할당자 내부 정보, 호출 스택, 실행 파일, OS 페이지는 포함하지 않았다.
+별도로 미리 만든 변경 기록도 제외하며, 기록 크기는 작업에 따라
+4,112·65,552·524,304바이트였다. 이 제외 항목은 모든 방식에 같은 조건으로 적용했다.
+전체 프로세스 메모리와 최대 메모리는 후속 측정 대상이다.
+
+## 시간 결과: 수정 위치에 따라 달라진다
+
+아래도 사슬 16개 × 길이 1,024개다. 단위는 **한 변경 묶음 처리당 마이크로초(µs)**다.
+각 숫자는 7회 측정에서 얻은 묶음 평균 처리 시간의 중앙값이며, 입력 지연의
+P50이나 P99가 아니다. 비교가 쉽도록 전체 재계산·매 연산 저장·간격 16을 나란히 적었다.
+
+| 변경 패턴 | 전체 재계산 | 매 연산 저장 | 16개마다 저장 |
+|---|---:|---:|---:|
+| 모든 사슬의 최초 입력 변경 | 107.713 | 115.260 | 112.930 |
+| 임의 위치의 연산 하나 변경 | 6.339 | 3.401 | 3.375 |
+| 끝 8개 중 연산 하나 변경 | 6.295 | 0.067 | 0.089 |
+| 사슬마다 연산 8개 변경 | 115.972 | 110.094 | 113.426 |
+
+끝부분 수정에서 매 연산 저장은 평균 약 4.55개 연산을 다시 실행했고,
+간격 16은 16개, 전체 재계산은 1,024개를 실행했다. 처리 시간 차이와 함께
+재계산량 증가를 직접 확인한 경우다.
+
+반대로 최초 입력이 모두 바뀌면 세 방식이 같은 16,384개 연산을 실행한다.
+저장과 비교, 반복문 구조 등의 비용이 달라질 수 있다. 어느 비용이 시간 차이의
+주원인인지는 아직 프로파일링하지 않았다.
+
+길이 256에서 간격 16은 최초 입력 변경을 약 13.4% 짧은 시간에 처리했지만,
+끝부분 수정에는 약 28.2% 더 걸렸다. 길이 1,024에서 관측한 1~3% 수준 차이 중에는
+반복 측정 범위가 겹치는 것도 있어 안정적인 속도 개선으로 결론 내리지 않는다.
+간격 4는 두 크기의 네 작업 모두에서 매 연산 저장보다 느린 중앙값을 보였다.
+보관 공간은 간격이 커질수록 줄었지만, 처리 시간은 단순히 같은 방향으로 움직이지 않았다.
+
+선택한 예시 외의 모든 조건과 최소·최대값은
+[전체 요약 표](../../research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv)에 남겼다.
+
+## 검증과 재현
+
+- 기준 구현은 각 사슬을 처음부터 계산한다. 별도 정확성 검사에서 매 변경 단계의
+ 모든 출력을 기준 구현과 비교했다.
+- 여러 시드, 길이 1과 홀수 길이, 한꺼번에 적용하는 변경, 아무 변화 없는 입력,
+ 서로 취소되는 변경, 앞의 변경은 취소되지만 뒤의 변경은 남는 경우를 검사했다.
+- 최적화 빌드와 ASan·UBSan 빌드에서 **각각 108,000개의 변경 단계 검사**를 통과했다.
+ 이는 검사를 통과했다는 뜻이며, 모든 가능한 프로그램의 정확성 증명은 아니다.
+- 성능 측정은 40개 조건 × 7회, 원시 표본 280개다. 각 측정 후 기준 출력 검사를
+ 수행했고, 같은 크기·작업의 방식 간 최종 출력 체크섬도 일치했다.
+- 초기 생성·기록 생성·준비 실행·출력 검사는 시간에서 제외했다.
+ 변경 적용, 실행 대상 선별, 재계산은 포함했다. 측정 구간 내 동적 할당은 없다.
+
+호스트는 **Raspberry Pi 5 / Linux aarch64**, 컴파일러는 GCC 14.2.0, 최적화는 `-O3`다.
+한 CPU에 실행을 고정하고 측정 순서를 섞었다. 공유 호스트이며 전원·온도는 통제하지 않았다.
+256개 처리 단계의 변경 기록을 반복 재생한 준비된 상태의 실험이다. 실제 사람의 입력 분포,
+초기 실행, 장시간 실행과 다른 시드에 대한 성능 평가는 별도로 필요하다.
+**사용자의 M3 macOS에서 측정한 결과가 아니다.**
+
+소스와 실행 스크립트의 해시, 컴파일러·호스트 정보, 검사 통과 결과는
+[실행 환경 기록](../../research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json)에 있다.
+[원시 결과](../../research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv)와
+[실행 방법·소스](../../research/experiments/001-checkpoint-granularity/README.md)를 함께 보관했다.
+보고서 작성 시 현재 소스·스크립트의 해시가 측정 기록과 같은지 확인했다.
+
+## 선행연구와 이번 결과의 위치
+
+계산을 어떤 크기의 단위로 재사용하는지가 성능에 영향을 준다는 문제는 기존 연구에 있다.
+Acar 등의 논문은 의존 관계와 메모이제이션이 재사용하는 단위의 제약을 분석한다.
+이번 고정 간격 실험이 그 논문의 알고리즘을 재현한 것은 아니다.
+[An Experimental Analysis of Self-Adjusting Computation, TOPLAS 2009](https://www.cs.cmu.edu/~blelloch/papers/ABBHT09.pdf)
+
+중간 결과를 버렸다가 다시 계산해 메모리 예산을 맞추는 온라인 정책도 기존 연구에 있다.
+DTR은 이를 텐서 계산에서 다룬다. 작은 스칼라 연산으로 된 이번 실험에 그 성능 결과를
+옮겨 적용할 수는 없다.
+[Dynamic Tensor Rematerialization, ICLR 2021](https://arxiv.org/abs/2006.09616v4)
+
+따라서 이번 결과는 **알려진 공간·시간 관계를 Pure의 첫 측정 장치에서 확인한 것**이다.
+독창적인 기여는 아직 입증하지 않았다. 문헌의 관련 부분을 확인했지만, 후속 연구를
+망라한 체계적 조사나 해당 논문들의 실험 재현을 완료한 상태도 아니다.
+
+## 다음 결정
+
+단순한 사슬은 연결 정보가 암묵적이고, 최종 결과만 필요하다. 실제 앱에서는 하나의 값이
+여러 곳에 쓰이고 편집기가 중간 값을 관찰할 수도 있다. 이때 연결·관찰·편집 정보가
+이번 절감량을 얼마나 상쇄하는지가 다음 질문이다.
+
+1. 사용 경험 검증용 작은 앱의 모델과 변경 의미를 먼저 구체화한다.
+ 실행 중 규칙 변경과 현재 상태 관찰에 필요한 정보를 기록한다.
+2. 그 모델의 분기·합류와 중간 값 관찰을 비교 실행기에 넣는다.
+ 보관 공간을 모델·필수 상태·연결·관찰 정보·캐시로 나누어 측정한다.
+3. 실제로 지배적인 비용을 확인한 후 저장 정책을 선택한다.
+ 고정 간격으로 충분하면 자동 적응 정책의 비용을 추가할 이유가 없다.
+
+초기 의제의 H1인 "변경 특성에 적응하는 정책이 더 유리하다"는 이번 실험으로
+채택하거나 기각할 수 없다. 이번에는 고정 간격만 비교했다.