메인 콘텐츠로 건너뛰기
분산 학습 실험에서는 여러 머신이나 클라이언트를 병렬로 사용해 모델을 학습합니다. W&B를 사용하면 이러한 분산 학습 실험을 추적할 수 있습니다. 사용 사례에 따라 다음 접근 방식 중 하나를 사용해 분산 학습 실험을 추적하세요:
  • 단일 프로세스 추적: W&B로 rank 0 프로세스(“리더” 또는 “코디네이터”라고도 함)를 추적합니다. 이는 PyTorch Distributed Data Parallel (DDP) 클래스에서 분산 학습 실험을 로깅할 때 일반적으로 사용하는 방법입니다.
  • 여러 프로세스 추적: 여러 프로세스가 있는 경우, 다음 중 하나를 선택할 수 있습니다:
    • 프로세스당 하나의 실행을 사용해 각 프로세스를 개별적으로 추적합니다. 필요에 따라 W&B App UI에서 이들을 하나의 그룹으로 묶을 수 있습니다.
    • 모든 프로세스를 하나의 실행으로 추적합니다.
동시 연결각 동시 연결은 연산, 메모리, 네트워크 리소스를 사용합니다. 지표를 정기적으로 로깅하지 않는 클라이언트 연결이라도 시스템 메트릭 업데이트를 계속 전송하므로, 차트를 불러올 때 성능이 저하될 수 있습니다.W&B는 워크로드에 맞게 동시 클라이언트 연결의 최대 개수를 제한하고, 시간이 지남에 따라 리소스 사용량을 모니터링할 것을 권장합니다. W&B는 Dedicated Cloud 환경에서 동시 클라이언트 연결 300개라는 하드 제한으로 테스트를 완료했습니다.Multi-tenant Cloud 조직에서는 분산 학습을 위한 클라이언트 연결도 일반 학습 실행과 동일한 요율 제한을 적용받습니다. Teams 및 Enterprise 플랜을 사용하는 사용자는 Free 플랜 사용자보다 더 높은 요율 제한이 적용됩니다.

단일 프로세스 추적

이 섹션에서는 rank 0 프로세스에서 확인할 수 있는 값과 메트릭을 추적하는 방법을 설명합니다. 이 접근 방식은 단일 프로세스에서만 확인 가능한 메트릭을 추적할 때 사용하십시오. 일반적인 메트릭에는 GPU/CPU 사용률, 공유 검증 세트에서의 동작, 그래디언트와 파라미터, 대표 데이터 예제에 대한 손실 값 등이 포함됩니다. rank 0 프로세스 내에서 wandb.init()을(를) 사용해 W&B 실행을 초기화한 다음, 해당 실행에 실험을 기록하기 위해 wandb.log를 사용합니다. 다음의 샘플 Python 스크립트(log-ddp.py)는 단일 머신에서 두 개의 GPU에 대한 메트릭을 PyTorch DDP를 사용해 추적하는 한 가지 방법을 보여줍니다. PyTorch DDP (torch.nnDistributedDataParallel)는 분산 학습을 위한 널리 사용되는 라이브러리입니다. 기본 원리는 어떤 분산 학습 환경에도 동일하게 적용되지만, 구현 방식은 달라질 수 있습니다. 이 Python 스크립트는 다음 작업을 수행합니다:
  1. torch.distributed.launch로 여러 프로세스를 시작합니다.
  2. --local_rank 커맨드라인 인자를 사용해 rank 값을 확인합니다.
  3. rank가 0으로 설정되어 있는 경우, train() 함수에서 조건부로 wandb 로깅을 설정합니다.
if __name__ == "__main__":
    # 인수 가져오기
    args = parse_args()

    if args.local_rank == 0:  # 메인 프로세스에서만
        # wandb 실행 초기화
        run = wandb.init(
            entity=args.entity,
            project=args.project,
        )
        # DDP로 모델 학습
        train(args, run)
    else:
        train(args)
단일 프로세스에서 추적한 메트릭을 보여주는 예시 대시보드를 살펴보세요. 이 대시보드는 온도와 사용률과 같이 두 개의 GPU에 대한 시스템 메트릭을 표시합니다.
GPU 메트릭 대시보드
하지만 에포크와 배치 크기에 따른 손실 값은 단일 GPU에서만 로깅되었습니다.
손실 함수 플롯

여러 프로세스 추적하기

여러 프로세스를 W&B로 추적하려면 다음 방법 중 하나를 사용할 수 있습니다:

각 프로세스를 개별적으로 추적하기

이 섹션에서는 각 프로세스마다 개별 실행을 생성하여 프로세스를 분리해 추적하는 방법을 설명합니다. 각 실행 내에서 해당 실행에 대한 메트릭, 아티팩트 등을 기록합니다. 학습이 끝날 때 wandb.Run.finish()를 호출해 실행이 완료되었음을 표시하면, 모든 프로세스가 올바르게 종료됩니다. 여러 실험에 걸쳐 실행을 관리하기가 어려울 수 있습니다. 이를 개선하기 위해, W&B를 초기화할 때(wandb.init(group='group-name')) group 파라미터에 값을 지정해, 어떤 실행이 특정 실험에 속하는지 구분하도록 합니다. 실험에서 학습 및 평가 W&B 실행을 추적하는 방법에 대한 자세한 내용은 Group Runs를 참고하세요.
개별 프로세스의 메트릭을 추적하려는 경우 이 접근 방식을 사용하세요. 일반적인 예로는 각 노드의 데이터와 예측(데이터 분산 디버깅용), 그리고 메인 노드 외부의 개별 배치에 대한 메트릭이 있습니다. 이 접근 방식은 모든 노드에서 시스템 메트릭을 수집하거나, 메인 노드에서 제공되는 요약 통계를 얻기 위해서는 필요하지 않습니다.
다음 Python 코드 스니펫은 W&B를 초기화할 때 group 파라미터를 설정하는 방법을 보여줍니다:
if __name__ == "__main__":
    # 인수 가져오기
    args = parse_args()
    # 실행 초기화
    run = wandb.init(
        entity=args.entity,
        project=args.project,
        group="DDP",  # 실험의 모든 실행을 하나의 그룹으로
    )
    # DDP로 모델 학습
    train(args, run)

    run.finish()  # 실행을 완료 상태로 표시
여러 프로세스에서 추적된 메트릭을 확인하려면 W&B App UI에서 예시 대시보드를 탐색하세요. 왼쪽 사이드바에서 두 개의 W&B 실행이 함께 그룹화되어 있는 것을 확인할 수 있습니다. 그룹을 클릭하면 해당 실험을 위한 전용 그룹 페이지로 이동합니다. 전용 그룹 페이지에서는 각 프로세스의 메트릭이 개별적으로 표시됩니다.
그룹화된 분산 실행
위 이미지는 W&B App UI 대시보드를 보여줍니다. 사이드바에는 두 개의 실험이 있습니다. 하나는 ‘null’로 표시되고, 다른 하나는 (노란색 상자로 강조된) ‘DPP’입니다. 그룹을 확장하려면(그룹 드롭다운을 선택하면) 해당 실험과 연결된 W&B 실행들을 볼 수 있습니다.

분산 실행 구성하기

노드의 역할에 따라 범주를 나누려면 W&B를 초기화할 때 job_type 파라미터를 설정하세요 (wandb.init(job_type='type-name')). 예를 들어, 메인 조정 노드 하나와 여러 개의 보고용 워커 노드가 있을 수 있습니다. 메인 조정 노드에는 job_typemain으로, 보고용 워커 노드에는 worker로 설정할 수 있습니다:
   # 메인 조정 노드
   with wandb.init(project="<project>", job_type="main", group="experiment_1") as run:
        # 학습 코드

   # 보고 워커 노드
   with wandb.init(project="<project>", job_type="worker", group="experiment_1") as run:
        # 학습 코드
노드에 job_type을 설정한 후에는 워크스페이스에서 저장된 보기(saved view)를 만들어 실행을 정리할 수 있습니다. 오른쪽 상단의 액션 메뉴를 클릭한 다음 Save as new view를 클릭합니다. 예를 들어, 다음과 같은 saved view를 생성할 수 있습니다:
  • Default view: worker 노드를 필터링해 잡음을 줄입니다.
    • Filter를 클릭한 다음 Job Typeworker로 설정합니다.
    • 보고용 노드만 표시합니다.
    • Debug view: 문제 해결을 위해 worker 노드에 집중합니다.
      • Filter를 클릭한 다음 Job Type== worker로 설정하고 StateIN crashed로 설정합니다.
      • 크래시되었거나 오류 상태에 있는 worker 노드만 표시합니다.
    • All nodes view: 모든 노드를 한 번에 확인합니다.
      • 필터 없음
      • 전체 모니터링에 유용합니다.
saved view를 열려면 사이드바에서 Workspaces를 클릭한 다음 해당 메뉴를 클릭합니다. 워크스페이스는 목록 상단에, saved view는 하단에 표시됩니다.

여러 프로세스를 하나의 실행으로 추적하기

x_label과 같은 x_로 시작하는 파라미터는 퍼블릭 프리뷰 상태입니다. 피드백을 제공하려면 W&B 저장소에 GitHub 이슈를 생성하세요.
요구 사항여러 프로세스를 하나의 실행으로 추적하려면 다음이 필요합니다:
  • W&B Python SDK 버전 v0.19.9 이상
  • W&B Server v0.68 이상
이 방식에서는 기본(primary) 노드와 하나 이상의 워커(worker) 노드를 사용합니다. 기본 노드에서 W&B 실행을 초기화합니다. 각 워커 노드에서는 기본 노드에서 사용한 실행 ID(run ID)를 사용해 실행을 초기화합니다. 학습 중에는 각 워커 노드가 기본 노드와 동일한 실행 ID로 로그를 기록합니다. W&B는 모든 노드에서 수집된 메트릭을 집계해 W&B App UI에 표시합니다. 기본 노드에서 wandb.init()으로 W&B 실행을 초기화합니다. settings 파라미터에 wandb.Settings 객체를 전달합니다(wandb.init(settings=wandb.Settings()) )와 함께 다음을 설정합니다:
  1. 공유 모드를 활성화하기 위해 mode 파라미터를 "shared"로 설정합니다.
  2. x_label에 고유한 레이블을 지정합니다. x_label에 지정한 값은 W&B App UI의 로그 및 시스템 메트릭에서 데이터가 어떤 노드에서 왔는지 식별하는 데 사용됩니다. 지정하지 않으면 W&B가 호스트 이름과 임의 해시를 사용해 레이블을 생성합니다.
  3. 이 노드가 기본 노드임을 나타내기 위해 x_primary 파라미터를 True로 설정합니다.
  4. 선택적으로 x_stats_gpu_device_ids에 GPU 인덱스 목록([0,1,2])을 제공하여 W&B가 어떤 GPU에 대해 메트릭을 추적할지 지정할 수 있습니다. 목록을 제공하지 않으면 W&B는 머신의 모든 GPU에 대해 메트릭을 추적합니다.
기본 노드의 실행 ID를 기록해 두세요. 각 워커 노드는 기본 노드의 실행 ID가 필요합니다.
x_primary=True는 기본 노드와 워커 노드를 구분합니다. 기본 노드는 설정 파일, 텔레메트리 등 노드 간에 공유되는 파일을 업로드하는 유일한 노드입니다. 워커 노드는 이러한 파일을 업로드하지 않습니다.
각 워커 노드에 대해 wandb.init()으로 W&B 실행을 초기화하고 다음을 제공합니다:
  1. settings 파라미터에 wandb.Settings 객체를 전달합니다(wandb.init(settings=wandb.Settings()) )와 함께:
    • 공유 모드를 활성화하기 위해 mode 파라미터를 "shared"로 설정합니다.
    • x_label에 고유한 레이블을 지정합니다. x_label에 지정한 값은 W&B App UI의 로그 및 시스템 메트릭에서 데이터가 어떤 노드에서 왔는지 식별하는 데 사용됩니다. 지정하지 않으면 W&B가 호스트 이름과 임의 해시를 사용해 레이블을 생성합니다.
    • 이 노드가 워커 노드임을 나타내기 위해 x_primary 파라미터를 False로 설정합니다.
  2. id 파라미터에 기본 노드에서 사용한 실행 ID를 전달합니다.
  3. 선택적으로 x_update_finish_stateFalse로 설정합니다. 이는 기본 노드가 아닌 노드가 실행 상태finished로 먼저 업데이트하는 것을 방지하여, 실행 상태가 일관되게 유지되고 기본 노드에서 관리되도록 보장합니다.
  • 모든 노드에서 동일한 엔터티와 프로젝트를 사용하세요. 이렇게 하면 올바른 실행 ID를 찾는 데 도움이 됩니다.
  • 각 워커 노드에서 환경 변수를 정의해 기본 노드의 실행 ID를 설정하는 방법을 고려하세요.
다음 예제 코드는 여러 프로세스를 하나의 실행으로 추적하기 위한 주요 요구 사항을 보여줍니다:
import wandb

entity = "<team_entity>"
project = "<project_name>"

# 기본 노드에서 실행을 초기화합니다
run = wandb.init(
    entity=entity,
    project=project,
	settings=wandb.Settings(
        x_label="rank_0", 
        mode="shared", 
        x_primary=True,
        x_stats_gpu_device_ids=[0, 1],  # (선택 사항) GPU 0과 1의 메트릭만 추적합니다
        )
)

# 기본 노드의 실행 ID를 기록해 두세요.
# 각 워커 노드에는 이 실행 ID가 필요합니다.
run_id = run.id

# 기본 노드의 실행 ID를 사용하여 워커 노드에서 실행을 초기화합니다
run = wandb.init(
    entity=entity, # 기본 노드와 동일한 엔터티를 사용합니다
    project=project, # 기본 노드와 동일한 프로젝트를 사용합니다
	settings=wandb.Settings(x_label="rank_1", mode="shared", x_primary=False),
	id=run_id,
)

# 기본 노드의 실행 ID를 사용하여 워커 노드에서 실행을 초기화합니다
run = wandb.init(
    entity=entity, # 기본 노드와 동일한 엔터티를 사용합니다
    project=project, # 기본 노드와 동일한 프로젝트를 사용합니다
	settings=wandb.Settings(x_label="rank_2", mode="shared", x_primary=False),
	id=run_id,
)
실제 환경에서는 각 워커 노드가 서로 다른 머신에 있을 수 있습니다.
GKE에서 멀티 노드 및 멀티 GPU Kubernetes 클러스터에서 모델을 학습하는 방법에 대한 엔드 투 엔드 예시는 Distributed Training with Shared Mode 리포트를 참조하세요.
실행이 로그를 기록하는 프로젝트에서 멀티 노드 프로세스의 콘솔 로그를 보려면 다음을 수행하세요:
  1. 해당 실행이 포함된 프로젝트로 이동합니다.
  2. 왼쪽 사이드바에서 Runs 탭을 클릭합니다.
  3. 확인하려는 실행을 클릭합니다.
  4. 왼쪽 사이드바에서 Logs 탭을 클릭합니다.
콘솔 로그 페이지 상단에 있는 UI 검색창에서 x_label에 제공한 레이블을 기준으로 콘솔 로그를 필터링할 수 있습니다. 예를 들어, 아래 이미지는 x_labelrank0, rank1, rank2, rank3, rank4, rank5, rank6 값을 제공했을 때 콘솔 로그를 필터링할 수 있는 옵션을 보여 줍니다.
멀티 노드 콘솔 로그
자세한 내용은 Console logs를 참조하세요. W&B는 모든 노드에서 시스템 메트릭을 집계하여 W&B App UI에 표시합니다. 예를 들어, 아래 이미지는 여러 노드의 시스템 메트릭이 포함된 샘플 대시보드를 보여 줍니다. 각 노드는 x_label 매개변수에 지정하는 고유한 레이블(rank_0, rank_1, rank_2)을 가집니다.
멀티 노드 시스템 메트릭
라인 플롯 패널을 사용자 정의하는 방법에 대한 정보는 Line plots를 참조하세요.

예제 사용 사례

다음 코드 스니펫은 고급 분산 사용 사례에서 흔히 등장하는 시나리오를 보여줍니다.

스폰된 프로세스

스폰된 프로세스에서 실행을 시작하는 경우에는 메인 함수에서 wandb.setup() 메서드를 사용하세요:
import multiprocessing as mp

def do_work(n):
    with wandb.init(config=dict(n=n)) as run:
        run.log(dict(this=n * n))

def main():
    wandb.setup()
    pool = mp.Pool(processes=4)
    pool.map(do_work, range(4))


if __name__ == "__main__":
    main()

실행 공유하기

프로세스 간 실행을 공유하려면 실행 객체를 인수로 전달하세요.
def do_work(run):
    with wandb.init() as run:
        run.log(dict(this=1))

def main():
    run = wandb.init()
    p = mp.Process(target=do_work, kwargs=dict(run=run))
    p.start()
    p.join()
    run.finish()  # 실행 완료로 표시


if __name__ == "__main__":
    main()
W&B는 로깅 순서를 보장할 수 없습니다. 동기화는 스크립트 작성자가 직접 처리해야 합니다.

문제 해결

W&B와 분산 학습을 사용할 때 흔히 겪을 수 있는 문제는 두 가지입니다.
  1. 학습 시작 시 멈춤 - 분산 학습에서 사용하는 multiprocessing과 wandb의 multiprocessing이 서로 간섭하면 wandb 프로세스가 멈출 수 있습니다.
  2. 학습 종료 시 멈춤 - 학습 작업이 종료 시점에 wandb 프로세스가 언제 종료해야 하는지 알지 못하면 멈출 수 있습니다. Python 스크립트의 마지막에서 wandb.Run.finish() API를 호출해 실행이 완료되었음을 W&B에 알려야 합니다. wandb.Run.finish() API는 데이터 업로드를 마무리한 뒤 W&B 프로세스를 종료합니다.
W&B는 분산 작업의 신뢰성을 높이기 위해 wandb service 명령을 사용할 것을 권장합니다. 위의 두 가지 학습 문제는 주로 wandb service를 사용할 수 없는 버전의 W&B SDK에서 자주 발생합니다.

W&B Service 활성화

사용 중인 W&B SDK 버전에 따라 W&B Service가 기본적으로 이미 활성화되어 있을 수 있습니다.

W&B SDK 0.13.0 이상

W&B SDK 0.13.0 이상에서는 기본적으로 W&B Service가 활성화되어 있습니다.

W&B SDK 0.12.5 이상

Python 스크립트를 수정하여 W&B SDK 0.12.5 이상 버전에서 W&B Service를 활성화하세요. 메인 함수 내에서 wandb.require 메서드를 사용하여 문자열 "service"를 인자로 전달하세요:
if __name__ == "__main__":
    main()


def main():
    wandb.require("service")
    # 나머지-스크립트-내용-여기에-작성
최적의 사용 환경을 위해 최신 버전으로 업그레이드할 것을 권장합니다. W&B SDK 0.12.4 및 이전 버전 W&B SDK 버전이 0.12.4 이하인 경우 WANDB_START_METHOD 환경 변수를 "thread"로 설정하여 멀티스레딩을 사용하십시오.