연구/삽질

[pytorch layer partitioning] 삽질 1회차 저장

윤창이 2021. 3. 31. 21:54
728x90

[주의] 개인 공부를 위해 쓴 글이기 때문에 주관적인 내용은 물론, 쓰여진 정보가 틀린 것일 수도 있습니다!

피드백 부탁드립니다. (- -)(_ _) 꾸벅

 

 


목표 : pytorch 프레임워크를 수정하여 CPU, GPU 이기종 디바이스에서 병렬 처리 training & Inference 구현

 

지금까지 한 것 - 파이토치 내부 프레임워크 분석.. 인데

2021.01.20 - [딥러닝 & 머신러닝/Pytorch] - [Pytorch] 1. torch 라이브러리 내부 구조 분석 (cpython, ctype, __init__)

2021.03.27 - [딥러닝 & 머신러닝/Pytorch] - [Pytorch] 2. torch 라이브러리 내부 구조 분석 (Module.cpp, THP 모듈)

2021.03.27 - [딥러닝 & 머신러닝/Pytorch] - [Pytorch] 3. torch 라이브러리 내부 구조 분석 (Convolution)

및 pytorch의 image classification의 동작 원리 이해 정도?

 

말이야 쉽지 첨부터 프레임워크 단에서 뭔가를 한다는 게 말이 안 된다. 특히 이제 알고리즘을 다 배운 학부생한테 넘 가혹 ㅠㅠ

일단 application 단에서 multiproessing을 이용하여 구현하고 실제로 효과가 있는지, 개선의 의지가 있는지 확인하는 게 우선이다.

 

 

먼저 데모용 모델을 간단하게 만들었다.

 

지금 단계에서는 첫 번째 input image를 CPU와 GPU에 어떻게 분배할지에 대한 policy(정책)이 없기 때문에 반반으로 나누어 주기로 했다. filter size가 5이므로 W, H는 4가 줄어들고 out channel은 6이므로 3, 3으로 이기종 디바이스에 나누어 연산해주기로 한다. 그림으로 간략히 나타내면 아래와 같다.

 

torch에서 기본적으로 제공하는 multiprocessing 라이브러리로 두 개의 모델을 한 곳에서는 CPU, 한 곳에서는 GPU에서 training 하는 것은 코드를 짰는데, 학습시간은 동시에 하여도 모델이 두 개인 만큼 2배로 나온다. 

목표는 이제 filter를 반반으로 나누어 CPU, GPU에 할당하는 것,  processor 간의 데이터 교환은 shard memory를 이용하도록 한다.

(Conv layer의 filter는 완벽하게 랜덤으로 나온다니깐 일단 무시 stackoverflow.com/questions/58870925/is-conv2d-using-random-filters-is-that-good-for-the-nn)

 

multiprocessing 방식에는 fork, spawn, forkserver의 세 가지 방법이 있는데, forkserver는 마이너 방식이고, CUDA에서 multiprocess를 돌릴 때 fork 방식은 안된다고 하여 spawn 방식을 사용한다. 그 이유는 multi-threaded 프로그램을 fork 하는 순간 child process가 무조건 죽어버리는 현재의 OS 디자인의 문제라고 한다. (newsight.tistory.com/323)

 

multiprocessor를 돌리기 위해서 한 번의 convolution layer를 forward 하고 merge 하기 전에 기다려야 하는 join부분이 있다.

 

먼저 multiprocessing을 위한 프로세서로 mp.Process(targer = ?, arg = ?) 처럼 객체를 만들어 줘야 하는데 target이 될 함수로는 module을 상속받은 net 모델의 레이어 객체인 x = conv1(x)가 될 것 같다. forward 함수 내에서 mp.Process 객체를 만들어 줘야 할 것 같고, argument로는 input data인 x면 되지 않을까?? mp.Process(target = conv1, arg = (x, )) 이걸로 시도해보기로..

 

각 conv 레이어마다 프로세서를  생성해서 cpu, gpu의 멀티 처리를 하는 것? 아닌데 device 초기에 정해지면 정적인 모델 바꿀 수 없으니깐 모델을 두 개로 만드는 게 맞네ㅅㅂ 

 

 

sync

모델 두 개로 하고, conv 연산이 끝나고 나면 기다리는걸 Lock의 acquire(), release() 메서드를 사용하자. 두 개의 conv가 각기 다르게 끝나도 동시에 끝낼 수 있도록 sync를 맞춘다. acquire은 각 conv나 forward의 try:~finally: 부분에 넣고 기다리도록 한다.

두 개가 끝났음을 알리는 trigger가 발동하면 lock의 release()를 해주고, merge를 위해 shard_memory로 공유. GPU에서 maxpool을 시도하자. (혹은 merge 하기 전에 maxpool 해주고 다음 conv layer 하기 전 merge? relu 작동원리 파악해 볼 것) 쨋든 첫 번째 conv에서 나온 도출물은 다시 CPU, GPU 둘 다 똑같이 갖고 있어야 한다는 뜻.

 

trouble shooting - 첫 번째 conv에서 나온 도출물을 VRAM과 RAM에 각기 넣기 전에 merge를 어디서 진행해야 하는가? tensor를 조작하는 방법? shared memory 접근 방법

 

 

 

728x90