공부/컴퓨터
[python] Flask로 app.run() 실행시 두개의 Process가 뜨는 문제
찬
2021. 2. 25. 00:18
반응형
오늘도 트러블슈팅
문제 상황
- AI 엔진을 띄우면 GPU를 사용하는 Process가 2개가 뜨면서 GPU RAM을 쓸데 없이 두번 먹는 현상.
문제 분석
- 웹 서버를 띄울때 Flask를 활용하고 있음
- "main" 에서 model을 로딩하면 최초 실행된 python process가 GPU 메모리를 1.5GB 정도 사용
- 이후 Flask의 app.run 을 실행.
- Flask의 app.run을 실행하면 python process가 1개 더 뜨면서 GPU 메모리를 1.5GB 정도 사용
- 아마도 app.run 실행시 python process 가 fork() 되면서 GPU메모리까지 clone 되는것으로 예측??
문제 확인
main
부분에서 바로 model을 로딩하지 않고, 바로 Flask의 app.run을 실행- 최초 predict request시 model을 한번만 로딩하도록 코드 수정
- nvidia-smi 확인시 /usr/bin/python3.7 단 1개만 GPU를 사용하는것을 확인
해결법 제안 ( 1번 방식 )
- Flask 사용시 app.run 이전에 최대한 메모리 사용을 하지 않도록 코드 작성 필요
- Flask 의 Context가 초기화 된 직후, Flask process에서 모델을 로딩하도록 수정.
- 예1> 코드에 model이 null 인 경우에만, 초기화 ( 아래 그림 )
- 예2> Flask의 annotaion 중 app.before_first_request 를 사용하여, 최초 requset 직전에 GPU 사용하는 모델을 로딩하도록 수정 필요
진짜 문제 상황
- 해당 문제는 Flask에서 사용되는 WSGI(Web Service Gateway Interface)와 관련이 있는 듯 하다.
- Werkzeug 라는 놈은 개발 편의를 위해 dev mode인 경우, code의 변경을 감시해 새롭게 서버를 띄우는 기능이 있는듯 하다. ( 즉, 이전에 process가 fork 된다고 이야기 했던것은 틀렸고, child process로 같은 프로세를 하나 더 실행 시키는 형태 였음 )
- 관련 링크 1 : https://stackoverflow.com/questions/25504149/why-does-running-the-flask-dev-server-run-itself-twice
- 관련 링크 2 : https://github.com/pallets/werkzeug/blob/54acdd16b247f7037482737e72ec52fc6d50a78d/src/werkzeug/_reloader.py#L160-L185
- 즉, Flask를 사용하여 서버를 띄우면, 두개의 Process가 뜨게 된다.
- 첫번째 프로세스 : Flask 역할 ( Http Request, Response를 처리 )
- 두번째 프로세스 : Flask 관련 코드가 변경되면 자동으로 dev서버를 reload 해 주는 역할
진짜 문제 해결 ( 2번 방식 )
- 그래서 어쩌면 되냐고? auto reload 모드를 끄면 된다고 한다.
- python 코드 안에서 설정하기 :
app.run(use_reloader=False)
- 하지만,
pyhon web.py
와 같은 방식으로 실행시키는 경우 코드가 두번 실행되는 이슈가 있으니,flask run --no-reload
방식으로 실행시키라고 이야기 하고 있다. - 관련 링크 3 : https://flask.palletsprojects.com/en/1.1.x/server/
그럼 뭘 써야 할까?
- 개발을 할 때는 코드가 변경되었을때 바로바로 업데이트되면 편하니깐, Debug를 켜두고 1번 방식을 적용하면 좋을것이다.
- 실제로 production에서 사용할꺼면, debug 모드도 끄고, reload도 끄는게 좋을 테니깐 2번 방식을 적용하면 더 좋을것이다. 물론 2번 방식을 적용할때 1번 방식을 같이 적용해도 괜찮을것이다.
반응형