We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
대주제 : Gunicorn 의 mutli worker 와 multi thread 에 관하여 실험을 해보고 싶어서, 실험을 해보게 되었습니다. 소주제 : Gunicorn 의 mutli worker 와 multi thread 때에 따라 request 를 처리하는 방향에 대해서 정리하고 싶었습니다.
대주제 : Gunicorn 의 mutli worker 와 multi thread 에 관하여 실험을 해보고 싶어서, 실험을 해보게 되었습니다.
mutli worker 와 multi thread
소주제 : Gunicorn 의 mutli worker 와 multi thread 때에 따라 request 를 처리하는 방향에 대해서 정리하고 싶었습니다.
Gunicorn
request
gunicorn 이란 python Server 를 배포하기위해서, 사용되는 WSGI 중에 하나입니다.
gunicorn
python Server
WSGI
다양한 모드(sync, gthread, gevent, tornado, eventlet) 들을 통해 다양한 경우를 지원을 해준다는 장점이 있어서, 많이들 사용하는 WSGI 입니다.
모드(sync, gthread, gevent, tornado, eventlet)
https://docs.gunicorn.org/en/stable/
예전에 딥러닝 모델을 API 로서, 올리는 과정에서 gunicorn 을 활용하였습니다.
API
그런데, 생각보다, 성능이 기대한 만큼 처리를 하지 못하고, 리퀘스트가 늘어나면 어느정도 에서는 엄청 느려진다는 것을 볼 수 있었습니다.
물론, 딥러닝연산 이 많은 CPU 연산량 이 필요한 작업이 맞지만, 어느정도 한계가 느껴진다는 것을 느낄 수 있었고,
딥러닝연산
CPU 연산량
process(worker) 를 늘릴수록, 기대한 만큼의 수치가 나오지 않는다는 것 또한 확인할 수 있었습니다.
process(worker)
물론, 제가 Gunicorn 의 내부 알고리즘을 전체를 다 분석을 할 수도 없었고, 당시 할당받은 서버의 스펙내부에서 최대한 성능을 이끌어 내고 싶었기에, AB(Apache Benchmark)test 를 활용하여서, 가장 좋은 결과가 나오는 경우를 찾아내었지만,
AB(Apache Benchmark)test
process
calculation time
우선, gunicorn 에 대해서, 완벽하게 제가 알지 못합니다. 각각의 경우에 대한 실험 또한, 간단하게 만든 실험 파일들을 기반으로, gunicorn 의 환경설정 값을 변화시켜서 만든 것일 뿐이고, 다음번에 돌렸을 때에는, 언제나 다른 결과가 나올수 있으며, 아래에 나온 결과 값들도 정확한 것은 아닙니다. 하지만, 대체적으로 worker x thread == 한번에 처리가능한 request 의 수 가 이론적으로 생각했을 때와는 달라질 수 있다는 것을 염두해주시고, 봐주시면 감사하겠습니다. 저는 개인적으로, 딥러닝을 올렸을 때, 어떻게 하면 효율적으로 할 수 있을까에 대해서, 생각하였는데, sleep time == 내 서버(API) 가 대략적으로 필요한 시간이라 생각해주시고, 본인의 환경에 대해서 생각해주세요. (물론 CPU 연산량으로 인한 처리속도 지연도 생각해보셔야합니다.)
우선, gunicorn 에 대해서, 완벽하게 제가 알지 못합니다.
각각의 경우에 대한 실험 또한, 간단하게 만든 실험 파일들을 기반으로, gunicorn 의 환경설정 값을 변화시켜서 만든 것일 뿐이고,
다음번에 돌렸을 때에는, 언제나 다른 결과가 나올수 있으며, 아래에 나온 결과 값들도 정확한 것은 아닙니다.
하지만, 대체적으로 worker x thread == 한번에 처리가능한 request 의 수 가 이론적으로 생각했을 때와는 달라질 수 있다는 것을 염두해주시고, 봐주시면 감사하겠습니다.
worker
thread
한번에 처리가능한 request 의 수
저는 개인적으로, 딥러닝을 올렸을 때, 어떻게 하면 효율적으로 할 수 있을까에 대해서, 생각하였는데, sleep time == 내 서버(API) 가 대략적으로 필요한 시간이라 생각해주시고, 본인의 환경에 대해서 생각해주세요.
sleep time
내 서버(API) 가 대략적으로 필요한 시간
(물론 CPU 연산량으로 인한 처리속도 지연도 생각해보셔야합니다.)
https://docs.gunicorn.org/en/stable/settings.html#worker-class
sync 의 경우, 직관적으로 처리되고 있는 것을 확인할 수 있으나, 그만큼 연산량 + 메모리 추가로 인한 응답 시간 이 많이 커지고 있다는 것을 확인할 수 있었음.
sync
응답 시간
CPU 연산량이 많은 딥러닝 API 에서는 gthread 가 비교적 제일 좋은 선택지라고 생각하며,
CPU 연산량이 많은 딥러닝 API
gthread
worker=1 일때에는, multi thread 를 해도, docs에 있는 설명과 비슷하게 리퀘스트가 균등하게 처리된느 것을 확인할 수 있었으나, worker 와 thread 가 늘어날 수 록, 예상과는 맞지 않는 모습이 보여 아래와 같이 실험을 하였습니다.
worker=1
multi thread
r -> client가 request 날린 총합 개수, 기본값 800
r
A, B, C -> 각 프로세스(=worker)당 리퀘스트를 받은 숫자를 큰수대로 나열한 것
client 16개 가 동시에 요청을 날리는 경우이다.
client 16개
worker = 2
worker = 3
위의 결과를 기반으로 볼 때, 생각보다는 multi worker 를 통해서, 많은 양의 request 들을 공평하게 나누지 못하고 동시 request , request 처리시간 에 따라서 프로세스의 사용비율이 달라진다는 것을 확인할 수 있었습니다.
위의 결과를 기반으로 볼 때, 생각보다는 multi worker 를 통해서, 많은 양의 request 들을 공평하게 나누지 못하고
multi worker
동시 request , request 처리시간 에 따라서 프로세스의 사용비율이 달라진다는 것을 확인할 수 있었습니다.
동시 request
request 처리시간
worker process
동시 request 수가 적거나 , request 처리시간이 클경우 이 두가지 경우에 대해서는
동시 request 수가 적거나
request 처리시간이 클경우
workerxthread 의 수만큼 동시에 request 를 처리하는 것이 아닌, 일종의 노는 process 가 존재하여, 특정 process 에 대해서 request 가 몰리는 경우가 생길 수 있어,
worker=1 일때에 비해서, 메모리 추가 양 대비, 성과가 별로일 수 있으니, 이를 참고하시면서, 개발해주시면 좋겠습니다.
The text was updated successfully, but these errors were encountered:
gunicorn_test - app.py - wsgi.py - client.py - run_server.sh - run_client.sh
app.py
import os import time from flask import Flask, request app = Flask(__name__) print("Start Server PID : {}".format(os.getpid())) count = 0 sleep_time = 2 @app.route('/a/<name>') def a_func(name): global count count += 1 # client_ip = request.remote_addr # print("a/ request Process PID : {}, ip:{}, name : {}".format(os.getpid(), client_ip, name)) time.sleep(sleep_time) print("a/ request Process PID : {}, count : {}".format(os.getpid(), count)) return name @app.route('/b/<name>') def b_func(name): global count count += 1 # client_ip = request.remote_addr #print("b/ request Process PID : {}, ip:{}, name : {}".format(os.getpid(), client_ip, name)) time.sleep(sleep_time) print("b/ request Process PID : {}, count : {}".format(os.getpid(), count)) return name @app.route('/c/<name>') def c_func(name): global count count += 1 # client_ip = request.remote_addr # print("c/ request Process PID : {}, ip:{}, name : {}".format(os.getpid(), client_ip, name)) time.sleep(sleep_time) print("c/ request Process PID : {}, count : {}".format(os.getpid(), count)) return name
client.py
import random import time import requests all_request_count = 800 per_request_count = int(all_request_count / 16) if __name__ == '__main__': abc_list = ["a", "b", "c"] for i in range(0, per_request_count): one_of_abc = random.choice(abc_list) start_time = time.time() response = requests.get("http://127.0.0.1:5008/{}/{}".format(one_of_abc, one_of_abc)) end_time = time.time() print("taken time : {}".format(end_time - start_time)) # print('11111')
wsgi.py
""" gunicorn 을 실행시키기 위해서, 서버를 배포하기 위해서 필요한 파일입니다. """ from app import app as application if __name__ == "__main__": application.run()
run_client.sh
python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py & python client.py &
run_server.sh
gunicorn -k gthread --workers=1 --threads=4 --timeout 60 --bind 0.0.0.0:5000 wsgi # 경우에 따라서, 수정함이 필요.
Sorry, something went wrong.
No branches or pull requests
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
자체의 내부 알고리즘이process
와calculation time
이 늘어 날때마다, 어떻게 달라지는지는 확인하지 않았기에, 이를 대략적으로 확인하고 싶어 이를 실험하기로 하였습니다.실험전 알고들어 가야하는 부분
gthread 만 선택해서, 한 이유
https://docs.gunicorn.org/en/stable/settings.html#worker-class
sync
의 경우, 직관적으로 처리되고 있는 것을 확인할 수 있으나, 그만큼 연산량 + 메모리 추가로 인한응답 시간
이 많이 커지고 있다는 것을 확인할 수 있었음.CPU 연산량이 많은 딥러닝 API
에서는gthread
가 비교적 제일 좋은 선택지라고 생각하며,worker=1
일때에는,multi thread
를 해도, docs에 있는 설명과 비슷하게 리퀘스트가 균등하게 처리된느 것을 확인할 수 있었으나,worker
와thread
가 늘어날 수 록, 예상과는 맞지 않는 모습이 보여 아래와 같이 실험을 하였습니다.실험에 대한 설정
r
-> client가 request 날린 총합 개수, 기본값 800A, B, C -> 각 프로세스(=worker)당 리퀘스트를 받은 숫자를 큰수대로 나열한 것
client 16개
가 동시에 요청을 날리는 경우이다.worker = 2
worker = 3
실험 결과에 대한 정리
동시 request
의 수의 증가에 따라서, 비교적worker process
들이 공평하게request
를 처리하고 있는 것을 확인할 수 있습니다.request
처리시간이 감소함에 따라서, 비교적worker process
들이 공평하게request
를 처리하고 있는 것을 확인할 수 있습니다.동시 request 수가 적거나
,request 처리시간이 클경우
이 두가지 경우에 대해서는worker
xthread
의 수만큼 동시에request
를 처리하는 것이 아닌, 일종의 노는process
가 존재하여, 특정process
에 대해서request
가 몰리는 경우가 생길 수 있어,worker=1
일때에 비해서, 메모리 추가 양 대비, 성과가 별로일 수 있으니, 이를 참고하시면서, 개발해주시면 좋겠습니다.The text was updated successfully, but these errors were encountered: