회사 테크

재시도는 어디까지 메우나 — Qwen3.8-27B 4bit, Terminal-Bench 89개 pass@2 46 대 53

Qwen3.8-27B MLX 4bit(17GB) 2회차. 1회차 실패 54개를 같은 조건으로 다시 돌려 pass@2 46/89(51.7%)로 올렸습니다. 복구 11개 중앙값 6.5분, 세 모델 중 27B만 푼 태스크 2개, 여전히 안 되는 43개. 그리고 실패만 재시도가 왜 더 오래 걸리는가.

삽질하는개발자

뉴런 네트워크 일러스트

요약

어제 글에서 Qwen3.8-27B 4bit(17GB)을 Flash Next 두 모델과 같은 조건으로 Terminal-Bench 2.1 89개에 한 번 돌려 **35/89 (39.3%)**를 얻었습니다. pass@k는 실패한 것만 다시 돌리는 게임입니다. 그래서 1회차에서 통과하지 못한 54개를 완전히 동일한 조건(terminus-2, ctx 120K, temperature 0.3, reasoning xhigh, 타임아웃 1.0×)으로 2회차를 돌렸습니다. 23시간 49분이 걸렸습니다.

결과: pass@2 = 46 / 89 (51.7%) — 1회차 35 + 이번에 복구한 11입니다.

54개 재시도 내역은 PASS 9, 타임아웃 시점에 답이 맞아 통과한 PASS(TO) 2, FAIL 10, TO 33입니다.

pass@k 27B 4bit (17GB) Flash Next stock (100GB) Uncensored 4bit
pass@1 35 (39.3%) 45 41
pass@2 46 (51.7%) 53
pass@5 64 59

한 번 더 돌리자 27B는 35→46으로 11개를 메웠습니다. 같은 조건에서 원본은 pass@1 45 → pass@2 53이었으니, 격차는 10에서 7로 좁혀졌습니다. 6배 작은 모델이 재시도로 절반을 넘긴 것은 그 자체로 의미가 있지만, 원본을 따라잡지는 못했습니다.

복구된 11개 — 무엇이 메워졌나

태스크 2회차 소요 1회차 다른 모델
nginx-request-logging PASS 1.5분 FAIL ddalcu·Uncensored 모두 통과했던 것
merge-diff-arc-agi-task PASS 2.9분 FAIL
sqlite-with-gcov PASS 3.9분 FAIL
polyglot-c-py PASS 4.9분 TO
query-optimize PASS 6.0분 FAIL 세 모델 중 27B만
regex-log PASS 6.5분 TO pass@5에서 통과했던 것
distribution-search PASS 8.3분 TO ddalcu·Uncensored 통과
torch-tensor-parallelism PASS(TO) 15.0분 FAIL
caffe-cifar-10 PASS 19.9분 TO
compile-compcert PASS 28.7분 TO 세 모델 중 27B만
mcmc-sampling-stan PASS(TO) 30.0분 TO ddalcu·Uncensored 통과

복구된 11개의 소요시간 중앙값은 6.5분입니다. 절반이 10분 안에 끝났습니다. 이 태스크들은 대부분 “어려워서 못 푼” 것이 아니라 “한 번은 헛디뎠지만 두 번째엔 곧장 걸어간” 것들입니다. 1회차에서 nginx-request-logging(4분)·merge-diff(5분)처럼 짧게 FAIL로 끝났던 것들이 2회차엔 1~3분 만에 PASS로 돌아왔습니다. 답에 이르는 길이 짧은 태스크에서 27B의 분산이 크다는 뜻입니다. 같은 문제를 두 번 주면 한 번은 맞힙니다.

반대편 끝에는 compile-compcert(29분)·caffe-cifar-10(20분)·mcmc-sampling-stan(30분)처럼 오래 걸려 복구된 것들도 있습니다. CompCert를 Coq 8.16.1로 configure하고 make로 빌드해 통과했고, MCMC는 4체인·10만 반복을 제한시간 끝에 맞춰 PASS(TO)를 받았습니다.

세 모델 중 27B만 푼 두 태스크

11개 복구 중 아홉은 이미 Flash Next 계열(원본 또는 Uncensored)이 어느 회차에서든 통과했던 태스크입니다. 그러나 두 개는 다릅니다.

  • compile-compcert — 원본은 pass@5까지 전부 타임아웃, Uncensored는 pass@5에서도 FAIL이었습니다. 시리즈 전체에서 이 태스크를 통과시킨 것은 27B가 처음이자 유일합니다.
  • query-optimize — 원본·Uncensored 모두 pass@5까지 FAIL이었습니다. 역시 27B만 6분 만에 통과했습니다.

작은 모델이 큰 모델을 전 구간에서 밑도는 것이 아니라, 태스크에 따라 앞서기도 한다는 증거입니다. pass@k 합산 점수는 27B가 뒤지지만, “이 특정 문제는 어느 모델이 푸느냐”는 질문에는 순위가 뒤집히는 칸이 있습니다.

왜 실패한 것만 재시도가 더 오래 걸렸나

돌리는 도중 “전체 89개(1회차 31시간)보다 실패 54개 재시도(2회차 24시간)가 왜 이렇게 오래 걸리냐”는 질문을 받았습니다. 직관과 반대로 보이지만 정상입니다. 1회차 89개의 실제 소요를 통과·실패로 갈라 보면 이유가 분명합니다.

그룹 개수 평균 소요 합계
PASS 35 6.9분 4.0시간
실패 54 28.2분 25.4시간

통과하는 태스크는 답을 찾으면 즉시 끝나 평균 7분이고, 89개 전체 실행시간 중 이 35개가 차지한 것은 4시간뿐이었습니다. 반면 실패하는 태스크는 제한시간(15·30·60·200분)을 끝까지 다 쓰고 TO가 납니다. 1회차 태스크 소요 합계 29시간 중 25시간을 이 54개가 잡아먹었습니다. pass@k 재시도는 정의상 이 “시간 잡아먹는 54개”만 골라 다시 돌리는 것이라, 빨리 끝나는 태스크가 섞이지 않아 평균이 확 올라갑니다. 실패만 모아 순차로 돌리면 전체를 돌리는 것과 비슷하거나 더 오래 걸리는 것이 당연합니다.

여전히 안 되는 43개

두 번을 줘도 통과하지 못한 43개(FAIL 10 · TO 33)의 실패 양상은 1회차와 판박이였습니다.

  • 130K 컨텍스트 wedge — custom-memory-heap-crash는 정적 소멸자 크래시를 못 잡고 287턴을 돌다 컨텍스트가 130K에 부딪혔습니다.
  • heredoc 함정 — make-mips-interpreter·regex-chess는 터미널이 heredoc에 갇혀 종료 마커를 못 보내고 반복 루프에 빠졌습니다.
  • “verified” 후 오답 — mailman은 “3개 테스트 모두 통과”라 자체 보고한 뒤 채점에서 FAIL, sparql-university도 “쿼리 정상·저장 완료”라 하고 FAIL이었습니다. 자기 검증을 과신하는 27B의 고질이 다시 나왔습니다.
  • 반복 루프 — build-pov-ray는 SourceForge 차단 뒤 200분 내내 같은 미러를 두드렸습니다.

그리고 이 43개 중 19개는 세 모델(27B·원본·Uncensored)이 pass@5까지 모두 통과하지 못한 태스크입니다. 벤치마크 자체가 어려운 칸이고, 여기서는 모델 크기나 재시도 횟수로 메워지지 않습니다.

세 번째로

pass@1 35 → pass@2 46. 다음 재시도의 기대 복구율은 빠르게 떨어집니다. 남은 43개 중 절반(19개)은 시리즈 전체가 손대지 못한 태스크이고, 나머지도 130K wedge·heredoc·자기검증 오류처럼 횟수가 아니라 하네스나 프롬프트를 손대야 풀릴 실패들입니다. 그래도 pass@k 곡선을 원본(64)·Uncensored(59)와 같은 지점까지 그려두는 편이 비교표를 정직하게 만듭니다. 3회차는 남은 43개로 돌리고 있습니다.

한 가지는 이번에도 분명했습니다. 반복 루프 감지를 하네스에 넣지 않는 한, 같은 태스크가 같은 방식으로 매 회차 제한시간을 태웁니다. 그것이 24시간의 대부분이었습니다.