종료 상태와 시그널
- 종료 코드 0: W&B는 run이 성공적으로 완료된 것으로 간주하며 다시 큐에 넣지 않습니다.
- 0이 아닌 종료 코드: run은 실패했거나 선점된 것으로 처리됩니다.
mark_preempting()을 사용하면 W&B가 run을 다시 큐에 넣으므로, 다른 에이전트(또는 재시작 후 동일한 에이전트)가 이를 재개할 수 있습니다.
sys.exit() 호출로 종료되는 경우 모두에 적용됩니다. 이 규약을 이해하고 이를 전제로 동작하도록 구현하는 것은 선점형 또는 클러스터 환경에서 중요합니다.
프로세스가 포착 가능한 시그널로 인해 종료될 때는 핸들러가 실행되어, run을 다시 큐에 넣으려는 경우 wandb.run.mark_preempting()을 호출하고, 정리 작업(예: checkpoint 저장)을 수행한 뒤 0이 아닌 코드로 종료할 수 있습니다. 시그널에 의해 종료될 때의 일반적인 관례는 sys.exit(128 + signum)입니다. W&B는 해당 종료 코드를 기록하며, 동일한 다시 큐에 넣는 규칙이 적용됩니다. 운영 체제 커널이 SIGKILL로 프로세스를 종료하면 프로세스는 종료 훅을 실행할 수 없으므로 W&B는 최종 summary를 기록하지 않으며, run이 crashed 또는 killed로 표시될 수 있습니다. 그래도 에이전트는 다음 run을 시작합니다.
정체된 run과 서버 측 시간 초과
SIGKILL 전송처럼) 정상적인 종료 처리 없이 종료될 때 발생할 수 있습니다. 일정한 간격으로 메트릭을 기록하거나 명시된 코드로 종료해 run 상태가 실제 발생한 상황과 일치하도록 하세요.
포착 가능한 시그널과 선점
- 핸들러는 가능한 한 일찍 등록하세요(예: 기본 트레이닝 루프에 들어가기 전).
- 핸들러에서는 선점 후 run이 다시 큐에 들어가도록 하려면
wandb.run.mark_preempting()을 호출하고, 정리 작업(예: checkpoint 저장)을 수행한 다음, 0이 아닌 종료 코드로 종료하세요.
SIGUSR1(일반적인 클러스터 선점 시그널)과 SIGTERM에 대한 핸들러를 등록합니다. SIGINT는 대화형 사용(예: 터미널에서 수동 취소)을 위해 그대로 둡니다. 핸들러는 wandb.run.mark_preempting()을 호출한 뒤 128 + signum으로 종료합니다:
SIGKILL (포착 불가)
SIGKILL은 운영 체제 커널에서 발생하며 포착하거나 무시할 수 없습니다. 프로세스는 핸들러나 atexit 콜백을 실행할 기회도 없이 즉시 종료됩니다. W&B는 해당 run의 최종 summary를 기록할 수 없습니다. 에이전트는 복구 후에도 스윕을 계속 진행하지만, 해당 run의 데이터는 불완전합니다. SIGKILL은 최후의 수단으로만 사용하세요. 정상 종료가 필요할 때는 SIGTERM 또는 SIGINT를 우선 사용하세요.
에이전트에서 자식 프로세스로 시그널 전달
wandb agent CLI를 사용하면 에이전트가 트레이닝 스크립트를 자식 프로세스로 실행합니다. 에이전트를 중단하면(예: Ctrl+C를 누르거나 스케줄러가 작업에 SIGTERM을 보내는 경우) 기본적으로 자식 프로세스(트레이닝 프로세스)는 시그널을 받지 못합니다. 따라서 트레이닝 스크립트는 핸들러를 실행하거나 mark_preempting()을 호출할 수 없습니다. 자세한 내용은 wandb GitHub issue #3667을 참조하세요.
자식 프로세스가 정상적으로 종료되고 핸들러에서 wandb.run.mark_preempting()을 호출할 수 있도록 하려면 --forward-signals 옵션과 함께 CLI 에이전트를 실행하세요:
wandb.agent()에 대해 시그널 포워딩을 지원하지 않습니다. 이 경로에서는 트레이닝 함수가 별도의 자식 프로세스가 아니라 스레드에서 실행되므로, 동일한 포워딩 동작이 적용되지 않습니다.
CLI 에이전트가 포워딩이 활성화된 상태에서 SIGINT 또는 SIGTERM을 받으면, 해당 시그널을 자식 프로세스로 전달합니다. 그러면 트레이닝 스크립트의 핸들러가 실행되어, 필요하면 wandb.run.mark_preempting()과 wandb.finish()를 0이 아닌 종료 코드와 함께 호출한 뒤 0이 아닌 코드로 종료할 수 있습니다. 에이전트 프로세스에서 Ctrl+C를 두 번 누르면 기본적으로 에이전트는 SIGTERM을 받습니다. --forward-signals를 사용하면 에이전트가 SIGINT를 자식 프로세스로 전달하여 핸들러가 실행되도록 할 수 있습니다.
자세한 내용은 wandb agent CLI 레퍼런스를 참조하세요.
SLURM과 같은 선점형 클러스터
- 스케줄러가 에이전트에 시그널을 보내는 경우:
wandb agent --forward-signals로 에이전트를 실행하세요. 그러면 스케줄러(또는 사용자)가 에이전트에 시그널을 보낼 때 에이전트가 이를 자식 프로세스에 전달합니다. 이후 자식 프로세스의 핸들러는wandb.run.mark_preempting(), 0이 아닌 코드로wandb.finish(exit_code=...), 그리고sys.exit(128 + signum)(또는 다른 0이 아닌 종료 코드)를 호출할 수 있습니다. - 스케줄러가 시작 스크립트에 시그널을 보내는 경우(에이전트에 직접 보내지 않는 경우): 시작 스크립트가 선점 시그널을 트레이닝 프로세스에 직접 보내도록 하세요. 예를 들어 트레이닝 스크립트가 자신의 프로세스 ID를 파일에 기록할 수 있습니다. 시작 스크립트는 클러스터 시그널(예:
SIGUSR1)을 trap한 뒤kill -SIGUSR1 $(cat $PID_FILE)를 실행해 트레이닝 프로세스의 핸들러가 실행되도록 합니다.
SIGTERM 또는 SIGUSR1)에 대한 핸들러를 등록하세요. 핸들러에서는 활성 run이 있으면 wandb.run.mark_preempting()를 호출한 다음, W&B가 run을 다시 큐에 넣을 수 있도록 0이 아닌 종료 코드와 sys.exit(128 + signum)(또는 다른 0이 아닌 코드)로 run을 종료하세요. W&B가 언제 run을 다시 큐에 넣는지와 이것이 mark_preempting()과 어떻게 상호작용하는지에 대한 자세한 내용은 선점형 Sweeps run 재개를 참조하세요.
스윕 상태: 에이전트를 시작하기 전에 wandb sweep entity/project/sweep_ID --resume를 실행해 스윕이 재개 모드가 되도록 하고, 다시 큐에 들어간 run을 할당하도록 하세요.
멀티 에이전트 조정: 많은 에이전트가 동시에 실행되면(SLURM array 작업 등) 동일한 선점된 run을 차지하려고 경쟁할 수 있습니다. 이는 알려진 제한 사항입니다. 이를 우회하려면 에이전트 시작 시점을 엇갈리게 하거나 락과 같은 외부 조정 메커니즘을 사용하세요.
멀티 GPU SLURM 작업에서 하나의 프로세스만 wandb.agent()를 호출해야 하는 경우, SLURM에서 sweeps를 어떻게 실행해야 하나요?를 참조하세요.
wandb sweep --cancel
--cancel command가 시그널 및 하위 프로세스와 어떻게 상호작용하는지 설명합니다. OS 시그널이 아니라 W&B API를 사용해 스윕을 취소합니다. wandb sweep --cancel entity/project/sweep_ID와 같은 command를 실행하세요. 서버가 에이전트에 종료하라고 지시하면, 에이전트는 실행 중인 하위 프로세스를 종료한 뒤 중지합니다. 취소가 실제로 적용되기까지는 짧은 지연이 있을 수 있습니다(대략 에이전트의 API 폴링 간격 기준).
취소하면 run에 **SIGKILL**이 전달됩니다. 하위 프로세스는 사용자 정의 시그널 핸들러를 실행할 기회가 없습니다. Sweeps UI에서 Cancel 컨트롤을 사용할 때도 동일합니다. 전체 스윕을 중지하고 취소된 것으로 표시하려면 --cancel을 사용하세요. 현재 run을 정상적으로 종료하려면 run에 포착 가능한 시그널을 보내세요(또는 CLI 에이전트와 함께 --forward-signals를 사용한 후 에이전트에 시그널을 보내세요). 스윕을 정상적으로 완료하려면 --cancel 대신 wandb sweep --stop을 사용하세요.
일시 중지, 재개, 중지, 취소 옵션에 대한 자세한 내용은 Manage sweeps를 참조하세요.
에이전트에 보내는 시그널과 run에 보내는 시그널
--forward-signals를 사용하지 않는 한, 에이전트를 중지해도 자식 트레이닝 프로세스까지 중지된다고 보장할 수는 없습니다.
에이전트가 종료되었는지 확인하려면 프롬프트가 나타나는지만 보지 말고 ps -p [AGENT-PID] 또는 pgrep -f "wandb agent" 같은 OS 명령어를 사용하세요.
레퍼런스: mark_preempting() 및 최종 run 상태
mark_preempting()을 언제 호출하는지와 프로세스가 어떻게 종료되는지에 따라 run 상태가 어떻게 달라지는지 요약한 것입니다. 여기서는 트레이닝 프로그램을 서브프로세스로 사용하는 wandb agent CLI를 사용한다고 가정합니다.
시그널 핸들러 안에서만
mark_preempting()을 호출하면, SIGKILL처럼 핸들러가 전혀 실행되지 않는 경우는 처리할 수 없습니다.
wandb.init() 직후 항상 mark_preempting()을 호출하면 W&B가 모든 실패를 선점으로 처리할 수 있으므로, bug나 잘못된 설정 때문인 경우까지 포함해 run이 반복적으로 다시 큐에 들어갈 수 있습니다.
선점 시그널이 명확하게 정의된 환경에서는 일반적으로 init() 후 무조건 호출하기보다, mark_preempting()을 호출한 뒤 0이 아닌 값으로 종료하는 시그널 핸들러 방식을 사용합니다.