TECH 으로 돌아가기
TECH HACKER NEWS 7분 읽기 23 READS

NES 에뮬레이터를 학습 없이 Qwen 가중치에 '컴파일'한 실험

NES 에뮬레이터를 학습 없이 Qwen 가중치에 '컴파일'한 실험
SOURCE IMAGE · HACKER NEWS

대형 언어 모델을 게임 콘솔로 쓸 수 있을까. nesformer는 이 도발적인 질문을 극단까지 밀어붙인 오픈소스 프로젝트다. 닌텐도 패미컴(NES)의 6502 CPU, 2KB의 작업용 RAM, 그리고 카트리지의 프로그램 ROM을 평범한 Qwen3.5 계열 체크포인트(Qwen3_5ForCausalLM) 안에 집어넣고, 그 가중치만으로 게임을 구동한다. 핵심은 이 가중치를 아무도 '학습'시키지 않았다는 점이다. 데이터로 훈련한 결과가 아니라, 컴파일러가 모든 수치를 직접 계산해 채워 넣었다. 게임을 실행하면 모델은 CPU의 실행 로그를 한 토큰씩 예측하고, 그 바깥에서 작은 호스트 프로그램이 화면을 그리고 컨트롤러 입력을 읽으며 수직 블랭크(vblank) 인터럽트를 발생시킨다.

가중치를 메모리로 쓰는 발상

nesformer는 Divyansh Agrawal이 만든 Qwenputer를 토대로 한다. Qwenputer는 CHIP-8과 RISC-V CPU를 Qwen3.5-4B에 컴파일한 선행 작업으로, nesformer는 그 컴파일러와 가장 중요한 트릭을 그대로 가져왔다. 바로 모델의 Gated DeltaNet 상태를 기계의 메모리로 사용하는 방식이다. DeltaNet의 각 헤드는 128×128 크기의 상태 행렬을 유지하며, 매 토큰마다 델타 규칙으로 이 행렬을 갱신한다. 게이트를 열어 둔 채 원-핫(one-hot) 키로 갱신하면 행렬의 한 행만 정확히 덮어쓰이고, 원-핫 쿼리로는 그 행을 되읽을 수 있다. 결국 각 행이 하나의 메모리 셀이 되고, 카트리지와 RAM, 레지스터가 모두 이 행들 안에 자리 잡는다.

주목할 만한 설계가 하나 더 있다. 프로그램 카운터(PC)를 명시적으로 저장하지 않는다는 점이다. 명령어마다 레코드가 만들어지고 마지막 토큰이 그 명령을 확정하는데, 이 마지막 토큰이 명령어의 길이 정보를 담는다. 세 개의 DeltaNet 카운터가 마지막 분기 이후 길이별 명령 수를 세고, PC는 분기 목표 주소에 그 누적값을 더해 계산된다. 실제 게임 코드에서 명령어당 평균 토큰 수는 1.1~1.3개로, 대부분의 명령은 토큰 하나로 처리된다.

검증은 꼼꼼하지만 속도는 가혹하다

이 프로젝트에서 신뢰를 좌우하는 것은 정확성 검증이다. 참조용 CPU 구현은 6502 테스트의 사실상 표준인 nestest의 골든 로그를 3,348개 명령에 걸쳐 일치시키고, py65 에뮬레이터와는 570만 개 명령 분량의 게임 코드에서 들어맞는다. 번들로 제공되는 테스트 게임에서는 모델이 생성한 모든 프레임이 통상적인 6502 에뮬레이터 출력과 정확히 일치한다. 가중치 폴더는 특별한 코드 없이 Qwen3_5ForCausalLM.from_pretrained로 그대로 로드되는 평범한 Hugging Face 포맷이라는 점도 재현성 측면에서 의미가 있다.

다만 실용 속도는 냉정하게 봐야 한다. numba로 컴파일하고 전부 0인 블록을 건너뛰는 기본 엔진은 한 개의 CPU 코어에서 초당 약 1,650토큰을 낸다. 순수 numpy 엔진은 약 210, 표준 transformers는 약 10토큰 수준이다. 그런데 실제 NES가 제대로 돌아가려면 초당 약 70만 토큰이 필요하다. 프레임 하나에 1~6초가 걸리므로, NES 시간으로 10초에 해당하는 600프레임을 뽑는 데 약 25분이 든다. 게임이 매 프레임 대부분을 vblank 대기 루프에 쓴다는 점을 이용해, 루프 본문이 변화 없이 반복되면 클럭을 다음 PPU 이벤트 직전으로 건너뛰는 최적화가 들어가 토큰 수를 2.6~4.2배 줄인다. 그럼에도 전체적으로 실제 콘솔보다 150~290배 느리다.

실무자에게 주는 함의

구동할 수 있는 게임은 iNES 매퍼 0, 즉 NROM 보드를 쓰는 타이틀로 한정된다. 슈퍼마리오브라더스, 동키콩, 익사이트바이크가 여기에 해당한다. ROM은 사용자가 직접 준비해야 하고, 프로젝트가 기본 제공하는 것은 자유 라이선스의 테스트 ROM 세 개뿐이다. 입력은 프레임 범위와 버튼 조합을 지정하는 방식으로 스크립팅할 수 있으며, ROM을 시작 시점에 모델 상태로 적재하기 때문에 같은 가중치로 여러 NROM 게임을 재빌드 없이 돌릴 수 있다. 전체 코드는 MIT 라이선스로 공개돼 있다.

이 작업을 '느린 에뮬레이터'로만 읽으면 요점을 놓친다. nesformer가 보여 주는 것은, 결정론적이고 검증 가능한 상태 기계를 트랜스포머 계열 구조의 상태 공간에 '컴파일'해 넣을 수 있다는 존재 증명이다. 학습으로 얻은 근사치가 아니라 모든 가중치가 설계된 값이기에, 출력이 참조 구현과 비트 단위로 일치하는지 확인할 수 있다. 실무 관점에서 당장 쓸 데가 있는 기술은 아니지만, 선형 어텐션 계열 상태가 사실상 메모리처럼 동작한다는 점, 그리고 신경망 구조를 범용 계산의 틀로 바라보는 시도는 모델 내부를 이해하려는 사람에게 생각할 거리를 준다. 한계 역시 분명하다. 매퍼 0에 묶인 호환성, 실사용이 불가능한 속도, 그리고 이것이 성능 최적화가 아니라 개념 실증이라는 성격을 전제로 받아들여야 한다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://github.com/dbreunig/nesformer
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...