diff options
Diffstat (limited to 'docs/research')
| -rw-r--r-- | docs/research/140-spec-suite.md | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/docs/research/140-spec-suite.md b/docs/research/140-spec-suite.md index 24d488a..4b799df 100644 --- a/docs/research/140-spec-suite.md +++ b/docs/research/140-spec-suite.md @@ -118,6 +118,66 @@ - **메시지의 행은 중첩의 땜질인가?** 레코드의 리스트를 메시지에만 허락한 것은 중첩이 없어서 낸 길로 보인다. 중첩이 들어오면 따로 둘 까닭이 없다. +## 027의 1단계: SHA-256 (2026-10-13) + +[027](../design/027-computation-core.md)의 1단계를 만들었다. +- **Pure.** 명령 넷이다. + - `I64_BITS`: and, or, xor, 두 시프트. `~x`는 xor −1이다. + - `BYTE_AT`: 자리의 바이트. + - `BYTES_OF`: i64 리스트의 바이트. + - `INDEX_AT`: 자리의 항목. 끝을 넘으면 멈춰 서지 않고 `not_found`다. +- **aup.** + - 16진 리터럴, 파이썬의 우선순위를 따르는 비트 연산자, `b[i]` + - `list of i64`(`number`, `bool`, `text`)와 그 리터럴, 자리로 읽고 쓰기, `bytes(xs)` + - 한 번에 주기 `a, b = x, y`와 `let a, b = …` +- **SHA-256.** aup의 `examples/sha256.aup`에 썼다. + +**맞음.** 공식 벡터를 Pure 안에서 돌려 맞는지 본다. +- 대조한 메시지는 142개다: FIPS 180-2의 예 넷("", "abc", 448비트, 896비트), 채움의 모든 경계를 덮는 길이 0–129, 255–32,000바이트. +- 다이제스트가 세 실행 길(묶음, 실행기만, 기계어)과 기본 길에서 모두 `hashlib`와 같다. +- 이 대조는 Pure의 `make check`(`module_assumptions`, 메시지 135개)에 들어갔다. +- aup의 검사에는 다음이 들어갔다. + - 진단 12건 + - 받아들이는 꼴 하나 + - 무작위 비트 식 192개: 사건 768개, 그중 넘침과 한도 실패 196개가 파이썬의 정수와 같다 + - 바이트와 리스트의 앱 하나 +- Pure 단위 시험(`bits_and_bytes`)은 비트 연산의 끝값 27개, 바이트 읽기 11개, 거절 7개를 본다. + +**막대.** + +| 막대 | 잰 것 | | +|---|---|---| +| 공식 벡터 모두 | 142/142, 세 길 | 지남 | +| 줄 수 ≤ 파이썬 참조 | aup 52줄(닫는 괄호만인 줄 7) 대 파이썬 28줄 | **못 미침** | +| C 대비 시간 | 65,536바이트에서 바이트당 1,591 ns 대 C 9.0 ns: **176배**. 순수 파이썬은 3,708 ns(Pure가 2.3배 빠름) | 기록(막대 없음) | +| 기존 일의 명령 수 | 아래 | 아래 | + +원본: `research/experiments/044-specs/` +- `check.py`: 맞음과 줄 수 +- `time.c`: 같은 바이트로 C와 견준 시간. 다이제스트가 같아야 잰다. +- `sha256.py`: 파이썬 참조 +- `2026-10-13-sha256.jsonl`: 잰 수 + +**줄을 길게 한 것.** 처음 쓴 것은 72줄이었다. 한 번에 주기가 없어서 상태 여덟 개를 옮기는 데만 24줄이 들었다. 그것을 1단계에 +넣어(싸고 범용이다) 52줄이 됐다. 남은 차이는 다음이다. +- 형식 지정이 없다. 16진 다이제스트에 7줄이 들었고, 파이썬은 `f'{x:08x}'` 한 줄이다. +- 바이트를 잇거나 자르지 못한다. 채움에 fn 하나와 바이트마다의 조건이 들었고, 낱말 만들기에 5줄이 들었다. 파이썬은 `data + b'\x80' + …`와 + `int.from_bytes` 한 줄씩이다. +- 리스트를 값으로 짓지 못한다. 메시지 스케줄을 블록마다 다시 만들지 못하고, 64칸을 미리 채워 덮어쓴다. +- `let`의 리스트는 핸들러 맨 바깥에만 둔다. 그래서 해시값을 리스트 대신 이름 여덟 개에 두었다. +- 닫는 괄호의 줄이 7줄이다. + +앞의 넷은 값의 일이라 2단계에 넣는다. 027의 2단계에 형식 지정(16진, 자릿수), 바이트 잇기와 자르기, 값으로서의 리스트를 더한다. + +**시간이 가는 곳.** 블록 하나에 Pure 명령 19,129개가 든다. +- 비트 연산이 21%다. +- fn 호출의 몫(인자를 꺼내는 PICK 16%, 리터럴 CONST 16%, 시프트 수를 바꾸는 I64_FROM 7%)이 39%다. +- `rotr(x, 7)`의 7은 상수인데도 fn을 펼칠 때 접히지 않아, `32 - n`을 매번 수로 계산하고 i64로 바꾼다. 인라인에서 리터럴 인자를 접으면 + 명령의 3분의 1 남짓이 줄 것으로 본다. 컴파일러의 구현 일이다. +- 명령 하나에 약 5.3 ns가 든다. 값의 칸(`Slot`)이 바이트 참조를 함께 들어 PICK마다 48바이트를 옮기는 꼴이다. +- 기계어 계층은 이 루프를 빠르게 하지 못했다. `PURE_JIT=all`이어도 시간이 같다. 새 명령마다 실행기의 걸음을 불러서다. +- 바이트와 비트의 일을 빠르게 하는 것은 핵이 선 뒤의 일이다(027). 그 과녁은 이제 수치 루프가 아니라 이런 일이다. + ## 착수 기준 (다음 일) - **바꿀 결정.** 계산의 핵을 설계한다(027). 위 표의 여덟 후보 가운데 무엇을 어떤 모양으로 받을지 정한다. |
