Closed kh3654po closed 1 year ago
tensor shape 이 1280,1000 이면 조금 큰 것 같은데, 사용한 모델이 어떤거야? 정애에게 전달받은걸 사용 중?
네 교수님 현재 xavier2 장치에서 mobilenetv1, mobilenetv2, inceptionv3 를 먼저 load해두고, flask 서버를 on 한 후 /mobilenet 라우트로 웹 request가 오면, mobilenet 모델을 추론하는 코드를 구성하여 테스트 중에 있습니다.
모델을 3개 미리 로드하고, flask서버까지 띄우다보니 메모리가 부족해 보이는 상황으로 파악됩니다.
코드중에 메모리 제한을 하는 코드가 있어 메모리 사이즈를 키워 다시 테스트를 진행하고있습니다.
오케이. 잘하고 있다. 하나씩 해결을 해보자. Flask 에서 바로 해결이 가능하다면 가장 이상적일것 같기는 하다.
테스트 결과 MobileNetV1 모델을 load하고 Flask를 배포하는 것이 정상적으로 동작함을 확인했습니다.
로컬에서 curl request에 대해서 get 200 http response를 확인했고 추론 유사도 결과값도 잘 나오는 것을 확인했습니다.
여러번 curl로 요청했을 때에도 추론 동작을 정상적으로 함을 알 수 있었습니다.
다만 모델 3개를 load해놓고 추론하는 것에서 메모리 관련 이슈가 발생합니다. 이부분을 해결하기 위해 각 process별로 mobilenet, mobilenetv2, inceptionv3를 하나씩 배포해두어야 할지 고려중입니다.
오케이. 잘했다. 소요시간은 대략적으로 얼마나 되는것같아?
curl 에서 time 명령어를 통해 확인해본 결과, 첫번째 추론 요청에 대해서 cold start가 발생함을 확인했습니다. 두번째 요청에서 부터는 매우 빠른 응답 속도를 확인했습니다.
오케이. 첫번째 요청은 확실히 모델로딩 등에 대한 시간이 포함되는듯 하네. 이건 그냥 무시해도 되겠다. 그런데 후반부의 요청도 200 msec 정도 소요가 되네? 지금 구현은 요청 받은 플래스크 프로세스 안에서 바로 파일을 읽어와서 요청 처리를 하게 되는거지? 요청 처리 단에서 소요되는 서버 단 시간을 확인해 볼래? 기억에 추론 시간은 수십 밀리초 정도여서 실제로 파일을 읽는데 추가적인 시간이 다 소모가 되는지 확인을 해보고 싶어. 그리고 결국은 curl 을 통해서 입력도 post 하는 방식으로 해야 할것 같기도 하고.
네 한번 확인해보겠습니다. 현재 nano에서도 테스트 해보고있는데 작동이 안돼서 확인해본 결과 gnome-shell 의 메모리 누수 문제를 발견했습니다. 검색해보니 예전부터 있던 버그로 Ubuntu 18.04 버전에서도 해결이 안됐다고 합니다. 일시적인 해결책으로는 gnome-shell을 재시작하는 거라고 합니다.
-nano 장치에서 htop 결과
석현아 해당 이슈 잘 찾았다. 그런데 ubuntu 18.04 를 사용하고 있다면 꽤나 옛날 버전이네. 작년에 실험을 했으니 ubuntu 를 쓴다면 20 혹은 22 버전 정도는 사용해도 괜찮을것 같은데.. 다른 장비도 ubuntu 18 인지 확인해주고, 운영체제를 업그레이드 하는건 어떨런지 한번 고려해보자.
현재 엣지 장비 tx2, nano, xavier rpi, master 모두 ubuntu 18.04 버전으로 통일되어 있는 상태입니다. (nvidia jetpack version 32.6.1) 엣지 장비의 ubuntu 버전을 20 혹은 22로 업데이트하려면 jetpack 버전을 업그레이드 해야하는 상황입니다. 모든 장비의 버전을 업그레이드 하려면 기존 장비에 데이터 백업 후 각각 장비마다 업그레이드 또는 재설치를 진행해야해서 시간 소요가 조금 많이 될 것 같습니다. 그리고 업그레이드 후에 어떤 이슈가 발생할지도 지켜봐야하는 고려사항이 있습니다.
현재 jetpack 최신 버전은 32.5.1이고 ubuntu 20.04를 지원하는 것을 아래 링크를 통해 확인할 수 있습니다. https://www.stereolabs.com/blog/nvidia-jetson-l4t-and-jetpack-support/
요청처리 단에서 소요되는 시간을 확인해봤습니다. 첫번째 요청에서는 6.8초 정도 소요가 됐고, 두번째 요청부터는 0.17초 정도 소요됐습니다.
전체적인 시스템의 업그레이드가 필요하겠네. 언제가 하기는 해야할텐데, 지금은 아닌것 같기는 하다. 우선 나노에서 여러 버그들 피해서 진행이 되게끔 해보자.
석현아. 저기서 보이는 time 은 어디에서 측정된 시간이야? 실제로 추론되는 서버에서 inference 의 시간 만인지, 파일을 불러오는 시간이 포함되었는지 궁금해.
저기서 time은 추론되는 서버에서 inference의 시간만 입니다. 파일은 미리 불러오고 요청이 들어왔을때 해당 파일을 바로 inference 합니다. 코드 일부를 같이 올리겠습니다.
오케이. 그렇다면 실제 추론에 240 msec 정도가 소요된다는건데, gpu 를 사용중인지 확인해볼까? 시간이 오래 걸리는것 같아.
jtop을 통해서 요청을 했을때 gpu사용량을 확인해봤는데 gpu가 0에서 466까지 증가하는것을 확인했습니다. 사용시간이 너무 짧아 사용될때 사진은 찍지못했습니다.
그렇다면 이전의 실험결과 (수십 밀리초) 와는 차이가 너무 많이 나는것 같은데.. 이전 실험 환경에서 사용한 코드와 비슷하게 사용을 하고 있는건지 확인을 해주면 좋을것 같아.
이전 실험결과를 볼 수 있는 이슈가 따로 없는거 같은데 이전 실험 기록을 볼 수 있는 곳이 있을까요?
정애가 제공을 해주면 좋을것 같아. 실험자료는 전에 공유한 pdf 에 있을텐데 코드는 따로 줘야할듯.
넵 정애님한테 요청해서 받고 확인해보겠습니다
이전 환경 코드를 확인하고 실행해본 결과 추론시간은 같은것으로 나왔습니다. 코드도 같았습니다.
기존 코드 추론 시간 (inception_v3, 1개의 이미지) : raw_image_classification_inference.py
기존 코드 추론 시간 (inception_v3, 3개의 이미지) : raw_image_classification_inference.py
현재 코드 추론 시간 (inception_v3, 1개의 이미지)
다만 기존 코드는 1000개의 이미지를 추론한다고 생각해 total_task_inference_time / 1000을 해 inference_time(avg) 값이 나왔습니다. 이전의 수 밀리초였던 것이 이 때문이었던거같습니다. 실험은 1개의 이미지만 추론한것으로, 두 코드의 추론 시간은 비슷했습니다.
콜드스타트 비교를 위해 1개의 이미지만 추론할 때와 3개의 이미지를 추론할 때도 실험해봤습니다. 8.85에서 9.54로 증가하는데 제 코드로 추론한 결과와 비교해보면 큰차이가 없는 것을 볼 수 있습니다.
이 데이터를 봐서는 2개의 시간이 비슷하다는 생각이 들지는 않는데. 몇가지 확인하고 싶은건 기존 코드에서 1000 장 이미지를 추론할때 배치 사이즈는 얼마인지? (inception_v3, 1개의 이미지), (inception_v3, 3개의 이미지) 가 무슨 의미인지.
1000 장을 추론했을때 8.8 초 가량과 아래 curl 의 경우 1개 이미지만 추론하는데 260 msec 이 소요된것 아닌가?
설명이 부족했던거 같습니다. 두 코드 다 배치사이즈는 1입니다. 위의 첫번째와 두번째 사진은 기존 코드를 실행한 결과인데 첫번째 사진은 이미지파일을 하나만 추론한 결과이고 두번째는 3개의 이미지파일을 추론한 결과입니다. 세번째 사진은 제가 구현한 코드에서 한 장의 이미지 파일을 추론한 결과이고 여러번 시도했을 때는 추론 시간이 줄어든 것을 볼 수 있습니다.
1개의 이미지 파일을 추론했을 때 시간은 8.85초(기존), 8.44초(제가 구현한 코드)로 비슷하고 콜드 스타트 이후에 시간도 비슷한지 보고자, 기존코드에서 3장의 이미지 파일을 추론한 결과도 확인했습니다(두번째 사진). 1장을 추론했을 때와 3장을 추론했을 때의 차이가 0.6초 정도로 콜드 스타트 이후에 0.3초정도 걸리는 것을 볼 수 있습니다. 이는 0.26초와 비슷한 값입니다.
inference_time(avg)가 몇 밀리초로 나온 이유는 추론한 이미지 개수와 상관없이 1000으로 나누고 출력해서 입니다.
아. 오케이. 설명이 많이 부족했네 ㅎㅎ 3장을 처리했을때는 나머지 2장의 실행 시간을 파악하기 위함이었구나. 그렇다면 2개의 시간을 따로 측정을 해서 보여주는것도 좋았겠다. 그런데 계속 걸리는게 전에 정애가 실험해서 이야기한 성능과 차이가 굉장히 많이 나는게 계속 걸린다. @jungae-park 전에 xavier 에서 Inception V3 추론 성능 확인 부탁해. 배치 사이즈 1로 했을때 이미지 하나당 평균 추론 시간이 얼마였어? 지금 석현이가 실험한것과 차이가 나는듯 한데, 확인을 해야 할듯 해.
xavier 장비에서 inception v3 모델에 대해 raw image 1000장을 batch size 1로 추론하였을 때, 이미지 하나 당 평균 추론 시간은 0.13초 였습니다.
tfrecord 와 raw 이미지 처리 성능에 차이가 있었던 거였구나. 해당 표를 보니 큰 차이였다고 보기는 힘들겠다. 정애야 그런데 지난주 부터 계속 석현이 실험에서 관찰되는 성능과 정애가 과거에 했던 실험과의 시간 차이를 계속 이야기를 했었잖아. 그렇다면 정애가 먼저 실험을 한 입장에서 내용을 확인해서 내가 놓치고 있는 부분을 이야기 해줬으면 서로 시간을 절약할 수 있었을것 같아. 이런 부분은 조금 더 신경을 써주면 좋을것 같아. 그렇게 서로 실험 결과 보고 지식 공유하려고 이슈 사용하고 슬랙 사용하는 거니까.
수치를 확인해보니 큰 차이가 없어서 코드가 정상 동작하는것 같습니다. 현재 nano, tx2에서는 동작하지 않아서 이 점을 해결해보겠습니다
응 석현아 그렇게 하자. nano, tx2 에서는 어떤 문제인거야? 오전에 같이 이야기 나눠봐도 괜찮겠다.
수치 확인 등 nano1, tx2 장비 접속 문제가 있어서 저랑 해결하고 있습니다.
장비접속 확인 방법 등을 석현씨에게도 전달하였고, 계속 실험 가능하도록 해결 완료하였습니다.
클라이언트에서 요청해서 어느정도 걸리는지와 실제 추론시간을 측정해보았습니다. 실제 추론시간과 요청후 받는데 까지 걸리는 시간의 차이가 0.1초 내외로 나옵니다. 측정방법은 time 명령어를 사용했습니다.
xavier
- mobilenet v1
mobilenet v2
inception v3
nano1
- mobilenet v1
오케이. 이정도면 그래도 충분히 예상 가능한 수준인듯 하다.
교수님 tx2 장비에 이슈가 생겨 공유드립니다. 처음 발견했던 RPC failed; curl 56 GnuTLS recv error (-9) 원인을 찾아보니 네트워크가 불안정해서 였습니다. tx2 장비에 ping 테스트 결과 네트워크가 연결되었다 끊겼다 했습니다.
이에 usb를 사용하여 tx2 장비에 직접 코드를 옮겨 테스트 해보려했지만 flask 모듈을 설치하는 과정에서 마찬가지로 네트워크 이슈가 나왔습니다. flask가 처음에는 설치가 시작되었다가 ReadTimeoutError가 발생합니다. 현재 tx2 테스트는 진행이 힘들것 같습니다.
ping 메시지를 보니 확실히 문제가 있어보이네. 해당 서버를 재부팅 하거나 해도 비슷한 문제가 발생해? 해당 장비만 특별히 에러가 날 이유는 없어 보이기는 하는데. 아이피 충돌등의 문제가 있는지도 봐볼래? 이정도 이슈라면 해결이 가능할것 같아. 최후의 수단으로는 운영체제 재 설치가 되어야 할수도 있지만.
교수님 tx2 장비의 네트워크 문제를 해결해 보려고 했지만 지금까지 해결하지 못해 우선은 작동이 잘되는 xavier와 nano에 포아송분포를 이용해 추론을 요청하는 라운드로빈 스케줄러 구현을 먼저 하겠습니다.
아이피 충돌의 문제인지 확인해 봤습니다. 다음 링크에서 충돌 확인 방법을 찾아 확인해 보았지만 아이피 충돌 문제는 아니었습니다. 출력 결과값이 1이면 충돌 0이면 충돌이 아닌데 0이 출력되었습니다.
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=zezegg123&logNo=220921190257
이 외에도 서버 재부팅과 네트워크매니저 재시작도 시도해보았지만 역시 실패했습니다.
다른 장비와의 차이점이라면 연결된 네트워크가 5G이냐 아니냐였습니다. nano와 xavier2가 edge-k8s_5G에 연결되어있는 반면에 tx2는 edge-k8s_5G를 찾지 못해 edge-k8s에 연결되어있습니다. 현재 작업이 진행되지않아 우선적으로 스케줄러를 구현하고 모델을 추가하는 방향으로 작업을 진행하고 후에 다시 tx2 장비 테스트를 시도해보겠습니다.
전에 클라이언트에서 추론 요청 후 응답 시간을 측정했을 때 잘못된 방법으로 측정한것 같습니다. xavier 장비에 추론을 요청해야 한다면 master 장비에서 curl 요청을 보냈어야 했는데, xavier 장비 즉 같은 장비에서 curl 요청을 보냈습니다. 어제 이슈에 남긴글에는 0.1초 차이라하였지만 master 장비에서 다시 측정해보니 추론시간 0.14초 요청후 응답받는 시간 평균 0.5초 정도로 0.3~0.4초정도의 차이가 보였습니다. 이 정도의 시간차이는 괜찮을까요?
응 석현아. 그렇게 하자. tx2 는 나도 내일 같이 한번 봐줄께.
석현이가 이야기한대로 마스터 노드에서 엣지 장비로 요청을 보내는게 맞아. 와이파이 망이라 그런지 시간이 오래 걸리기는 한다. tx2 도 그렇고 네트워크 성능이 제한되는것 같은 생각이 든다. 어쩌면 tx2 는 지금까지 계속 저런 상태였을것 같기도 하고.. 라우터를 더 좋은것으로 바꾸던지 유선 연결등을 고려해봐야 할수도 있겠다. 내일 같이 한번 봐보자.
네 알겠습니다!
현재 xavier 장비에 서버를 열고 master 장비에서 추론을 요청하는 코드를 구현해 테스트 해보았습니다. 현재 코드는 호스트네임과 포트번호, 추론을 요청할 모델을 명령행 인자로 받으면 해당 서버에 추론을 요청하고 추론시간을 결과로 리턴받고 출력합니다. 추론할 모델은 따로 입력하지 않으면 mobilenet v1, mobilenet v2, inception v3 모두를 추론합니다. 이번 코드는 요청과 추론이 제대로 동작하는지 확인하기위한 간단한 동작방식을 가지고 있습니다. 여기서 발전해 나가면 될것같습니다.
tx2 장비에서도 코드가 제대로 동작하는것을 확인했습니다. 네트워크 속도가 개선돼서 추론시간과 요청해서 결과값을 받는 시간 사이의 차이가 0.1~0.15초 정도가 되었습니다.
쓰레드를 이용해 병렬로 요청을 보낸 결과입니다. 서버에서 들어온 요청에 각각 인덱스를 붙이고 해당 인덱스와 시작 및 종료 했을 때 시간을 출력해 보았습니다. 요청처리 완료 순서가 들어온 순서와 다른것으로 보아 flask에서 병렬적으로 요청을 처리하는 것 같습니다. 추가적으로 종료시간을 보고 추론도 병렬로 실행 되는것을 알 수 있었습니다. 아래 사진에서 [1]과 [6]의 시작시간을 보시면 0.05초정도의 차이가 나는데 종료시간을 보시면 0.02초 차이가 납니다. 이전의 데이터에서 추론하는데 걸리는 시간이 0.15초 였던것에 비해 차이가 거의 없어서 추론하는데도 병렬실행했다고 판단했습니다.
요청처리 시작시간
요청처리 종료시간
추가적으로 마스터에서 출력된 결과 입니다. 병렬적으로 실행되다다보니 추론시간(아래 사진의 inference time)이 0.15에서 1.6초 정도로 10배정도 느려졌습니다.
간단한 스케줄러를 구현 해봤습니다. xavier2, tx2 장비에 mobilenet v1, mobilenet v2, inception v3 추론 요청을, nano1 장비에 mobilenet 추론요청을 받는 서버를 띄우고 스케줄러에 mobilenet v1, mobilenet v2, inception v3 요청들이 들어오면 각 장비에서 요청 받을 수 있는 모델에 따라 라운드 로빈으로 요청을 보내는 스케줄러입니다.
예를 들어 스케줄러에 mobilenet v1, mobilenet v1, mobilenet v1, inception v3, mobienet v2, inception v3 순으로 요청이 들어오면 각각의 요청은 xavier2, tx2, nano1, xavier2, xavier2, tx2 이렇게 요청이 전달 됩니다.
현재까지 각 장치의 부하를 테스트하면서 알아낸점을 공유 드리겠습니다.
오케이. 석현아 그렇다면 확실히 여러 요청들을 동시에 보낼 경우 해당 요청들이 동시에 처리가 되는것 같기는 하네. 그런데 이런 상황에서도 예를 들어 10개의 요청을 동시에 보낼 경우에도 마지막에 보내진 요청 뿐만 아니라 가장 처음에 보내진 요청도 똑같이 오래 걸리는 거지? 왠지 여러개의 요청이 동시에 들어올 경우에 엣지 장비에서 여러 모델을 context switching 해가면서 동시에 모든 요청을 처리하는 것일수 있겠네. 같이 디버깅을 한번 해보자.
오후에 추가적으로 여러 쓰레드 상에서 확인을 해봤는데, flask 서버에서 보이는것과 비슷하게 보이네.
하나의 프로세스에서 50개의 쓰레드를 만들어서 시간을 찍어보면 모든 쓰레드가 4~5초 정도 소요가 되는것으로 나오고, 둘이 같이 봤던 실험결과와 유사한것 같아. 그런데 2개의 프로스세를 만들고 각각의 프로세스에서 50개의 쓰레드를 만들어서, 총합 100개의 쓰레드로 동작하게 했을때도 각 요청은 4~5초 정도에 완료가 되네. 즉, 현재 xavier 상에서 자원이 프로세스 단으로 할당이 되는것 같아. 이런 부분도 흥미로운 탐구거리이기는 한데, 주요 주제에서 벗어날것 같아서..
우선은 지금 처럼 thread 로 돌리지 않고, 각각의 요청을 process 단에서 처리가 되게끔 해보면 어떨까 싶어. flask 에서 multi-thread 사용하지 않고 프로세스로 구동해보려고 아래 링크를 찾아보기는 했는데, 성공은 안되었네.
각 요청별/모델별로라도 독립적인 프로세스에서 동작이 가능할런지도 한번 확인해보자.
몇가지 실험한 상황을 정리해주면.
위 2개의 경우 유사한 시간을 보이는데,
2개의 프로세스로 분리 후에 실험을 진행하면 2개가 거의 서로 영향을 주지 않는것 같아. 확인 필요.
현재까지 테스트한 상황과 결과 공유드립니다.
테스트 상황
- xavier2 장비에 서버 두개를 띄우고 각각 포트 5001, 5002로 flask 요청을 받는다
- 5001포트로 mobilenet v1 요청 40개를 보내고 시간 측정
- 5001, 5002 포트에 mobilenet v1 요청 각각 20개를 보내고 시간측정
테스트 결과
- 40개를 한 서버에 보냈을 때 3~4초대 소요
- 20개를 각각 서버에 보냈을 때 2~3초대 소요
- 한 서버에 20개의 요청을 보냈을 때 2~3초대 소요
이것으로 보아 두개의 프로세스가 서로 영향을 주지않는것 같습니다.
flask를 이용해 엣지장비에 추론을 요청하는 모듈을 구현하고 있습니다. 현재 코드 구현을 다하고 테스트하기위해 xavier2 장비에 코드를 실행해 보는데 메모리 자원부족 에러인 ResourceExhaustedError가 떠서 원인 파악을 하고있습니다.