[W ProcessGroupNCCL.cpp:1618] Rank 1 using best-guess GPU 1 to perform barrier as devices used by this process are currently unknown. This can potentially cause a hang if this rank to GPU mapping is incorrect.Specify device_ids in barrier() to force use of a particular device. 해결법
에러 메시지
[W ProcessGroupNCCL.cpp:1618] Rank 1 using best-guess GPU 1 to perform barrier as devices used by this process are currently unknown.
This can potentially cause a hang if this rank to GPU mapping is incorrect.Specify device_ids in barrier() to force use of a particular device.
이후 코드 돌아가다가 갑자기 사망.
에러 발생 지점
$python -m torch.distributed.launch
pytorch의 torch.distributed.launch, 즉 multi-gpu 상황일 때 발생한다.
일반적으로 torch.distributed.launch를 하게 되면, 자동으로 프로세스에 process local rank가 할당되고, local rank에 따라 cuda:0, cuda:1 형식으로 디바이스를 할당하게 된다. 그리고 다른 프로세스가 동시 점유 하여 문제가 발생하지 않도록, barrier라는 개념이 있는데, 이 barrier가 정상적으로 작동하지 못하게 되면 문제가 발생한다.
다양한 원인이 존재한다.
NCCL, NVCC 버전 문제 / 드라이버 손상
동일한 Local Rank를 가진 Zombie 프로세스가 백그라운드에 살아있어서 발생하는 문제
Pytorch 버전 문제(?)
해결법
NCCL, NVCC 드라이버 문제
NCCL과 CUDA와 cuDNN을 다시 설치해주면 문제가 해결될 수 있다.
Zombie Process 문제
$ps -ef | grep python
위 명령어를 통해 Python이 사용되고 있는 프로세스를 찾고 종료시킨다. 일반적으로, 그래픽카드를 사용하여 생기는 문제이므로, 간단하게
$nvidia-smi
위 명령어를 통해 process의 pid를 얻어내고 종료시켜도 좋다.
Pytorch 버전 문제
물론 정상적인 방법은 아니다. 위 방법을 모두 시도했을때도 실패했다면 시도를 해보는 것이 바람직하다. 해당 이슈는 Pytorch가 1.9로 버전업되면서 분산학습에 torch elastic이 사용되는 경우가 있다. 여기서 문제가 발생하는 경우가 꽤 많은 것 같다.
완벽한 대응은 아니었지만, 필자는 huggingface의 BERT를 Tesla V100 2대로 분산학습 시키는 과정에서 위 에러를 만났고, 끝까지 해결법을 찾지 못해 torch 버전을 아예 1.6버전으로 낮춰버리고 다시 학습을 돌렸더니 정상적으로 동작을 하는 모습을 확인할 수 있었다.
리눅스를 사용하다보면, 로그파일이나 머신러닝에서 필요한 데이터셋등 거대한 파일을 주로 다루게 된다.
문제는 이렇게 너무 거대한 파일들은 정상적으로 Editor로 열어보기도 힘들 뿐더러,
파일 입출력이라도 시도했다간, Memory 전체 크기보다 파일의 용량이 크기 때문에 프로그램이 죽어버리게 되는 불상사가 생긴다.
이러한 문제점을 해결하기 위해서, 리눅스는 split이라는 커맨드를 통해 거대한 파일을 다양한 방식으로 sharding 하는 기능을 제공한다. 이번 포스팅에서는 split과 사용 방법에 대해 다룬다.
파일 크기 기준으로 쪼개기
$split -b 크기(byte) 파일명
# Example
$split -b 1024 console_log # 1024 바이트 단위로 분할
$split -b 1k console_log # 1kb 단위로 분할
$split -b 1m console_log # 1mb 단위로 분할
$split -b 1024m console_log #1gb 단위로 분할
# g는 지원안함
파일을 원하는 용량 단위로 나눠주는 역할을 하게 된다. 다만 접두사 설정을 달지 않으면, xaa xab xac 이런식으로 굉장히 분할이 너저분하게 되므로 접두사 설정을 확인하자.
파일명 지정 (prefix 설정)
$split console_log [원하는 접두사]_
# Example
$split console_log log_
위와 같은 설정을 통해 보다 가독성 좋게 파일을 쪼갤 수 있다.
라인 수 기준으로 쪼개기
$split -l [원하는 라인수] [분할할 파일 이름]
# Example
$split -l 10000 console_log log_ #10000라인 단위로 자르기
# TIP
$wc -l console_log # 원본 파일의 총 라인수가 몇인지 알 수 있음
또한 라인수를 기준으로 자르는 것도 가능하다.
이는 머신러닝에서 NLP를 다룰 때 매우 유용하게 사용된다.
Corpus가 일반적으로 행 마다 sentence 하나를 저장하게끔 설계된 경우가 많기 때문에, 애용하는 옵션이다.
linux에서 현재 메모리 상태를 보는 top 명령을 통해 메모리 상태를 보게 되면, buff/cache라는 값이 있다는 것을 확인할 수 있다. Used도 아니고 Available도 아닌 이 메모리는 무엇일까?
이 메모리는 실제로 사용되는게 아니라, 버퍼와 캐시에서 사용하는 메모리 할당량이다. 물론 일반적으로 캐시에 저장된 값은 자주 사용되기 때문에 OS에서 등록한 정보이고, 이로 인해 성능의 향상을 불러오지만, 딥러닝등 일반적이지 않은 대용량 데이터를 빈번히 Load 해야 하는 상황에서는 캐시에 저장된 값을 자꾸 바꿔주는데 들어가는 비용이 더 커지기 때문에, 학습 스크립트를 모두 돌린 후에, 새로운 학습 스크립트를 돌리기 위해서는 미리 비워주는 것이 오히려 더 좋다.
즉, cache의 hit ratio가 앞으로 극히 낮아질 것이라는 확신이 있다면, buffer/cache를 미리 비워줌으로써 새로운 데이터를 금방 할당받을 수 있도록 하는 것이 유리하다.
Page Cache 해제
sync
$echo 1 > /proc/sys/vm/drop_caches
첫줄의 sync는 플러싱을 해주는 역할로, 현재 사용하고 있는 메모리 데이터를 동기화해주는 역할을 한다.
삭제 전에 sync를 통해 불필요한 메모리 손실이 일어나지 않도록 한다.
Dentries, I-nodes 해제
sync
echo 2 > /proc/sys/vm/drop_caches
Page Cache, Dentries, I-nodes 모두 해제
sync
echo 3 > /proc/sys/vm/drop_caches
위와 같은 방식을 통해, 버퍼/캐시 메모리를 모두 비워주고 나면, Free Memory의 값이 커지고, Buff/Cache 값이 줄어들게 된다.
먼저 기본적으로, 카카오톡 알림, 네이버 알림등은 서버를 통해 어느정도 딜레이가 발생 한 후 푸시 알림이 도착하므로, 알림을 받아서 예약하는건 사실상 불가능합니다.
빨리빨리의 민족 한국답게 1초만에 이미 예약이 완료되는 경우가 많기 때문에,
자주 잔여백신이 나오는 병원을 미리 잘 파악하고 있다가, 해당 병원들에 대해서 무한 업데이트를 진행하는 방식이 가장 빠르게 예약 페이지로 넘어갈 수 있는 방법인 것 같습니다. 다만 손가락이 아플정도로 업데이트해야하고, 계속 들여다봐야 한다는 단점이 있습니다. 그렇게 하다보니 성공적으로 예약이 성공했습니다.
접종 방법
3시쯤 예약이 잡혔는데, 4시까지 운영한다는 내용이 와있어서,
급하게 허겁지겁 출발했습니다.
제가 예약한 곳은 그렇게 큰 병원은 아니었어서 대기가 길지도 않았고,
"잔여백신 맞으러 왔어요!"하면서 가면 접종 전 문답지를 주시고,
문답지만 작성하면 바로 진료실에 들어가 접종받는 방식이었습니다.
문답지 작성 후에 접종받는 건 사실상 1분도 안걸렸고,
이상반응이 있는지 없는지 15분간 병원에서 대기 후 귀가하도록 안내받았습니다.
생각보다 너무 빨리빨리 진행되서 당황스러울 정도였습니다 ㅋㅋ
직장인분들도 살짝 나가서 접종받을 수도 있지 않을까 싶을 정도로 빠르게 진행됩니다.
2차접종에 대해서 다들 궁금하실텐데,
잔여백신은 1차 예약하는 순간 자동으로 2차접종 예약까지 진행된다고 합니다.
실제로 접종 후 5분정도 지나니까 2차 접종 안내 국민비서 문자가 왔습니다.
유의 사항
의사 선생님께서, 20대 초반 남자분들이 심근염등 부작용이 생길 수 있다고 말씀하셨는데,
사실 100만명중에 3~4명 꼴로 일어나는 희귀한 상황이니 걱정할 필요는 없다고 하셨습니다.
다만 유의사항을 몇가지 말씀해주셨는데 다음과 같습니다.
밤까지 늦게 스마트폰/컴퓨터 하지 않고 무조건 일찍 잠자리에 들고, 충분한 시간 수면 취할 것 -> 수면이 부족할 경우 몸안에서 염증 반응이 급격히 증가하고, 부작용 가능성이 높아질 수 있다.
가능한 일주일 동안은 격렬한 운동 하지 않을 것 -> 무산소성 근력운동 또한 몸에 염증 수치를 높이므로, 기본적으로 염증과 관련된 모든 신체 활동은 자제하는 것이 좋다.
2~3일간은 무기력증을 동반한 근육통이 있을 수 있다. 정상적인 현상이니 너무 심하면 타이레놀을 먹고, 물을 많이 마셔주는 것이 도움이 된다. -> 타이레놀은 사실 필수는 아니고, 물을 충분히 많이 마셔주는 것도 통증 완화에 도움이 된다고 한다.
첫날은 목욕 자제, 둘째날에도 접종 부위에 직접 물 닿는건 피할 것 -> 감염? 때문이 아닐까 싶습니다.
접종 후기
처음 접종 할 때는, 그냥 일반적인 주사랑 별반 다를 바가 없습니다.
딱히 더 아프거나 덜 아프거나 하지 않고, 살짝 따끔하고 끝납니다.
그 후에도 별다른 느낌은 없으나, 2~3시간 쯤 지나면 슬슬 접종 부위 주변으로 근육이 뭉치는 느낌이 들고,
손끝이 살짝 저립니다.
백신 먹고 삼겹살 먹으면 덜 아프다는 민간 요법이 있는데, 당연히 비과학적이고 아무 효과도 없을 거라는 걸 알지만 괜히 갑자기 고기 땡겨서 목살을 구워먹었습니다 ㅋㅋㅋ
접종 후 4~5시간 쯤 지나면 근육통이 좀 더 생기는데, 걱정하실 정도는 아니고 남자분들이라면 헬스장에서 팔 운동 했을 때, 근육통 온 느낌입니다. 아무래도 지인들의 사례를 봤을 때는 근육통에 익숙하지 않은 여성분들이 더 고통을 많이 호소하는 듯 한 느낌입니다.
7시간 쯤 지나면, 팔에서 어깨쪽까지 근육통 범위가 점점 늘어납니다.
많이 아픈 수준은 아니고, 이것도 마찬가지로 어깨 운동 한 다음날 근육 뻐근한 느낌과 가장 흡사합니다.
그리고 이 때부터는 37도가 넘어가면서 미열이 발생합니다.
그냥 자도 되겠지만, 열이 높아지면 두통 증상이 생긴다고 들어서 그냥 저는 타이레놀을 먹고 잤습니다.
--model_type : pretrained weight 없이 구조만 가져와서 처음부터 학습을 진행할 시 사용된다. 본 포스팅에서는 bert를 학습하므로, bert를 입력하면 된다.
--tokenizer_name: pretrained tokenizer를 불러오거나, tokenizer가 저장된 폴더의 경로를 전달하여 tokenizer를 불러온다. 기본적으로, tokenizer_config.json, vocab.txt, special_tokens_map.json을 불러오며, 이는 이전 포스팅에서 학습한 tokenizer를 저장한 경로에 존재한다.
--max_seq_length : input으로 사용될 문장의 길이 한도를 의미한다. bert-based 모델은 512를 사용하므로 512를 입력
--train_file : 학습에 사용될 Corpus 데이터를 전달하면 된다.
--validation_file : validation 과정에 사용될 Corpus 데이터 경로를 전달하면 된다.
--validation_split_percentage : 별도의 validation_file이 없을 경우, train set에서 몇퍼센트를 추출하여 validation_set으로 활용한다. 10정도 입력하면 적절하다.
--cache_dir : 전처리된 임시 파일, 로그, checkpoint등이 저장될 경로, 입력하지 않으면 기본값인 nltk_data cache로 가지만, 지정해주면 해당 경로에 저장된다. 생각보다 용량이 커질 수 있으므로 용량이 넉넉한 파티션에 지정하는 것이 좋다.
--preprocessing_num_workers : 전처리에 사용할 프로세스의 개수이다. CPU Core수에 맞게 적절히 세팅해주면 좋다. 기본값으로 돌릴 시 47시간 걸리던 전처리가, num_workers를 16으로 해줬더니 10시간으로 줄어들었다. 하지만 너무 클 경우 CPU와 메모리에 부하가 크므로, CPU 사양을 고려하여 설정해야한다.
--line_by_line : 문장이 라인 단위로 쪼개져있는 Corpus에서 사용한다. 기본적으로 False 상태로 되어있다. 기본적으로 huggingface에서는 line_by_line이 꺼져있으면, 문장들을 합친 뒤 512를 넘기지 않도록 적절히 chunks를 만들고 이를 이용해 학습을 진행한다. line_by_line은 왠만하면 키지 않는 것이 좋다. 오용될 경우, Corpus에 불필요한 [PAD]가 매우 많이 발생하기 때문이다.
--pad_to_max_length : 512보다 짧은 문장에 padding을 추가하여 512로 만들어준다. 기본적으로 켜주는게 좋지만, 잘못된 방식으로 line_by_line과 함께 사용될 경우, 전체 데이터 단어 1개에 [PAD] 토큰 99개가 붙는 최악의 상황이 발생할 수 있다.
--per_device_train_batch_size : 말 그대로 train batch size
--per_device_eval_batch_size : eval batch size
--save_steps : 몇 step 마다 저장할 것인지, 기본값은 5000이지만, Corpus가 크다면 넉넉히 설정하는게 좋다. 너무 자주 저장되면 checkpoints 용량도 어마어마하게 크기 때문이다.