Skip to content
ioob.dev
Go back

곱셈이 없는 1975년 CPU로 언어모델 돌리기

Autoregressive Language Model on the 6502 Processor

원문 보기 · mattbeton.com · Matt Beton ·
· 8분 읽기

BBC 마이크로 화면에 BitNet 언어모델이 생성한 문장이 떠 있고, 그 아래로 기판이 드러난 사진

출처: Matt Beton — Autoregressive Language Model on the 6502 Processor

BBC 마이크로가 뱉은 문장

Matt Beton은 현대 머신러닝으로 이 기계에 들어가는 가장 강한 언어모델이 무엇인지 보고 싶었습니다. 아버지가 80년대에 쓰던 BBC Model B가 그 기계입니다.

“옛날 옛적에 톰과 릴리는 것들을 보았다 릴리는 슬펐다 그녀의 집 그는 그들을 heartd 릴리와 톰은 말했다 그래 그녀는 어린 소녀가 웃는 것을 보았다 톰은 너무 신났다 그녀의 엄마는 말했다 그래”

(“once upon a time tom and lily saw things lily were sad her house he heartd them ilily and tom said yes she saw a little girl smiled tom was so excited her mom said yes”)

문법은 서고 철자는 대부분 맞습니다. 어휘는 알파벳 26자와 공백 한 개, 은닉 차원은 56이에요. 뜻은 없습니다.

기계에 올리는 과정이 절반은 공작입니다. 추론 코드는 CC65로 6502 명령어까지 컴파일하고, 맥북에서 학습한 모델을 얹은 바이너리를 PlayUEF로 테이프에 실어 보냅니다. 3.5mm 케이블을 직접 만들어 노트북 헤드폰 잭으로 오디오를 재생하면 BBC가 그걸 테이프 드라이브 소리로 믿는다는 거죠.

돌았다는 걸 Matt Beton만 아는 것도 아닙니다. sim65 에뮬레이터로 C 추론 바이너리와 파이썬 레퍼런스 구현의 출력을 맞춰보고, 실물에 올리기 전에 jsbeeb에서 엔진 전체를 돌려봤는데요. 브라우저에서 직접 볼 수도 있습니다. 원문에 걸린 링크는 BBC 마이크로를 띄우고 깃허브에서 테이프 이미지를 받아 명령까지 자동으로 칩니다.

KV 캐시가 32KB를 먹어치운다

이 프로젝트에서 아키텍처는 취향이 아니라 잔여 메모리가 정합니다.

트랜스포머의 어텐션은 토큰마다 이전 토큰 전부와 내적을 합니다. 복사나 needle-in-a-haystack 문제에 강한 건 그 정확한 회상 덕이죠. 알파벳 26자로 짧은 동화를 잇는 데 그 정밀도가 필요할까요. 대가는 확실합니다. KV 캐시가 토큰을 만들 때마다 n_layer × hidden_dim씩 자라고, 32KB 예산에서는 가중치를 넣고 싶은 자리를 캐시가 먹습니다.

토큰이 생성될 때마다 어텐션이 이전 토큰 전부로 뻗어나가고 KV 캐시가 커지는 애니메이션

출처: Matt Beton — Autoregressive Language Model on the 6502 Processor

그래서 상태 크기가 고정된 계열로 갑니다. SSM이나 RNN은 은닉 상태 h의 크기가 정해져 있어서 매 스텝 계산 모양이 똑같아요.

GRU는 학습마다 터졌습니다. 순환 한 스텝마다 오차가 순방향 행렬의 최대 고윳값 크기로 증폭되는데, 삼진 양자화 영역에서는 그 스펙트럴 반경이 1을 훌쩍 넘습니다. 1 근처로 눌러 놓으려면 가중치의 98%가 0이어야 하죠. 모든 학습 시도가 발산했습니다.

살릴 방법이 없진 않았습니다. 주 가중치 행렬만 int4처럼 높은 정밀도로 저장하면 됩니다. 문제는 그게 모델에서 가장 큰 행렬이라는 점인데요. 그 순간 쓸 수 있는 차원이 통째로 쪼그라듭니다. Mamba를 고른 건 채널별 스칼라 감쇠값이 추론 시점에 [0, 128)/128 범위에서 계산되기 때문입니다. 구조상 1을 넘을 수 없으니 폭발이 일어날 수 없죠.

150사이클을 30사이클로 줄인 삼진 가중치

6502에는 곱셈 명령이 없습니다. 비트 시프트와 덧셈을 반복해서 만들어야 하고, 8×8 곱셈 누산 하나에 150클럭이 듭니다.

BitNet은 가중치를 {-1, 0, 1} 삼진으로 눌러서 이 문제를 통째로 없앱니다. 곱셈이 사라지고 건너뛰기·덧셈·뺄셈만 남으니 같은 누산이 30클럭이에요. 다섯 배죠. 실제 추론 루프의 안쪽은 이렇게 생겼습니다. 패킹된 바이트에서 2비트씩 꺼내 세 갈래로 분기합니다.

switch (b & 0b11) {
    case 0b00:                                            // 0 → 건너뜀
        break;
    case 0b01:
        a += x->data[j + x->width * (4 * k + l)];         // +1 → 더함
        break;
    case 0b10:
        a -= x->data[j + x->width * (4 * k + l)];         // -1 → 뺌
        break;
}
b = b >> 2;   // 다음 파라미터를 노출

파라미터 하나가 차지하는 정보량은 log₂3 = 1.58비트입니다. 그러면 바이트에 몇 개를 담을 것인가에서 밀도와 속도가 맞교환됩니다.

Matt Beton은 추론 속도를 이유로 4개를 골랐습니다. 밀도를 내주고 속도를 샀어요. 낮은 양자화로 파라미터 수를 늘리는 쪽이 높은 정밀도로 적게 담는 쪽보다 남는 장사라는 건 그와 별개 명제인데, 저자는 실험으로 확인했다는 한 줄만 붙이고 결과는 내놓지 않습니다.

8비트로 눌러 담을 때 정보가 죽는 지점

활성값은 8비트로 저장됩니다. 누산 항 하나가 128 이하이니 16비트 누산기에 256개까지 넘치지 않고 쌓을 수 있고, 이게 모델 차원의 상한이 됩니다. 문제는 다시 8비트로 내려올 때죠.

16비트를 그냥 clip(x, -128, 127)로 자르면 대부분이 벽에 붙습니다. 저자가 든 계산이 명확합니다. Uniform(-128, 127) 값 64개를 누산하면 표준편차가 약 591이라, 값의 83%가 -128이나 127에 눌러 붙어요. 그래서 학습되는 시프트 값 shr을 두고 clip(x >> shr, -128, 127)로 내립니다. 이 값은 1만 바뀌어도 활성 크기가 두 배나 절반이 되는 예민한 파라미터라, 학습 전반부에는 움직이게 두고 후반부에는 얼려 버립니다.

shr이 커질수록 입력 범위는 넓어지지만 출력은 -128에서 127로 고정되는 클램프 곡선들

출처: Matt Beton — Autoregressive Language Model on the 6502 Processor

소프트맥스도 같은 방식으로 우회합니다. 지수 함수가 없으니 온도 T에 맞춰 round(255 × e^(-d/T)) 값을 미리 표로 만들어 둡니다. T = 0.9[255, 83, 27, 9, 3, 1, 0, 0, ...]이고요. 최댓값을 빼서 안정화한 로짓을 이 표에 넣고, 16비트 유사난수를 배열 합으로 나눈 나머지로 뽑습니다.

여기서 시드를 넣을 데가 없습니다. 사용자 입력 없이는 6502에서 난수를 끌어올 경로가 아예 없어서, 시드가 고정이고 같은 문장이 매번 나옵니다.

저자가 결과를 적는 문장에는 볼드가 하나 박혀 있습니다.

“이 모델링과 추론 작업의 결과물은 BBC 마이크로에서 실제로 추론을 돌리는 Mamba 기반 모델이다. 그리 똑똑하진 않지만, 요즘 모델과 비슷한 종류의 모델을 1980년대 하드웨어에서 돌린다는 걸 보여주긴 한다. 꽤 멋지다!”

(“The result of this modeling and inference work is a Mamba-based model that actually runs inference on the BBC Micro. While it isn’t particularly intelligent, it does demonstrate running a model similar to contemporary models on hardware from the 1980s. Pretty awesome!”)

느낌표를 찍을 자격이 있습니다.

하드웨어 제약이 달랐다면 지금 표준이 된 아키텍처도 옵티마이저도 달랐을 거라는 게 Sarah Hooker의 하드웨어 로터리 가설이고, 글 마지막에 끌어오는 것도 이 가설입니다. 정작 Matt Beton이 자기 작업을 요약하며 쓴 단어는 따로 있는데요. 기계적 공감(mechanical sympathy), 곧 모델링 결정을 하드웨어를 염두에 두고 내려야 한다는 뜻입니다.

이 글이 실제로 증명한 건 그 가설의 역방향입니다. 1975년 칩의 제약을 다시 걸었더니 어텐션이 떨어져 나가고 GRU가 떨어져 나가고 부동소수점이 떨어져 나갔습니다. 남은 조합인 Mamba도 BitNet도 2023년 말 이후 논문이에요. 반세기 전 제약이 최신 연구를 골라냈습니다.


Share this post on:

Comments

Loading comments...