일지를 남기며
20~22년 석사 졸업, 22년 대기업 연구직 취뽀. 그런데 막상 돌이켜보니까 22년에 업무로 뭘 했는지 기억이 안나네, 그래서 아 주기적으로 기록을 남겨야겠다라고 마음먹고 이렇게 글을 쓰게 되었다. 이런게 있어야 나중에 이직하더라도 자기소개서에 쓸 내용이 있지 아니면 물경력 될 듯.
요즘 평생 직장 없듯이 언제든 좋은 환경의 근무지, 높은 연봉 제안을 받으면 빠른 이직 시대에 맞게 언제든지 내가 무엇을 했고, 무엇을 느꼈으며, 그 과정에서 무엇을 배웠는지 남겨야 겠다고 생각한다.
23년 1월
■ 현장에 설치된 레이저 포인터(White Line) Detection 과정을 수행하는 시스템 개발 프로젝트 착수
■ C# 또는 C++ language 선택 필요했다 (결론은 C++ 선택). → 초당 10 frame을 연산 처리하고, 동영상 저장이 필요한 작업이었기 때문에 Accuracy 보다는 Time이 중요했다(Time > Accuracy). 즉, Just-In-Time System. 그렇기 때문에 메모리를 직접 Handling 할 수 있는 C++ 선택했다.
■ 때로는 영상처리에서 Time과 Accuracy 중 어떤 것이 더 중요한지 갈린다. 이번에 진행했던 영상처리의 경우 Time이 무조건적으로 중요했기 때문에 적당한 Accuracy를 유지하며, 무조건적으로 Time이 초당 10 frame을 처리할 수 있도록 설계하는 것이 중요했다.
■ 이를 위해 CPU에선 Thread 처리 방법이 있었다. 기본적으로 프로그램은 위에서 아래로 Sequencial 방식으로 진행한다. 영상 처리를 수행하게 될 경우 2중 for loop가 여러 번 수행하게 될 것이고(이거는 빈번), 심할 경우 3중 for loop가 있을 수도 있다(이거는 최악!!).
■ 이럴 경우 초당 10 frame을 절대 수행하지 못하게 된다. 왜냐하면, 대표적으로 1920 by 1080 화면의 픽셀을 2중 for만 수행하는데 얼마나 많은 시간이 걸리겠는가? 상상만 해도 처리 후 나오는 이미지가 "버벅 버벅"할 것이다. 이를 보완하기 위해 Multi-Thread 개념을 도입하게 되었고, 전체 시스템을 부분 부분으로 나누어 각각의 Thread로 구성시켰다.
■ 이를 통해 기존의 Sequencial 코드를 병렬(Parraller) 처리 방식으로 변경하여 수행하도록 설계서를 작성했다.
■ 내가 맡은 부분은 L1으로부터 받는 PLC Data(Server 측)를 사용할 수 있도록 받아오는 1. Client 측 코드와 2. Client 측과 첫 번째 Thread를 연결하여 데이터를 유기적으로 받아올 수 있도록 환경 세팅 코드, 3. Basler Camera의 SDK를 활용한 Grab 코드, 4. 데이터 처리를 끝내고 추후 연구 개발 목적으로 데이터 Export 및 txt file로 저장시키는 코드, 5. Export 및 txt 파일을 긁어와서 MSSQL DataBase로 Insert 시키는 코드 개발을 담당했다.
■ 1번째를 위해 TCP/IP 설계 코드 개발 공부, https://easycode.tistory.com/19
■ 2번째를 위해 Shared Memory 개발 공부, https://easycode.tistory.com/24
■ 3번째를 위해 Basler의 Grab 및 Opencv 라이브러리 사용 및 코드 개발 공부, https://easycode.tistory.com/27
■ 4,5번째를 위해 Data 관리 및 개발 공부를 진행해야 됨을 알 계획했다.
23년 2월
■ TCP/IP의 경우 생각보다 굉장히 쉽게 코드를 완성할 수 있었다. 기본적으로 자체 Server를 만들어 Client와 통신 Test를 진행했고, 큰 이슈 없이 마무리할 수 있었다. 기본적으로 TCP/IP의 통신 구조만 안다면 쉽게 개발할 수 있다. 처음에는 초당 1번만 Client에 데이터를 날리려고 Sleep(1000)를 사용했지만, 추후에는 SetTimer()을 사용했다. 개인적으로 Client를 날리는데 Sleep을 통해 잠시 죽이는 것은 올바른 방향이 아니라고 판단했기 때문에 SetTimer을 통해 초당 2번 Event를 날리는 방식으로 변경했다.
■ Basler Camera의 경우 SDK 및 구글링을 통해 쉽게 Image를 Grab 하고 Opencv 라이브러를 사용해 Mat을 통해 이미지의 pixel data를 저장했다. 하지만, 이때 잠깐의 이슈(하루 정도) Visual Stduio를 쓰는 데 있어 외부 라이브러리를 사용하기 위해서는 dll 파일 저장 위치 설정과 Visual Stduio의 속성에서 path 설정을 할 필요가 있다는 것을 알 수 있었다.
■ 이러한 과정을 통해 2월 말경 Processor를 완성했지만 처리 속도가 매우 늦는 것을 알 수 있었다. CMD Log를 통해 디버깅 결과 우리의 의도인 Parraller 병렬처리가 아니라 구간만 나눈 Sequencial 방식임을 알았고, Thread 만드는 것에서 매우 잘못된 방향으로 가고 있다는 것을 알 수 있었다.
■ 이유는 Thread를 처음 만들어 보는 것으로, 각 Thread 내부에 While Loop를 넣지 않고, Main 문에 Thread 호출 및 이를 While Loop를 돌렸기 때문이다.
■ 결론적으로 Thread의 구성은 각 Thread는 While Loop를 기반으로 이전 Thread가 이후 Thread에게 "너 이제 실행해"라는 Signal을 날려야 되는 구성이어야 된다. 이를 통해 첫 번째 한 바퀴는 Sequencial 하게 움직이겠지만, 두 번째 바퀴부터는 Parraller 방식으로 움직이게 된다는 것을 알 수 있었다.
■ 당시, 고민했던 부분은 직접적으로 메모리 핸들링을 하다 보니 잘못된 Thread 설계로 인해 메모리 오류가 계속 발생했고, 이를 위해 mutex를 사용했다. 하지만, mutex는 프로세스의 전체적인 소요시간에 Long Time이 발생하기 때문에 사용하면 안 되는 개념 있었다. 이 대신 새로운 Semaphore 개념이 필요하다는 생각을 하게 되었다.
23년 3월
■ 2월의 실패를 경험 삼아 전체 구조 설계를 다시 들어갔다.
■ 초당 10 frame을 처리하기 위해 각 Thread 마다 넉넉잡아 16개(Total 16 frames)의 처리 공간을 만들기 시작했다. 이게 무슨 말이냐? 솔직히 나도 말로만 설명하니까 헷갈려 죽겠네. 그림으로 보면 아래와 같다.
■ 위의 그림과 같이 각 Thread의 구조를 변경했고, 레이저 포인터(White Line) Detection을 통한 실시간 영상 처리(Just-In-Time) 시스템 개발 시스템 뼈대를 재구성했다.
■ 이렇게 구성해서 Main에서 각 Thread를 불러와서 한 번만 실행시키면 각 Thread는 Sema Signal을 주고받으면서 각 Thread의 while()을 무한히 동작하고 있게 된다. https://easycode.tistory.com/25
■ 당시, 또 한 가지 고민했던 부분은 각 Thread에서 처리한 데이터들 특히, Arrray 데이터들을 Structure에 저장하고, 다시 다음 Thread에서 Structure에서 데이터 값을 불러오는 과정을 어떻게 하면 빠르게 수행할 수 있을까를 고민했다. 간단하게는 for문을 통해 저장 및 불러오기를 할 수 있다. 하지만, 수많은 pixel 값을 이렇게 불러오고, 쓰기에는 처리 시간에 문제가 있다고 판단했고, 이를 보완하고자 Thread의 역할 마지막/시작 부분에 필요한 데이터들을 memcpy 하여 빠르게 저장 및 불러오기를 수행했다. memcpy 관련 링크는 하단에 있다.
① https://blockdmask.tistory.com/442
② https://zoosso.tistory.com/1064
23년 4월
■ 결론적으로 프로젝트를 어느 정도 마무리 하는 단계에서....
■ 현재는 자력 화할 코드 개발은 모두 끝난 상태이며, 디버깅 및 해당 코드가 현장에서 잘 작동하는지 테스트 중이다. 또한, DB로 Insert를 위해 테이블 설계 및 프로시저, 스케줄러 코드는 협력 업체에게 맡긴 상황이다.
■ 이번 프로젝트를 하면서 아쉬웠던 점은 여러 시행착오를 거쳤지만 일의 진행 순서를 전체적인 Global Variable 정의 및 Header 파일 선언 (모든 개발에 Global Memory Map을 구축하고 서로 간의 약속을 정하는 것이 제일 중요한 거 같다) → Thread 구성 및 코드화 → 각자 맡은 부분 코드 개발 순으로 했으면 더 빠르게 프로젝트가 끝났을 수 있을 거 같다.
■ 회사 생활을 하면서 박람회를 통해 여러 영상처리 업체를 살펴봤지만, 머신 비전 개념을 도입한 영상처리 방식이 많았지만, 해당 영상처리를 구현하기 위해 구체적으로 SW의 Processing 설명을 듣지 못했다.
■ 내가 궁금한 것은 이렇게 Time dependant 한 시스템에서 어떻게 무거운 머신 개념을 도입할 수 있는지, 이를 통해 시간 안에 모든 Processig을 처리할 수 있는지?,
■ GPU 기반의 Thread는 어떻게 설계되어 있는지, 분명 CPU와 다른 개념으로 Thread를 설계할 텐데 이러한 부분을 자세히 들을 기회가 없었다. 기회가 된다면 GPU 기반 Processor 설계를 해보고 싶다. 엔비디아의 CUDA로 한다는데 어떻게 공부해야될지 모르겠음.
■ 아직도 이해되지 않는 부분이 있음 23.04.21, 새롭게 알게 되는 부분이 있으면 Update 예정
■ 앞으로 들어가는 신규 프로젝트는 절대적인 Accuracy가 중요하기 때문에 Time의 가중치를 줄일 것이다. 그렇기 때문에 CNN과 같은 머신 개념을 추가해서 영상처리 작업을 진행해 볼 것이다. 약간 설렘. 예전에 U-net의 8 layers 구조의 러닝을 통해 영상처리 Smoke Detection 프로젝트를 했던 적이 있었는데 약간 Detection 정확도도 낮았고, low-level 수준이었음. 이번에 제대로 해보고 싶음.
■ 추가로 일을 하면서 업무 외적으로 든 생각은 직무로는 개발자, 직군은 제조업, 회사 규모는 중소기업으로는 취업하면 근무하기에 힘들 거 같다는 생각이 든다. 일단 다 모르겠고 중소기업의 경우 협력으로 들어가는 경우가 많은데 이럴 경우 대기업의 제조 지역으로 지방 어디로든 파견이 너무 많고, 프로젝트 기간동안 사랑하는 가족 또는 연인과 떨어져 지내야 되니까 내 개인적인 삶에 미치는 영향이 클 거 같다. 이게 가장 별로... 웬만하면 대기업으로 모두들 가시는 것을 추천합니다.
댓글