๋ฉํฐGPU ๊ต์ก
์ด ๊ฐ์ด๋๋ ๋จ์ผ ๋๋ ์ฌ๋ฌ ๋์ ์ปดํจํฐ์์ YOLOv5 ๐๋ก ๋ฐ์ดํฐ ์ธํธ๋ฅผ ํ๋ จํ๊ธฐ ์ํด ์ฌ๋ฌ GPU๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.
์์ํ๊ธฐ ์ ์
๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ๋ณต์ ํ๊ณ ์๊ตฌ์ฌํญ.txt๋ฅผ ์ค์นํฉ๋๋ค. Python>=3.8.0 ํ๊ฒฝ์ ํฌํจํ์ฌ PyTorch>=1.8. ๋ชจ๋ธ ๋ฐ ๋ฐ์ดํฐ ์ธํธ๋ ์ต์ YOLOv5 ๋ฆด๋ฆฌ์ค์์ ์๋์ผ๋ก ๋ค์ด๋ก๋๋ฉ๋๋ค.
git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # install
๐ก ํ๋ก ํ! ๋์ปค ์ด๋ฏธ์ง ๋ ๋ชจ๋ ๋ฉํฐGPU ๊ต์ก์ ๊ถ์ฅ๋ฉ๋๋ค. ์ฐธ์กฐ Docker ๋น ๋ฅธ ์์ ๊ฐ์ด๋
๐ก ํ๋ก ํ! torch.distributed.run
๋์ฒด torch.distributed.launch
in PyTorch>=1.9. ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ์ฐธ์กฐํ์ธ์.
๊ต์ก
ํ๋ จ์ ์์ํ ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ ์ ํํฉ๋๋ค. ์ฌ๊ธฐ์๋ ๊ฐ์ฅ ์๊ณ ๋น ๋ฅธ ๋ชจ๋ธ์ธ YOLOv5s๋ฅผ ์ ํํฉ๋๋ค. ๋ชจ๋ ๋ชจ๋ธ์ ๋ํ ์ ์ฒด ๋น๊ต๋ README ํ๋ฅผ ์ฐธ์กฐํ์ธ์. ์ด ๋ชจ๋ธ์ COCO ๋ฐ์ดํฐ ์ธํธ์ Multi-GPU ๋ก ํ๋ จํฉ๋๋ค.
์ฑ๊ธ GPU
๋ค์คGPU ๋ฐ์ดํฐ๋ณ๋ ฌ ๋ชจ๋(โ ๏ธ ๊ถ์ฅํ์ง ์์)
๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก device
๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ๋ณ๋ ฌ ๋ชจ๋์์ ์ฌ๋ฌ GPU๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ๋ฐฉ๋ฒ์ 1๊ฐ๋ง ์ฌ์ฉํ๋ ๊ฒ์ ๋นํด ์๋๊ฐ ๋๋ฆฌ๊ณ ํ๋ จ ์๋๊ฐ ๊ฑฐ์ ๋นจ๋ผ์ง์ง ์์ต๋๋ค GPU.
๋ค์คGPU ๋ถ์ฐ๋ฐ์ดํฐ๋ณ๋ ฌ ๋ชจ๋(โ ๊ถ์ฅ)
๋ค์์ ํต๊ณผํด์ผ ํฉ๋๋ค. python -m torch.distributed.run --nproc_per_node
๋ฅผ ์
๋ ฅํ ๋ค์ ์ผ๋ฐ์ ์ธ ์ธ์๋ฅผ ์
๋ ฅํฉ๋๋ค.
python -m torch.distributed.run --nproc_per_node 2 train.py --batch 64 --data coco.yaml --weights yolov5s.pt --device 0,1
--nproc_per_node
๋ ์ฌ์ฉํ GPU ๊ฐ์๋ฅผ ์ง์ ํฉ๋๋ค. ์์ ์์์๋ 2์
๋๋ค.
--batch
๋ ์ด ๋ฐฐ์น ํฌ๊ธฐ์
๋๋ค. ๊ฐ GPU ์ ๊ท ๋ฑํ๊ฒ ๋๋ฉ๋๋ค. ์์ ์์์๋ GPU ๋น 64/2=32์
๋๋ค.
์์ ์ฝ๋๋ GPU๋ฅผ ์ฌ์ฉํฉ๋๋ค. 0... (N-1)
.
ํน์ GPU ์ฌ์ฉ(ํ์ฅํ๋ ค๋ฉด ํด๋ฆญ)
์ฅ์น` ๋ค์ ํน์ GPU๋ฅผ ์ ๋ฌํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์๋ ์ฝ๋์์๋ GPU `2,3`์ ์ฌ์ฉํฉ๋๋ค.SyncBatchNorm ์ฌ์ฉ(ํด๋ฆญํ์ฌ ํ์ฅ)
[SyncBatchNorm](https://pytorch.org/docs/master/generated/torch.nn.SyncBatchNorm.html) could increase [accuracy](https://www.ultralytics.com/glossary/accuracy) for multiple gpu training, however, it will slow down training by a significant factor. It is **only** available for Multiple GPU DistributedDataParallel training. It is best used when the batch-size on **each** GPU is small (<= 8). To use SyncBatchNorm, simple pass `--sync-bn` to the command like below,์ฌ๋ฌ ๋์ ์ปดํจํฐ ์ฌ์ฉ(ํ์ฅํ๋ ค๋ฉด ํด๋ฆญ)
์ด๋ ์ฌ๋ฌ ๊ฐ์ GPU DistributedDataParallel ๊ต์ก์ **๋ง** ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ณ์ํ๊ธฐ ์ ์ ๋ชจ๋ ๋จธ์ ์ ํ์ผ, ๋ฐ์ดํฐ ์ธํธ, ์ฝ๋๋ฒ ์ด์ค ๋ฑ์ด ๋์ผํ์ง ํ์ธํ์ธ์. ๊ทธ๋ฐ ๋ค์, ๋จธ์ ๋ค์ด ์๋ก ํต์ ํ ์ ์๋์ง ํ์ธํ์ธ์. ๋ง์คํฐ ๋จธ์ (๋ค๋ฅธ ๋จธ์ ๊ณผ ๋ํํ ๋จธ์ )์ ์ ํํด์ผ ํฉ๋๋ค. ์ฃผ์(`master_addr`)๋ฅผ ์ ์ด๋๊ณ ํฌํธ(`master_port`)๋ฅผ ์ ํํฉ๋๋ค. ์๋ ์์ ์์๋ `master_addr = 192.168.1.1`๊ณผ `master_port = 1234`๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. ์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด ๋ฉ๋๋ค, ์ฌ๊ธฐ์ `G`๋ ๋จธ์ ๋น GPU ๊ฐ์, `N`์ ๋จธ์ ์, `R`์ `0...(N-1)`์ ๋จธ์ ๋ฒํธ์ ๋๋ค. GPU๊ฐ ๊ฐ๊ฐ 2๊ฐ์ฉ ์๋ ๋จธ์ ์ด ๋ ๋ ์๋ค๊ณ ๊ฐ์ ํ๋ฉด ์์ ๊ฒฝ์ฐ `G = 2` , `N = 2`, `R = 1`์ด ๋ฉ๋๋ค. ํ๋ จ์ ๋ค์์ด ๋ ๋๊น์ง ์์๋์ง ์์ต๋๋ค. ๋ชจ๋ N`๋์ ๋จธ์ ์ด ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค. ์ถ๋ ฅ์ ๋ง์คํฐ ๋จธ์ ์๋ง ํ์๋ฉ๋๋ค!์ฐธ๊ณ
- Windows ์ง์์ ํ ์คํธ๋์ง ์์์ผ๋ฉฐ Linux๋ฅผ ๊ถ์ฅํฉ๋๋ค.
--batch
๋ GPU ์์ ๋ฐฐ์์ฌ์ผ ํฉ๋๋ค.- GPU 0์ EMA๋ฅผ ์ ์งํ๊ณ ์ฒดํฌํฌ์ธํธ ๋ฑ์ ๋ด๋นํ๋ฏ๋ก ๋ค๋ฅธ GPU๋ณด๋ค ์ฝ๊ฐ ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐจ์งํฉ๋๋ค.
- ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ
RuntimeError: Address already in use
๋ก ํ์๋๋ ๊ฒฝ์ฐ ํ ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ ๊ต์ก์ ์คํํ๊ณ ์๊ธฐ ๋๋ฌธ์ผ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋ค๋ฅธ ํฌํธ ๋ฒํธ๋ฅผ ์ถ๊ฐํ์ฌ--master_port
์๋์ ๊ฐ์ด,
๊ฒฐ๊ณผ
1 COCO ์ํฌํฌ์ ๋ํ YOLOv5l์ฉ 8x A100 SXM4-40GB๋ฅผ ์ฌ์ฉํ๋ AWS EC2 P4d ์ธ์คํด์ค์ DDP ํ๋กํ์ผ๋ง ๊ฒฐ๊ณผ.
ํ๋กํ์ผ๋ง ์ฝ๋
# prepare
t=ultralytics/yolov5:latest && sudo docker pull $t && sudo docker run -it --ipc=host --gpus all -v "$(pwd)"/coco:/usr/src/coco $t
pip3 install torch==1.9.0+cu111 torchvision==0.10.0+cu111 -f https://download.pytorch.org/whl/torch_stable.html
cd .. && rm -rf app && git clone https://github.com/ultralytics/yolov5 -b master app && cd app
cp data/coco.yaml data/coco_profile.yaml
# profile
python train.py --batch-size 16 --data coco_profile.yaml --weights yolov5l.pt --epochs 1 --device 0
python -m torch.distributed.run --nproc_per_node 2 train.py --batch-size 32 --data coco_profile.yaml --weights yolov5l.pt --epochs 1 --device 0,1
python -m torch.distributed.run --nproc_per_node 4 train.py --batch-size 64 --data coco_profile.yaml --weights yolov5l.pt --epochs 1 --device 0,1,2,3
python -m torch.distributed.run --nproc_per_node 8 train.py --batch-size 128 --data coco_profile.yaml --weights yolov5l.pt --epochs 1 --device 0,1,2,3,4,5,6,7
GPU A100 |
๋ฐฐ์น ํฌ๊ธฐ | CUDA_mem device0 (G) |
COCO ๊ธฐ์ฐจ |
COCO val |
---|---|---|---|---|
1x | 16 | 26GB | 20:39 | 0:55 |
2x | 32 | 26GB | 11:43 | 0:57 |
4x | 64 | 26GB | 5:57 | 0:55 |
8x | 128 | 26GB | 3:09 | 0:57 |
์์ฃผ ๋ฌป๋ ์ง๋ฌธ
์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๋จผ์ ์๋ ์ฒดํฌ๋ฆฌ์คํธ๋ฅผ ์ฝ์ด๋ณด์ธ์! (์๊ฐ์ ์ ์ฝํ ์ ์์ต๋๋ค)
์ฒดํฌ๋ฆฌ์คํธ(ํ์ฅํ๋ ค๋ฉด ํด๋ฆญ)
- ์ด ๊ฒ์๋ฌผ์ ์ ๋๋ก ์ฝ์ผ์ จ๋์?
- ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ค์ ๋ณต์ ํด ๋ณด์ จ๋์? ์ฝ๋๋ ๋งค์ผ ๋ณ๊ฒฝ๋ฉ๋๋ค.
- ์ค๋ฅ๋ฅผ ๊ฒ์ํด ๋ณด์ จ๋์? ๋๊ตฐ๊ฐ ์ด๋ฏธ ์ด ๋ฆฌํฌ์งํ ๋ฆฌ๋ ๋ค๋ฅธ ๋ฆฌํฌ์งํ ๋ฆฌ์์ ์ด ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ์ฌ ํด๊ฒฐ์ฑ ์ ๊ฐ์ง๊ณ ์์ ์ ์์ต๋๋ค.
- ์๋จ์ ๋์ด๋ ๋ชจ๋ ์๊ตฌ ์ฌํญ(์ฌ๋ฐ๋ฅธ Python ๋ฐ Pytorch ๋ฒ์ ํฌํจ)์ ์ค์นํ๋์?
- ์๋ 'ํ๊ฒฝ' ์น์ ์ ๋์ด๋ ๋ค๋ฅธ ํ๊ฒฝ์์๋ ์๋ํด ๋ณด์ จ๋์?
- coco128 ๋๋ coco2017๊ณผ ๊ฐ์ ๋ค๋ฅธ ๋ฐ์ดํฐ์ ์ผ๋ก ์๋ํด ๋ณด์ จ๋์? ๊ทธ๋ฌ๋ฉด ๊ทผ๋ณธ ์์ธ์ ๋ ์ฝ๊ฒ ์ฐพ์ ์ ์์ต๋๋ค.
์ง์ ํ๊ฒฝ
Ultralytics ๋ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ๋ค์ํ ํ๊ฒฝ์ ์ ๊ณตํ๋ฉฐ, ๊ฐ ํ๊ฒฝ์๋ ๋ค์๊ณผ ๊ฐ์ ํ์ ์ข ์์ฑ์ด ์ฌ์ ์ค์น๋์ด ์์ต๋๋ค. CUDA, CUDNN, Python, ๋ฐ PyTorch์ ๊ฐ์ ํ์ ์ข ์ ์์๋ฅผ ์ค์นํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ํ ์ ์์ต๋๋ค.
- ๋ฌด๋ฃ GPU ๋ ธํธ๋ถ:
- Google Cloud: GCP ๋น ๋ฅธ ์์ ๊ฐ์ด๋
- Amazon: AWS ๋น ๋ฅธ ์์ ๊ฐ์ด๋
- Azure: AzureML ๋น ๋ฅธ ์์ ๊ฐ์ด๋
- Docker: Docker ๋น ๋ฅธ ์์ ๊ฐ์ด๋
ํ๋ก์ ํธ ์ํ
์ด ๋ฐฐ์ง๋ ๋ชจ๋ YOLOv5 GitHub Actions ์ง์์ ํตํฉ(CI) ํ ์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ํต๊ณผ๋์์์ ๋ํ๋ ๋๋ค. ์ด๋ฌํ CI ํ ์คํธ๋ ๊ต์ก, ๊ฒ์ฆ, ์ถ๋ก , ๋ด๋ณด๋ด๊ธฐ ๋ฐ ๋ฒค์น๋งํฌ ๋ฑ ๋ค์ํ ์ฃผ์ ์ธก๋ฉด์์ YOLOv5 ์ ๊ธฐ๋ฅ๊ณผ ์ฑ๋ฅ์ ์๊ฒฉํ๊ฒ ํ์ธํฉ๋๋ค. 24์๊ฐ๋ง๋ค ๊ทธ๋ฆฌ๊ณ ์๋ก์ด ์ปค๋ฐ์ด ์์ ๋๋ง๋ค ํ ์คํธ๋ฅผ ์ํํ์ฌ macOS, Windows ๋ฐ Ubuntu์์ ์ผ๊ด๋๊ณ ์์ ์ ์ธ ์๋์ ๋ณด์ฅํฉ๋๋ค.
ํฌ๋ ๋ง
๋ชจ๋ ์์ ์ ๋์์ฃผ์ @MagicFrogSJTU์ ๋ชจ๋ ๊ณผ์ ์ ์๋ดํด ์ฃผ์ @glenn-jocher์๊ฒ ๊ฐ์ฌ์ ๋ง์์ ์ ํฉ๋๋ค.