Introduction 

저의 경우에서는 DDP를 구성하고 코드 작업을 하는 경우가 많다. 그렇다 보면 torch에서 DDP로 구성하는것이 귀찮기도 하고 생각보다 시간이 걸리는데 

이러한 노고의 시간을 줄여주기 위한 유용한 library가 있어서 공유하고자 한다. 

https://huggingface.co/docs/accelerate/index

 

Accelerate

Concepts and fundamentals

huggingface.co

 

 

홈페이지에 들어가보면 보는 것과 같이 Pytorch code의 distributed configuration을 4개의 라인으로 줄여서 효과적으로 사용하게 되는 방법을 제공해준다고 한다. 

홈페이지에서 제공해주는 코드지만 아래의 코드에 보는바와 같이 4줄이면 DDP setting이 끝나는 것을 볼 수 있다.

+ from accelerate import Accelerator
+ accelerator = Accelerator()

+ model, optimizer, training_dataloader, scheduler = accelerator.prepare(
+     model, optimizer, training_dataloader, scheduler
+ )

  for batch in training_dataloader:
      optimizer.zero_grad()
      inputs, targets = batch
      inputs = inputs.to(device)
      targets = targets.to(device)
      outputs = model(inputs)
      loss = loss_function(outputs, targets)
+     accelerator.backward(loss)
      optimizer.step()
      scheduler.step()

위와 같이 코드를 넣어지게 되어지만 torch_xla, torch.distributed가 build가 되어진다. 

tmi) 최근에서는 fully sharded data parallelism도 되어지니 유용하게 사용하고 있다. 

 

코드 실행은 아래와 같이 python파일에 accelerate launch만 넣어주면 된다. 

accelerate launch {my_script.py}

 

그러면 아주 설치과정부터 기본 실행까지 보자.

 Installation 

설치는 Python3.8이상부터는 되어지는 환경이고 pip 으로 설치할 경우 아래와 같이 되어진다. 

pip install accelerate

conda의 경우도 아래와 코드와 같이 되어지며 source github에서 설치할려면 다음과 같다. 

conda install -c conda-forge accelerate
pip install git+https://github.com/huggingface/accelerate

그리고 acclerate에 기본 default로 설정되어지는 값들이 있는데 이 값들의 수정함으로써 DDP나 process의 설정이나 config에 대해서 설정할수 있다. 

accelerate env

- `Accelerate` version: 0.11.0.dev0
- Platform: Linux-5.10.0-15-cloud-amd64-x86_64-with-debian-11.3
- Python version: 3.7.12
- Numpy version: 1.19.5
- PyTorch version (GPU?): 1.12.0+cu102 (True)
- `Accelerate` default config:
        - compute_environment: LOCAL_MACHINE
        - distributed_type: MULTI_GPU
        - mixed_precision: no
        - use_cpu: False
        - num_processes: 2
        - machine_rank: 0
        - num_machines: 1
        - main_process_ip: None
        - main_process_port: None
        - main_training_function: main
        - deepspeed_config: {}
        - fsdp_config: {}

 

Start

설치가 끝났다면 어떻게 사용하는지 다시 한번 살쳐보자. 

1. 첫번째로는 아래와 같이 accelerate를 불러온다. 

 

이때 Accelerator의 내부에서는 많은 변수들을 받을수 있는데 scipts안에서 setting이 가능하기때문에 이 내용에 대해서는 추구에 살펴보기도 하자.

참고로 GPU의 갯수에 따라서 multi GPU인지 single GPU인지 인식이 되어저 사동으로 환경을 setting해주는 많이 건들어질것 없을것이다. 

from accelerate import Accelerator 
accelerator = Accelerator()

 

2. 두번째로 중요한건 우리가 tensor에 선언헀던 to(device), cuda()부분은 지워야 한다. 

왜냐하면 accelerator로 선언되어진 객체로 multi gpu에 따라서 device를 자동으로 할당되어주기 때문에 to(accelerator.device)로 변경해줘야 한다. 

3. training에 사용되어지는 객체들을 prepare() 라는 곳에 넣어준다. (아래코드와 같다. )

아래 코드오 Parellel하게 사용되어지는 경우가 필요하면 prepare에 넣으면 되며 

model, optimizer, train_dataloader, lr_scheduler = accelerator.prepare(
    model, optimizer, train_dataloader, lr_scheduler
)

4. loss.backward()의 경우도 DDP로 되어지는 경우도 있음으로 accelerator.backward(loss)로 되어져야 한다. 

Config 

accelerate를 사용하게 되어질때 이전의 multi GPU나 mixed precision이나 선택해야될때가 있는데  

이것에 따른 config를 설정해주기 위해서 accelerate config라는 명령어가 있다. 

아래와 같이 입력하면 각종 setting들을 쉽게 만들어준다. 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------In which compute environment are you running?
This machine                                                                                                                                                                                                                
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Which type of machine are you using?                                                                                                                                                                                        
multi-GPU                                                                                                                                                                                                                   
How many different machines will you use (use more than 1 for multi-node training)? [1]: 2                                                                                                                                  
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------What is the rank of this machine?                                                                                                                                                                                           
0                                                                                                                                                                                                                           
What is the IP address of the machine that will host the main process? ---                                                                                                                                                
What is the port you will use to communicate with the main process? ---                                                                                                                                                   
Are all the machines on the same local network? Answer `no` if nodes are on the cloud and/or on different network hosts [YES/no]: ㅜno
What rendezvous backend will you use? ('static', 'c10d', ...): static
Do you wish to optimize your script with torch dynamo?[yes/NO]:no
Do you want to use DeepSpeed? [yes/NO]: no
Do you want to use FullyShardedDataParallel? [yes/NO]: no
Do you want to use Megatron-LM ? [yes/NO]: no
How many GPU(s) should be used for distributed training? [1]:2
What GPU(s) (by id) should be used for training on this machine as a comma-seperated list? [all]:1,2
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Do you wish to use FP16 or BF16 (mixed precision)?
fp16                                                                                                                                                                                                                        
accelerate configuration saved at ~/.cache/huggingface/accelerate/default_config.yaml

 

위의 같은 명령어로 만들어주면 yaml파일이 만들어지며 

이렇게 설정된 config는 ~/.cache/huggingface/accelerate/default_config.yaml 에 있음으로 확인설정을 할수 있다. 

compute_environment: LOCAL_MACHINE
deepspeed_config: {}
distributed_type: MULTI_GPU
downcast_bf16: 'no'
dynamo_backend: 'NO'
fsdp_config: {}
gpu_ids: 1,2
machine_rank: 0
main_process_ip: 
main_process_port: 
main_training_function: main
megatron_lm_config: {}
mixed_precision: fp16
num_machines: 2
num_processes: 2
rdzv_backend: static
same_network: false
use_cpu: false

 

 

이러한 yaml을 변경해서 사용해도 되며 아래와 같이 config를 test하여 정상적으로 돌아가는지 확인 할 수도 있다.

accelerate test --config_file path_to_config.yaml

최종적인 코드 실행은 아래와 같이 실행이 되어지면 multi-gpu에 대해서 자동으로 할당되어서 parellel하게 실행이 되어진다. 

accelerate launch path_to_script.py --args_for_the_script

 

이렇게 실행된 코드 안에서 유용한 methode들도 많은데 이것에 대해서 간략하게 정리를 해보면 다음과 같다. 

  • if accelerator.is_local_main_process : 서버당 하나의 GPU만 동작 (서버 : GPU장비가 모인 곳)
  • if accelerator.is_main_process : 머신당 하나의 GPU에서만 동작 (머신 : GPU들)
  • accelerator.wait_for_everyone() : Multi GPU에 있는 모든 값을 모으기 위해서 다른 GPU에 있는 동작을 기다리는 명령어. 
  • accelerator.save_model(model, save_directory) : 기다린 GPU들을 model을 저장함(단 저장하기 전에 모델의 크기로 인해서 unwrap을 해야됨)
  • unwrapped_model = accelerator.unwrap_model(model) : 각 GPU에 있는 큰 모델들을 하나의 모델로 변경 (torch 저장을 추천하는 방법으로 unwarp을 해주어서 model을 뱉어낸후에 torch.save로 해서 저장함)

ETC

우리가 흔히 deep learning을 사용하다보면 kaggle이나, notebook에서 사용하는 경우가 많은데 

이와 같은 경우에서는 학습하는 function을 notebook_launcher에 넣고 실행하면된다. 

코드는 아래와 같다. 

from accelerate import notebook_launcher

notebook_launcher(training_function)

 

 

마치며

이번시간에서는 이렇게 accelerator에 유용한 기능들과 실행 방법에 대해서 알아보았다. 

다음번에는 좀더 다양한 기능들에 대해서 알아보겠다.

 

 

반응형

+ Recent posts