inference가 10분정도 걸리는 api를 생성했다.
api구성은 web application framework로 flask를 사용하고, WSGI서버로 gunicorn을 사용했다.
들어가기 전 상황
문제 발생)
api를 11번 동시호출 하니, 10분이 걸리던 api가 하나당 1시간이 넘게 걸리면서 timeout 에러가 발생했다.
cpu를 나눠써서 시간이 너무 오래걸린다....
먼저 해당 인스턴스는 gcp의 n2, 2코어 8gb 메모리, intel cascade lake이기 때문에
4코어로 올려보았다.
상세 스펙은 n2, 4코어 16gb 메모리, intel cascade lake
당연하게도 속도는 감소해서 timeout에러는 나지 않았지만,
11번 동시호출에 대해 하나의 api호출이 40분이 걸리는건 여전히 문제였다.
그래서 gunicorn의 워커와 쓰레드를 조정해보았다.
기존에는 worker1, thread10개로 설정했었다.
Gunicorn Worker & Thread
gunicorn의 worker란?
gunicorn은 master process와 worker process로 구성되어 있다.
gunicorn이 실행되면 그 프로세스가 이미 master process이고, fork를 사용해서 설정한 worker 수대로 worker process를 생성한다.
worker process의 default 개수는 1이다.
master process는 worker process를 관리하고,
worker process는 작성한대로 웹어플리케이션을 실행한다.
공식문서에서 추천하는 worker의 개수
(2~4) x $(NUM_CORES)
gunicorn의 thread란?
각 worker마다 가질 thread를 의미한다.
파이썬에는 GIL(Global Interpreter Lock)이란게 존재해서, 하나의 process내의 여러개의 thread가 병렬적으로 실행될 수 없다.
따라서 CPU core와 thread가 여러개여도, 각 호출에 대해 CPU를 하나만 사용한다.
따라서 수행하는 작업이 CPU bound job일 때는 thread를 늘려주는 것이 의미가 없다.
하지만 I/O bound job을 사용할 때는 thread를 늘려주는 것이 유리하다.
이유는 어떤 thread가 I/O를 수행할 때는 block이 되는데, 이 때, GIL을 반환한다.
그럼 반환되어 그동안 다른 thread가 실행 될 수 있기 때문이다.
공식문서에서 추천하는 thread의 개수 (worker 개수와 동일)
(2~4) x $(NUM_CORES)
정리
CPU bound 작업을 위한다면 worker process를 늘리고,
I/O bound 작업을 위한다면 thread를 늘린다.
만약 -w 4 --threads 4 옵션을 gunicorn에서 사용하면, 한번에 16개의 IO를 처리할 수 있다.
주의
CPU bound job은 물리적 코어 수, IO bound job은 논리적 코어 수에 의존한다.
만약 물리적 코어 수 대비 비교적 작은 수로 worker를 설정하면 오버헤드가 발생한다.
Gunicorn gevent 옵션
gunicorn에서는 k옵션이 있다.
worker class의 타입을 지정하는 옵션으로 default는 sync이다.
이걸 async방식의 gevent를 사용하면 더욱 성능을 향상시킬 수 있다.
참고) gevent, thread, worker 조정을 통한 성능 비교
수행 결과
다른 게시물에 게시
2021.12.01 - [분류 전체보기] - gunicorn worker & thread 설정(2) - 성능 테스트
gevent로 고정
4core cpu를 사용하면서 worker&thread 설정한 내용
16, 16 -> 어플리케이션 실행 단계에서 timeout. 초기 실행시킬 것들이 있는데 timeout 시간을 기존과 똑같이 뒀더니 바로 걸림. 이후에 타임아웃 시간은 수정하지 않음.
8, 8 -> [CRITICAL] WORKER TIMEOUT (pid:379) 뜨고,
Error: socket hang up 에러뜨고,
Calling `Model.predict` in graph mode is not supported when the `Model` instance was constructed with eager mode enabled. Please construct your `Model` instance in graph mode or call `Model.predict` with eager mode enabled 에러뜨고,
그러다 마지막껏만 성공함ㅠ 엉엉ㅜ
'mlops, devops' 카테고리의 다른 글
gunicorn worker & thread 설정(2) - 성능 테스트 (0) | 2021.12.01 |
---|---|
gunicorn의 gevent란? (0) | 2021.12.01 |
python warning (0) | 2021.11.30 |
GCP Connection via Cloud Identity-Aware Proxy Failed error (0) | 2021.11.26 |
docker 내 conda 환경이 안맞는 이슈 (0) | 2021.11.19 |