heojae / FoodImageRotationAdmin

Food Image Rotation (음식이미지 회전) 이라는 주제에 대해서. 실제로 딥러닝(deeplearning)을 어떻게 도입하고, 이를 API(backend)로서 서버에 올리며, 웹(frontend) 를 통해서 올리는 과정을 구현하기 위해서 만든 프로젝트입니다.
0 stars 0 forks source link

[Backend] Gunicorn 의 gthread 상태일때의, multi worker 와 multi thread 의 결과에 대한 실험 및 분석 #42

Open heojae opened 3 years ago

heojae commented 3 years ago

대주제 : Gunicorn 의 mutli worker 와 multi thread 에 관하여 실험을 해보고 싶어서, 실험을 해보게 되었습니다.

소주제 : Gunicornmutli worker 와 multi thread 때에 따라 request 를 처리하는 방향에 대해서 정리하고 싶었습니다.

Gunicorn 이란?

gunicorn 이란 python Server 를 배포하기위해서, 사용되는 WSGI 중에 하나입니다.

다양한 모드(sync, gthread, gevent, tornado, eventlet) 들을 통해 다양한 경우를 지원을 해준다는 장점이 있어서, 많이들 사용하는 WSGI 입니다.

https://docs.gunicorn.org/en/stable/


왜 실험을 하고 싶은 것인가?

예전에 딥러닝 모델을 API 로서, 올리는 과정에서 gunicorn 을 활용하였습니다.

그런데, 생각보다, 성능이 기대한 만큼 처리를 하지 못하고, 리퀘스트가 늘어나면 어느정도 에서는 엄청 느려진다는 것을 볼 수 있었습니다.

물론, 딥러닝연산 이 많은 CPU 연산량 이 필요한 작업이 맞지만, 어느정도 한계가 느껴진다는 것을 느낄 수 있었고,

process(worker) 를 늘릴수록, 기대한 만큼의 수치가 나오지 않는다는 것 또한 확인할 수 있었습니다.

물론, 제가 Gunicorn 의 내부 알고리즘을 전체를 다 분석을 할 수도 없었고, 당시 할당받은 서버의 스펙내부에서 최대한 성능을 이끌어 내고 싶었기에, AB(Apache Benchmark)test 를 활용하여서, 가장 좋은 결과가 나오는 경우를 찾아내었지만,

gunicorn 자체의 내부 알고리즘이 processcalculation time 이 늘어 날때마다, 어떻게 달라지는지는 확인하지 않았기에, 이를 대략적으로 확인하고 싶어 이를 실험하기로 하였습니다.


실험전 알고들어 가야하는 부분

우선, gunicorn 에 대해서, 완벽하게 제가 알지 못합니다.

각각의 경우에 대한 실험 또한, 간단하게 만든 실험 파일들을 기반으로, gunicorn 의 환경설정 값을 변화시켜서 만든 것일 뿐이고,

다음번에 돌렸을 때에는, 언제나 다른 결과가 나올수 있으며, 아래에 나온 결과 값들도 정확한 것은 아닙니다.

하지만, 대체적으로 worker x thread == 한번에 처리가능한 request 의 수 가 이론적으로 생각했을 때와는 달라질 수 있다는 것을 염두해주시고, 봐주시면 감사하겠습니다.

저는 개인적으로, 딥러닝을 올렸을 때, 어떻게 하면 효율적으로 할 수 있을까에 대해서, 생각하였는데, sleep time == 내 서버(API) 가 대략적으로 필요한 시간이라 생각해주시고, 본인의 환경에 대해서 생각해주세요.

(물론 CPU 연산량으로 인한 처리속도 지연도 생각해보셔야합니다.)


gthread 만 선택해서, 한 이유

https://docs.gunicorn.org/en/stable/settings.html#worker-class


실험에 대한 설정

worker = 2

sleep(time)\thread t=1 t=2 t=3 t=4
2 A=524, B=276 A=513, B=287 A=587, B=213 A=568, B=232
1 A=491, B=309 A=658, B=142 A=564, B=236 A=576, B=224
0.1 A=667, B=133 A=647, B=153 A=677, B=123 A=541, B=259
0.1 r=8000 A=6810, B=1190 A=6919, B=1081 A=6163, B=1837 A=4898, B=3102
0.01 A=566, B=234 A=435, B=365 A=509, B=291 A=453, B=347
0.01 r= 8000 A=4493, B=3507 A=4135, B=3865 A=4599, B=3401 A=4290, B=3710

worker = 3

sleep(time)\thread t=1 t=2 t=3 t=4
2 A=488,B=193,C=119 A=588, B=128, C=114 A=446, B=203, C=151 A=519, B=147, C=134
1 A=377, B=176, C=247 A=520, B=152, C=128 A=516, B=148, C=136 A=513, B=161, C=126
0.1 A=630, B=123, C=46 A=396, B=237, C=167 A=361, B=280, C=159 A=339, B=263, C=198
0.1 r=8000 A=5878, B=1399, C=723 A=5472, B=1580, C=948 A=3922, B=2588, C=1490 A=3663, B=2750, C=1587
0.01 A=371, B=235, C=194 A=308, B=257, C=235 A=338, B=239, C=223 A=305, B=276, C=239
0.01 r=8000 A=3813, B=2119, C=2068 A=3067, B=2589, C=2344 A=3100, B=2565, C=2335 A=2829, B=2689, C=2482

실험 결과에 대한 정리

위의 결과를 기반으로 볼 때, 생각보다는 multi worker 를 통해서, 많은 양의 request 들을 공평하게 나누지 못하고

동시 request , request 처리시간 에 따라서 프로세스의 사용비율이 달라진다는 것을 확인할 수 있었습니다.

동시 request 수가 적거나 , request 처리시간이 클경우 이 두가지 경우에 대해서는

workerxthread 의 수만큼 동시에 request 를 처리하는 것이 아닌, 일종의 노는 process 가 존재하여, 특정 process 에 대해서 request 가 몰리는 경우가 생길 수 있어,

worker=1 일때에 비해서, 메모리 추가 양 대비, 성과가 별로일 수 있으니, 이를 참고하시면서, 개발해주시면 좋겠습니다.

heojae commented 3 years ago

실험 파일들

gunicorn_test
    - app.py
    - wsgi.py
    - client.py
    - run_server.sh
    - run_client.sh