Accelerate documentation
문제 해결
문제 해결
이 가이드는 Accelerate를 사용할 때 발생할 수 있는 일부 문제에 대한 해결책을 제공합니다. Accelerate는 지속적으로 발전하는 활성 라이브러리이며 다양한 사용 사례와 분산 학습 설정이 존재하기 때문에 모든 오류를 다루지는 않습니다. 여기 설명된 해결책이 특정 오류에 도움이 되지 않는 경우, 도움을 받을 수 있는 곳과 방법에 대해 알아보려면 도움 요청 섹션을 참고하세요.
로깅
로깅은 오류의 원인을 파악하는 데 도움이 됩니다. 여러 프로세스가 포함된 분산 환경에서는 로깅이 어려울 수 있지만, Accelerate는 logging() 유틸리티를 제공하여 로그가 동기화되도록 보장합니다.
문제를 해결하려면 표준 Python logging 모듈 대신 logging()을 사용하세요. log_level 매개변수로 상세 수준(INFO, DEBUG, WARNING, ERROR, CRITICAL)을 설정한 다음, 다음 중 하나를 수행할 수 있습니다:
log_level을ACCELERATE_LOG_LEVEL환경 변수로 내보냅니다.log_level을get_logger에 직접 전달합니다.
예를 들어, log_level="INFO"를 설정하려면:
from accelerate.logging import get_logger
logger = get_logger(__name__, log_level="DEBUG")기본적으로 로그는 메인 프로세스에서만 호출됩니다. 모든 프로세스에서 호출하려면 main_process_only=False를 전달하세요.
모든 프로세스에서 순서대로 로그를 호출하려면 in_order=True도 전달하세요.
from accelerate.logging import get_logger
logger = get_logger(__name__, log_level="DEBUG")
# log all processes
logger.debug("thing_to_log", main_process_only=False)
# log all processes in order
logger.debug("thing_to_log", main_process_only=False, in_order=True)hanging 코드 및 타임아웃 오류
코드가 멈추는 이유는 다양할 수 있습니다. 코드가 멈추게 만드는 가장 흔한 문제 중 일부와 해결 방법을 살펴보겠습니다.
텐서 모양 불일치
tensor의 shape가 일치하지 않는 것은 분산 환경에서 코드가 상당한 시간 동안 멈추게 할 수 있는 일반적인 문제입니다.
분산 환경에서 스크립트를 실행할 때, Accelerator.gather()와 Accelerator.reduce()와 같은 함수를 사용하여 여러 디바이스에 걸쳐 텐서를 수집하고 이를 공동으로 조작해야 합니다. 이 함수들(및 기타 함수)은 torch.distributed에 의존하여 gather 연산을 수행하며, 이 연산은 모든 프로세스에서 텐서가 완전히 동일한 shape를 가져야 합니다. 텐서의 shape가 일치하지 않으면 코드가 멈추고 결국 타임아웃 예외가 발생합니다.
Accelerate의 운영 디버그 모드를 사용하면 이 문제를 즉시 감지할 수 있습니다. accelerate config 설정 시 이 모드를 활성화하는 것을 권장하지만, CLI, 환경 변수, 또는 config.yaml 파일을 수동으로 편집하여 활성화할 수도 있습니다.
accelerate launch --debug {my_script.py} --arg1 --arg2환경 변수로 디버그 모드를 활성화하는 경우 accelerate launch를 호출할 필요가 없습니다.
ACCELERATE_DEBUG_MODE="1" torchrun {my_script.py} --arg1 --arg2config.yaml 파일에 debug: true를 추가하세요.
compute_environment: LOCAL_MACHINE
debug: truedebug 모드를 활성화하면, 텐서 형식 불일치 문제를 가리키는 traceback를 확인하실 수 있습니다.
Traceback (most recent call last):
File "/home/zach_mueller_huggingface_co/test.py", line 18, in <module>
main()
File "/home/zach_mueller_huggingface_co/test.py", line 15, in main
broadcast_tensor = broadcast(tensor)
File "/home/zach_mueller_huggingface_co/accelerate/src/accelerate/utils/operations.py", line 303, in wrapper
accelerate.utils.operations.DistributedOperationException:
Cannot apply desired operation due to shape mismatches. All shapes across devices must be valid.
Operation: `accelerate.utils.operations.broadcast`
Input shapes:
- Process 0: [1, 5]
- Process 1: [1, 2, 5]조기 종료
분산 학습에서 조기 정지를 사용할 때, 각 프로세스마다 특정 정지 조건(예: 검증 손실)이 있는 경우 모든 프로세스 간에 동기화되지 않을 수 있습니다. 그 결과, 프로세스 0에서는 break가 발생하지만 프로세스 1에서는 발생하지 않아, 타임아웃이 발생하기까지 코드가 무한정 멈추게 됩니다.
조기 종료 조건이 있는 경우, set_trigger 및 check_trigger 메서드를 사용하여 모든 프로세스가 올바르게 종료되도록 확인하세요.
# Assume `should_do_breakpoint` is a custom-defined function that returns a conditional,
# and that conditional might be true only on process 1
if should_do_breakpoint(loss):
accelerator.set_trigger()
# Later in the training script when we need to check for the breakpoint
if accelerator.check_trigger():
breakLinux의 낮은 커널 버전
Linux에서 커널 버전이 < 5.5인 경우, 프로세스가 멈추는 현상이 보고되었습니다. 이 문제를 피하려면 시스템을 더 최신 커널 버전으로 업그레이드하세요.
MPI
MPI를 사용하는 분산 CPU 학습 작업이 멈추는 경우, 노드 간에 비밀번호 없는 SSH(키 사용)가 설정되어 있는지 확인하세요. 이는 hostfile의 모든 노드에 대해, 비밀번호를 입력하라는 프롬프트 없이 한 노드에서 다른 노드로 SSH 접속이 가능해야 함을 의미합니다.
다음으로, mpirun 명령을 실행하여 sanity check를 수행해 보세요. 예를 들어, 아래 명령은 각 노드의 hostname을 출력해야 합니다.
mpirun -f hostfile -n {number of nodes} -ppn 1 hostname메모리 부족
One of the most frustrating errors when it comes to running training scripts is hitting “Out-of-Memory” on devices like CUDA, XPU or CPU. The entire script needs to be restarted and any progress is lost.
이 문제를 해결하기 위해 Accelerate는 toma를 기반으로 한 find_executable_batch_size() 유틸리티를 제공합니다. 이 유틸리티는 OOM(메모리 부족) 조건으로 인해 실패하는 코드를 재시도하고 배치 크기를 자동으로 낮춥니다. 각 OOM 조건에서 알고리즘은 배치 크기를 절반으로 줄인 후 성공할 때까지 코드를 재시도합니다.
find_executable_batch_size()를 사용하려면, 학습 함수를 find_executable_batch_size를 포함하는 내부 함수를 가진 구조로 재구성하고, 데이터 로더를 그 내부 함수에서 생성하도록 해야 합니다. 최소한 4줄의 새로운 코드만 추가하면 됩니다.
내부 함수는 반드시 배치 크기를 첫 번째 인자로 받아야 하지만, 호출 시에는 이를 전달하지 않습니다. 래퍼가 이를 처리해 줍니다. Accelerator에 전달되는 디바이스 메모리를 사용하는 모든 객체(모델, 옵티마이저)도 반드시 내부 함수 안에서 선언되어야 합니다.
def training_function(args):
accelerator = Accelerator()
+ @find_executable_batch_size(starting_batch_size=args.batch_size)
+ def inner_training_loop(batch_size):
+ nonlocal accelerator # Ensure they can be used in our context
+ accelerator.free_memory() # Free all lingering references
model = get_model()
model.to(accelerator.device)
optimizer = get_optimizer()
train_dataloader, eval_dataloader = get_dataloaders(accelerator, batch_size)
lr_scheduler = get_scheduler(
optimizer,
num_training_steps=len(train_dataloader)*num_epochs
)
model, optimizer, train_dataloader, eval_dataloader, lr_scheduler = accelerator.prepare(
model, optimizer, train_dataloader, eval_dataloader, lr_scheduler
)
train(model, optimizer, train_dataloader, lr_scheduler)
validate(model, eval_dataloader)
+ inner_training_loop()장치 구성 간 재현 불가능한 결과
디바이스 설정을 변경한 후 모델 성능이 달라지는 것을 관찰했다면, 설정을 변경할 때 스크립트를 업데이트하지 않은 것이 원인일 가능성이 높습니다. 동일한 스크립트와 동일한 배치 크기를 사용하더라도 TPU, 멀티 GPU, 단일 GPU 환경에서는 결과가 여전히 달라집니다.
예를 들어, 단일 GPU에서 배치 크기 16으로 학습하다가 듀얼 GPU 구성으로 전환하는 경우, 동일한 유효 배치 크기를 유지하려면 배치 크기를 8로 변경해야 합니다. 이는 Accelerate로 학습할 때 dataloader에 전달되는 배치 크기가 GPU당 배치 크기이기 때문입니다.
설정 간에 결과를 재현할 수 있도록 하려면 동일한 시드(seed)를 사용하고, 배치 크기를 그에 맞게 조정하며, 학습률을 스케일링하는 것을 고려하세요.
배치 크기에 대한 자세한 내용과 빠른 참고를 위해 서로 다른 장치 구성 간 성능 비교 가이드를 확인하세요.
다른 GPU에서 발생하는 성능 문제
멀티 GPU 구성이 서로 다른 GPU로 이루어져 있는 경우, 일부 성능 문제를 겪을 수 있습니다:
- GPU 간에 GPU 메모리 불균형이 있을 수 있습니다. 이 경우, 메모리가 작은 GPU가 GPU에 로드할 수 있는 배치 크기 또는 모델 크기를 제한합니다.
- 성능 프로파일이 서로 다른 GPU를 사용하는 경우, 다른 GPU들이 해당 GPU의 워크로드 완료를 기다려야 하므로 가장 느린 GPU가 전체 성능을 결정합니다.
동일한 설정 내에서 성능이 크게 다른 GPU를 사용하면 성능 병목 현상이 발생할 수 있습니다.
도움 요청
여기 제시된 해결책과 조언이 문제를 해결하는 데 도움이 되지 않았다면, 언제든지 커뮤니티와 Accelerate 팀에 도움을 요청할 수 있습니다.
Accelerate 카테고리에 질문을 게시하여 Hugging Face 포럼에서 도움을 요청하세요. 문제 해결 가능성을 높이기 위해, 환경 설정에 대한 관련 컨텍스트와 재현 가능한 코드를 포함하여 설명적인 게시글을 작성하는 것이 중요합니다!
Discord에 질문을 게시하고 팀과 커뮤니티의 도움을 받으세요.
라이브러리와 관련된 버그를 발견했다고 생각되면 Accelerate의 GitHub 저장소에 이슈를 생성하세요. 버그에 대한 맥락과 분산 환경 설정에 대한 세부 정보를 포함하여, 무엇이 잘못되었는지 파악하고 어떻게 수정할 수 있는지 확인하는 데 도움이 되도록 해 주세요.