회사 테크

5회차, 포화라던 곡선이 다시 올랐다 — 원본 Qwen3.8 pass@5 64/89 (71.9%)

원본 mixed-4-8bit Qwen3.8 Flash Next의 Terminal-Bench 2.1 5회차(pass@5) 결과. 29개 재시도에서 4개 복구, 타임아웃 직전 제출 2건, 120K 컨텍스트 핸드오프와 fallback 루프까지 12시간 30분의 기록

삽질하는개발자

시냅스 일러스트

요약

3편에서 증분이 8 → 5 → 2로 줄어 “곡선이 포화 중”이라고 썼습니다. 남은 29개를 같은 조건으로 다섯 번째 돌렸더니 4개가 뒤집혔습니다. 예상이 틀렸습니다.

결론은 **pass@5 = 64/89(71.9%)**입니다. 공식 Terminal-Bench가 5 trial 기준이니 원본 쪽 시도는 여기서 채워집니다.

시도 원본 ddalcu Uncensored ARC4NUM
1회 (pass@1) 45 / 89 (50.6%) 41 / 89 (46.1%)
2회 누적 53 / 89 (59.6%)
3회 누적 58 / 89 (65.2%) 56 / 89 (62.9%, best-of-3)
4회 누적 60 / 89 (67.4%)
5회 누적 (pass@5) 64 / 89 (71.9%)

증분은 8 → 5 → 2 → 4입니다. 다만 정직하게 적자면 4개 중 2개는 AgentTimeoutError로 끝났는데 디스크에 남은 파일이 채점을 통과한 PASS(TO)입니다. 모델이 “다 했다”고 말한 적이 없는 통과가 절반이라는 뜻입니다.

5회차에서 무슨 일이

29개를 돌려 4개 복구, 5개 FAIL, 20개 TO였습니다. 12시간 30분, 태스크당 평균 24.2분입니다.

raman-fitting (3.2분, 14턴) — 그래핀 라만 스펙트럼의 G/2D 피크를 피팅하는 태스크입니다. Uncensored는 3회 전패, 원본도 4회 내내 3~4분 만에 “검증 완료”하고 틀렸습니다. 이번 궤적은 시작부터 달랐습니다. 데이터 파일이 **소수점을 쉼표로 쓰는 유럽식 표기에 x축이 파장(nm)**이라는 걸 3턴째에 알아채고 파수(1/λ)로 변환하자 레이저 라인(~525 cm⁻¹)·G(1580)·2D(2670)가 교과서 위치에 나타났습니다. 그 뒤 Lorentzian+offset과 Gaussian을 둘 다 피팅해 잔차로 비교한 다음 제출했습니다. 같은 3분이지만 “데이터 형식을 먼저 의심했느냐”가 갈랐습니다.

overfull-hbox (9.3분, 25턴) — 좁은 textwidth의 LaTeX 문서에서 동의어 사전만 써서 overfull hbox 경고 7개를 없애는 태스크입니다. Uncensored만 통과했던 6개 중 하나였는데 원본이 다섯 번째에 따라잡았습니다. 처음엔 이전 회차처럼 경고 줄의 단어를 하나씩 짧은 동의어로 바꿨는데, 줄바꿈이 밀리면서 새 overfull이 생기는 두더지잡기에 빠졌습니다. 여기서 이전 네 번과 갈립니다. 15턴째에 “줄바꿈은 전역 최적화 문제”라고 결론짓고, 110개 동의어 계열을 대상으로 매 반복마다 ~600번 컴파일하는 greedy 탐색 스크립트를 써서 7 → 5 → 3 → 2 → 1 → 0으로 수렴시켰습니다. 손으로 안 되면 도구를 만든다는 전환이 처음 나왔습니다.

torch-pipeline-parallelism (15.0분 TO, 19턴) — AFAB 파이프라인 병렬 학습 스텝을 구현하는 태스크입니다. 컨테이너에 torch도 pip도 없어서 이전 네 번은 전부 설치 시도에서 시간을 다 썼습니다. 이번엔 설치를 4분 만에 포기하고 구현을 먼저 써 놓은 뒤 검증에 들어갔고, 자기 검증 스크립트가 requires_grad 붙은 loss 텐서를 큐로 못 넘기는 문제에서 시간이 끝났습니다. 하지만 이미 써 둔 train_step_pipeline_afab가 채점기 4개 테스트를 전부 통과했습니다. **“환경을 고치기 전에 답부터 써 두기”**가 갈랐습니다.

winning-avg-corewars (60.0분 TO, 93턴, ctx 63K) — Core War 워리어를 써서 다섯 상대 각각에 정해진 승률 이상을 내는 태스크입니다. 3편의 대표 루프 사례(146턴 · ctx 127K · 107턴 반복)였는데 이번엔 루프가 한 번도 없었습니다. pMARS 소스에 DIE 로그를 패치해 자기 프로세스가 어디서 죽는지 추적하고, 상대 유형별로 워리어 다섯 종을 돌려 승수를 재고, g2-clear 계열에 dec=2700을 얹어 45분 시점에 다섯 임계치를 전부 넘겼습니다. 그리고 남은 15분 동안 “stone 마진이 +1뿐”이라며 최적화를 계속하다 시간이 끝났습니다. 결정적 시드라 +1이면 충분하다고 스스로 적어 놓고도 멈추지 않았습니다. 채점은 5/5 상대 통과입니다.

어디서 갈렸나 (원본 5회 vs Uncensored 3회, 89개 전체) — 최종

구분 개수 태스크
둘 다 통과 52
둘 다 전패 21 path-tracing 계열, regex-chess, feal-linear, make-*-mips, install-windows-3.11, compile-compcert, schemelike, rstan-to-pystan, query-optimize, video-processing 등
원본만 통과 12 circuit-fibsqrt, custom-memory-heap-crash, dna-insert, extract-elf, llm-inference-batching-scheduler, mteb-leaderboard, qemu-startup, sparql-university, train-fasttext, tune-mjcf, raman-fitting, torch-pipeline-parallelism
Uncensored만 통과 4 feal-differential-cryptanalysis, filter-js-from-html, model-extraction-relu-logits, polyglot-rust-c

Uncensored 전용은 6 → 4로 줄었습니다. 남은 4개는 5회 동안 원본이 한 번도 못 넘은 것이라 두 모델의 실제 편차로 봅니다. 단, 시도 횟수가 5 대 3이라 이 표는 아직 공정하지 않습니다 — 아래 “다음”에서 다룹니다.

남은 25개의 실패 해부

① 반복 루프와 컨텍스트 폭주. TO 20개 중 넷이 루프였고, 이번엔 하네스가 루프를 끊는 장면과 못 끊는 장면을 둘 다 봤습니다.

  • path-tracing-reverse 30분 · 230턴 · ctx 129K. 최악의 형태입니다. 프롬프트가 131K를 넘자 서버가 400을 돌려주고, terminus-2는 4단계 fallback(전체 요청 400 → 파싱 오류 재시도 400 → 핸드오프 요약 400 → “Briefly continue” 724토큰 단일 메시지)을 11분 동안 사이클로 돌렸습니다. 서버 400 overflow 카운트가 이 한 태스크에서 +335였습니다. 컨텍스트가 넘친 뒤엔 요약조차 못 보내니 회복 경로가 없습니다.
  • regex-chess 60분 · 194턴 · ctx 120K. 95턴에서 100K를 넘고 120턴 근처에서 같은 메시지 4연속이었습니다. 그런데 120K에서 terminus-2의 컨텍스트 핸드오프(요약)가 발동해 ctx가 47K로 내려갔고, 루프가 풀렸습니다. 이후 74턴은 전부 다른 내용이었습니다. 시간이 9분밖에 안 남아 결과는 TO지만, 3편에서 “필요한 건 강제 행동 전환 장치”라고 썼던 게 우연히 검증된 셈입니다.
  • schemelike-metacircular-eval 40분 · 169턴 · ctx 120K, polyglot-rust-c 15분 · 60턴. 3편과 같은 패턴입니다.

② 아슬아슬한 실패. 넷입니다.

  • query-optimize 5.4분 — 다섯 번째도 6개 중 5개 통과입니다. 실행 시간 0.980초, 기준 0.765초(골든 0.729 × 1.05). 5회 모두 “충분히 빨라졌다”고 제출했습니다.
  • video-processing 7.1분 — 점프 영상에서 이륙/착지 프레임 추출입니다. 발 궤적을 깨끗한 포물선으로 뽑고 takeoff=55·landing=60을 “물리적으로 정확”하다며 제출했는데 채점 허용 범위는 takeoff 5054, landing 6264입니다. 채점기는 발이 뜨는 순간이 아니라 추진 시작과 완전 접지를 봅니다. 정의 차이입니다.
  • rstan-to-pystan 30분 TO — 이번엔 원인이 선명합니다. 샘플링이 100%까지 돌았는데 httpstan 워커 4개 + 부모가 각각 전체 샘플을 들고 있어 메모리가 8 GB cgroup 한계(7.7 GB)에 걸려 종료 단계에서 멈췄습니다. Ctrl+C 후 체인 순차 실행으로 고쳐 재실행했으나 시간 초과였습니다. 순차 실행을 처음부터 택했으면 통과였습니다.
  • model-extraction-relu-logits 11.7분 — 30행 중 20행 복원입니다. 은닉 뉴런 수를 20으로 가정했는데 실제는 30이었습니다.

③ 조기 확신 제출. sanitize-git-repo 4.3분(AWS 키 4개 “모두 제거 확인” → 테스트 2/3 실패), filter-js-from-html 9.7분. 3편과 같습니다.

운영 메모

12시간 30분 동안 서버 재시작 0회, wedge 0건입니다. 가동 시간은 3일을 넘겼습니다. 이번 회차에서 새로 본 것이 셋 있습니다.

  • 400 overflow +335, 전부 path-tracing-reverse의 fallback 루프 11분 동안 발생했습니다. 서버는 멀쩡했고 요청당 수 초 만에 400을 돌려줬으니 부하는 아니었습니다.
  • regex-chess가 122K를 밟는 동안 free 0.2 GB · 메모리 여유 15%까지 떨어졌고 디코드가 41 → 20.7 tok/s로 반토막 났습니다. 핸드오프로 ctx가 47K로 내려가자 10분 안에 free 1 GB · 여유 22% · 디코드 42 tok/s로 회복했습니다. 8-bit KV라도 120K는 이 머신에서 스왑 경계입니다.
  • 00:43에 swap이 한 번에 +2.1 GB 늘면서 mlx-serve RSS가 46 → 40.7 GB로 빠졌습니다(커널이 모델 페이지를 스왑 아웃). 그런데 디코드 속도에 영향이 없었습니다. 활성 가중치가 아닌 페이지가 밀려난 것으로 보이고, 이후 12시간 동안 swap은 천천히 줄기만 했습니다.

다음

이 표의 문제는 시도 횟수입니다. 원본은 5회, Uncensored는 3회(그것도 두 번은 타임아웃 배수를 바꾼 재시도라 엄밀히는 같은 조건이 아닙니다)입니다. 그래서 지금 Uncensored의 best-of-3 실패 33개를 원본과 완전히 같은 조건(제한 1.0×, reasoning high, temperature 0.3)으로 네 번째 돌리고 있습니다. Uncensored 쪽도 4개 이상 뒤집힌다면 “포화” 얘기는 두 모델 다 접어야 합니다.

한 줄 요약: 5번째 시도에서 4개가 뒤집혀 64 vs 56. 포화는 제 착각이었고, 이제 상대편도 같은 횟수를 줘야 합니다.