서버 및 pytorch

[editor & 서버] VSCode로 디버깅, gpu 설정 - with HRNet

쑤스토리 2022. 4. 11. 13:09

https://github.com/HRNet/HRNet-Human-Pose-Estimation 코드를 바탕으로 작성하였다.


VSCode Debugging

run → start debuging → python file 선택

옆 설정 버튼을 누르면 launch.json이 나온다.

 

launch.json

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Test",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "args": ["--cfg", "experiments/mpii/hrnet/w32_256x256_adam_lr1e-3.yaml"]

        }
    ]
}

python tools/train.py --cfg experiments/mpii/hrnet/w32_256x256_adam_lr1e-3.yaml

 

여기서 cfg 부분을 args dictionary로 만들어준다.

그리고 f5누르면 run/debugging이 저절로 실행된다.

 

 

vscode 아이콘

 

 

여기서 breaking point

train 안에있는 상태에서 model 알고 싶으면 debug console에서 model을 치면 model 정보가 나온다

ex) cfg.GPUS : GPU 사용 정보

 

  • f10 두번째 아이콘 : 다음줄 시행
  • step into 세번째 아이콘 : breakpoint 함수 안으로/ 2줄 코드면 3번 누르기
  • step over 네번째 아이콘 : 한줄 씩 진행 (함수 안으로 안들어가고)

 

GPU 사용 설정

보통 정보는 아래와 같이 주어진다

python tools/train.py --cfg experiments/mpii/hrnet/w32_256x256_adam_lr1e-3.yaml

experiments → mpii → hrnet → w32_256x256_adam_lr1e-3.yaml 에 들어가면 위 사진과 같이 dictionary 형태로 정보가 주어지는데, GPUS : (7, ) 은 value가 tuple형태이며, 몇번째 gpu를 사용할지에 대한 key 값이다.

 

즉 GPU를 여러개 사용하고 싶다면(0,1,2,3번 사용시), GPU : (0,1,2,3) 을 사용.

 

GPU와 BATCH_SIZE_PER_GPU 관계

 

보통 gpu 1개를 사용할때, BATCH_SIZE_PER_GPU 는 32에서 (원래 GPU 4개로 각 gpu당 32개 batch) 4x32를 대입해줘야한다. But, training debuging을 할때, 빠른 학습을 위해 4로 설정!

 

Multi-gpu

 

디버깅을 할때 즉 CUDA_VISIBLE_DEVICES=7 python train.py ~ 를 작성하지 못할때,

multi gpu안에서 실제로 torch에서는 7번 외 GPU에 memory 를 할당안했으나, (위처럼 cfg.GPUS = (7,) 설정) 하드웨어 자체에서 multi-gpu로 인식해서 하드웨어는 8개 gpu를 알고있어야하고, 거기에서 7번 메모리를 할당해야하기 때문에

즉, 지금은 7번을 쓴다고 했지만 중간에 바뀔 수도 있고, 다른 GPU에 대한 최소한의 어떤 정보를 지녀야하기 때문에 11MiB 정도의 메모리가 각 GPU 0~7까지 올라가게 된다.

 

따라서 torch.cuda.memory_allocated 결과 값을 찍으면 0으로 나오지만 사실상 정보를 얻기 위해 gpu 전체를 쓰고있다고 할 수 있다.

 

따라서 코드 내에

    os.environ['CUDA_VISIBLE_DEVICES'] = ",".join(list(map(str,cfg.GPUS)))

CUDA_VISIBLE_DEVICES를 작성해주면 된다.

 

전체 코드는 아래와 같다.

    os.environ['CUDA_VISIBLE_DEVICES'] = ",".join(list(map(str,cfg.GPUS)))
    
    if len(cfg.GPUS) ==1:
        # torch.cuda.is_available()
        # torch.cuda.set_device(7)

        print('Current cuda device:', torch.cuda.current_device())
        print('Count of using GPUs:', torch.cuda.device_count())
        model = model.cuda()
    elif len(cfg.GPUS) > 1 :
        model = torch.nn.DataParallel(model, device_ids=cfg.GPUS).cuda()


    else:
        print('not in gpu')

이게 잘못될시 아래와같은 오류가 남!

 

Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same or input should be a MKLDNN tensor and weight is a dense tensor

reference : GPU설정 참고 링크

 

선택한 GPU에만 메모리 할당하는 방법

출처: https://www.tensorflow.org/tutorials/using_gpu Issue: multi-GPU 시스템에서 tensorflow를 실행할 경우 하나의 GPU에서 코드가 실행되게 프로그래밍을 해도 모든 GPU에 메모리를 할당한다. 이는 위의..

dongjinlee.tistory.com


 

Multi-gpu는 module이라는 함수를 내포하고 있으나, single gpu일때는 없기에,

다음과 같이 코드는 변경해준다.

'best_state_dict' : model.module.state_dict() if len(cfg.GPUS)>1 else model.state_dict()

 

GPU에 올라가기 위해  .cuda( ) 해주기!