TL;DR
CacheVerifier의 tenant별 fine-tuning 작업이 1시간 timeout을 무시하고 9시간 40분 동안 멈춘 원인은 RQ SimpleWorker의 SIGALRM 방식이 PyTorch의 단일 C-level self-attention 연산을 선점하지 못했기 때문입니다. 명시적인 max_length 제한이 없어 실제 데이터에서 peak memory가 약 5.6 GB까지 치솟았고, max_length를 128 tokens로 제한하고 batch size를 낮추자 메모리는 약 1.27 GB, 처리 시간은 905초에서 224초로 줄었습니다. 이후 새 모델의 precision이 약 10 percentage points 낮아 보였지만 AUC는 0.890에서 0.8905로 거의 같았고, 전체 threshold sweep에서 두 모델의 곡선도 겹쳐 threshold calibration 차이로 판명됐습니다. 작성자는 live threshold와 hit rate 또는 error rate가 10 percentage points 넘게 달라지는 자동 전환을 막고 명시적 확인을 요구하도록 바꿨으며, 첫 fine-tune에는 이 검사를 제외했습니다.
실용적 조언
- RQ의 timeout을 실제 hard timeout으로 사용해야 한다면 작업을 종료할 수 있는 별도 프로세스 경계를 두는 방안을 우선 검토해야 합니다. 글에서는 SimpleWorker 대신 외부에서 자식 프로세스를 종료할 수 있는 RQ의 regular Worker 전환을 다음 후보로 두고 있습니다. 다만 process fork에 따른 job overhead 때문에 더 가벼운 대안을 찾는 상태이며, 이 부분은 아직 확정되지 않았습니다.
- Transformer 기반 fine-tuning 입력에는 base model의 기본값을 그대로 두지 말고 tenant 데이터에 맞는 max_length 상한을 명시해야 합니다. 긴 입력 하나가 batch 전체의 self-attention 메모리 비용을 키우므로 training batch size도 함께 낮추고 실제 데이터에서 peak memory와 처리 시간을 재측정해야 합니다. 이 사례에서는 max_length 128 tokens와 batch size 조정으로 peak memory가 약 5.6 GB에서 약 1.27 GB로 내려갔습니다.
- Fine-tuned verifier의 모델 품질은 각 모델이 자동으로 선택한 threshold 한 점만 비교하지 말고 전체 cutoff의 operating curve로 평가해야 합니다. AUC가 거의 같은데 production precision이나 hit rate가 크게 달라지면 모델의 구분 능력보다 threshold calibration 차이를 먼저 확인해야 합니다. 새 threshold가 live 운영 지표를 10 percentage points 넘게 바꾸는 경우에는 자동 전환을 막고 사유 기록과 명시적 확인을 거치게 하는 방식이 제안됐습니다.
섹션별 상세
이미지 분석

그래프는 A Static Threshold (GPTCache-style), B Adaptive Threshold (vCache-style), C Synchronous Krites, D This proposal, E Fine-tuned verifier의 hit rate를 error rate에 따라 표시합니다. E Fine-tuned verifier와 D This proposal의 점들은 대체로 error rate 약 0.05~0.07 구간에서 hit rate 약 0.72~0.92로 상승한 뒤 0.94 안팎에 모이며, A 방식은 error rate가 약 0.026에서 0.114까지 커지는 동안 hit rate가 약 0.36에서 0.996까지 증가합니다. 이 시각화는 단일 threshold가 아니라 error rate와 hit rate의 전체 operating curve를 비교해야 한다는 글의 calibration 논점과 연결됩니다.
SemCacheLMArena에서 Error rate와 Hit rate의 관계를 다섯 방식으로 비교한 산점도입니다.
용어 해설
- RQ의 동일 프로세스 작업 실행기(SimpleWorker)
- — SimpleWorker는 작업마다 종료 가능한 자식 프로세스를 따로 만들지 않고 worker 프로세스 안에서 작업을 실행하는 RQ 실행기입니다. 이 구조에서는 타임아웃이 SIGALRM과 Python 예외에 의존하므로, PyTorch처럼 긴 C-level 연산이 진행되는 동안 Python 인터프리터가 제어권을 되찾지 못하면 작업을 즉시 중단하기 어렵습니다.
- Unix 알람 시그널(SIGALRM)
- — SIGALRM은 지정된 시간이 지나면 프로세스에 전달되는 Unix 시그널입니다. RQ의 SimpleWorker는 이 시그널을 받은 뒤 Python 핸들러가 예외를 발생시키는 방식으로 타임아웃을 처리하지만, 프로세스가 하나의 차단된 C-level tensor 연산 안에 머물면 핸들러 실행이 지연될 수 있습니다.
- 셀프 어텐션(self-attention)
- — self-attention은 입력 토큰 사이의 관계를 계산해 각 토큰의 표현을 갱신하는 Transformer 연산입니다. cross-encoder 학습에서는 sequence length가 길어질수록 attention 메모리 사용량이 대략 제곱으로 증가하므로, max_length 제한이 없으면 긴 배치 하나가 메모리 부족과 극심한 thrashing을 일으킬 수 있습니다.
- 최대 시퀀스 길이(max_length)
- — max_length는 모델이 한 입력에서 처리하도록 허용하는 최대 토큰 수입니다. 이 글에서는 값을 128 tokens로 제한하고 training batch size를 낮춰 동일한 tenant 데이터의 peak memory를 약 5.6 GB에서 약 1.27 GB로 줄였으며, 처리 시간도 905초에서 224초로 단축했습니다.
- 분류 성능 곡선 아래 면적(AUC)
- — AUC는 분류기가 가능한 threshold 전 범위에서 양성과 음성을 얼마나 일관되게 구분하는지 나타내는 지표입니다. 새 모델과 이전 모델의 AUC가 0.890에서 0.8905로 거의 변하지 않았는데도 특정 production threshold에서 precision이 10 percentage points 낮아져, 단일 threshold 비교만으로는 실제 품질 변화를 판단하기 어려웠습니다.
- Youden's-J 임계값 보정(Youden's-J)
- — Youden's-J는 held-out 데이터에서 sensitivity와 specificity의 균형을 기준으로 분류 threshold를 고르는 calibration 방식입니다. 이 사례에서는 작은 held-out slice에 적용한 결과가 기존 threshold보다 더 공격적인 operating point를 선택했고, 모델의 discriminative power가 아니라 threshold 위치 차이가 precision 하락처럼 보이는 현상을 만들었습니다.
언급된 도구
Redis Queue 기반 worker에서 fine-tuning job을 실행하고 job_timeout을 처리합니다.
작업을 별도 자식 프로세스가 아니라 같은 프로세스에서 실행해 SIGALRM 기반 timeout의 선점 한계를 만들었습니다.
큰 batch의 self-attention forward pass와 tensor 연산을 수행하며 C-level 연산 중 Python timeout 처리가 지연되는 상황을 만들었습니다.
언급된 리소스
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.