멀티스레드의 역효과.
멀티스레드의 역효과
서론
나는 지금 중국 우한의 TIANMA(천마) 라는 국영기업 공장에 나와있다.
목적은 OMM(Open Metal Mask) 검사기의 Setup 이다.
OMM 은 가로세로 폭이 크고 (대략 2m 정도 되어보인다) 라인스캔카메라로 이미지를 취득한다.
따라서 실시간 이미지 취득, 이미지 전처리, 검사, 데이터 처리, 검사결과 저장의 수행이 빠르게 동작해야 한다.
이로인해 검사 알고리즘의 속도최적화를 알뜰살뜰 만들었고 일반적인 상황에선 큰 문제가 없었다.
그러나… Defect 이 다수 발생하는 구간에서 CPU 사용률이 100% 에 도달하며 Image Grab Buffer 가 깨지는 절망적인 상황이 벌어졌다.
도대체 왜 이렇게 느렸던걸까
Defect 이 많이 발생하는 구간이라는 점에 초점을 맞추면, Defect 의 추출과 Feature 계산 등의 연산이 영향을 미친다고 볼 수 있다.
하지만 이건 해결할 수 없는 문제였다. 그 당시와 지금의 나로써는 뾰족한 수가 없다.
Gv 추출은 Histogram 방식으로 이미 최적화를 진행했고, Defect 후보점을 줄인다면 실불량 미검출의 리스크가 따랐다.
프로그램 빌드도 속도최적화 O2 옵션을 켰고 이미지 전처리도 AVX2 벡터확장 가속을 사용했다.
검사 자체도 멀티스레드로 최대한 병렬화를 진행했다.
라고 생각하던 찰나였다.
잠깐… 병렬화? 멀티스레드?
그래 가만히 생각해보면 이미지 한 장의 검사 시간이 늘어나는.. 현상이 있다.
아무리 Defect 이 많이 발생했다 해도 본래 0.3 초 가량 소요되는 검사 시간이 2 초로 늘어나는 건 도저히 비정상적인 일이다.
그리고 이 때 나는 CPU 사양을 확인했다.
Intel i9-10900 (SMT) 물리코어 10, 논리프로세서 20
원인을 찾았다.
범인을 찾았다
비전 S/W 에서 수행하는 역할들은 멀티스레드 방식으로 구현됐다.
이미지 취득, 이미지 검사, 결과 저장…
이미지 취득에서 스레드 6개,
이미지 검사에서 스레드 30개,
결과 저장에서 스레드 5개였나.. 6개였나…
비단 비전 S/W 뿐 아니라 Windows OS 위에서는 다양한 S/W 들이 실행되어 있었다.
물론 이미지 검사처럼 많은 양의 연산을 수행하는 스레드들은 아니었을 테지만 말이다.
나는 이미지 검사 스레드의 개수를 줄여보았다.
18개.
뭔가 병목현상이 조금 줄어든 것 같아보였다. Image Buffer 는 더 이상 깨지지 않는다.
12개.
확실히 좋아진게 보인다. 더 줄여보길 잘했다.
6개.
완벽하다. Defect 이 다발하는 구간에서도 6개의 스레드가 동시활성화 되지 않는다.
멀티스레드.. 다다익선이 아니었다.
CPU의 코어 개수보다 활성 스레드가 더 많다면 각 스레드는 코어를 나눠써야 한다.
1개의 코어가 1개 이상의 스레드에서 사용되는 것이다.
병렬화 작업이 진행되는 것처럼 보이지만, 결코 이것은 동시 진행이 아니라 하나의 코어가 두 개의 스레드일을 빠르게 번갈아가며 처리하는 것이다.
이러고 끝이라면.. 사실 역효과라고 까지 볼 순 없을 것이다.
어쨌든 총 소요시간은 동일할테니까 말이다.
하지만 그렇지 않다.
오버헤드??
코어의 멀티스레드는 레지스터와 연관이 있다.
하나의 코어가 여러개의 스레드 일을 처리하느라 작업이 전환되는 것을 컨텍스트 스위칭이라고 부른다.
컨텍스트 스위칭이 발생하면 OS 커널이 현재 스레드의 레지스터 상태를 저장한다.
그리고 다음 스레드의 상태를 복원하며 Stack Pointer를 반환한다.
이러한 과정 자체가 us 단위로 시간 비용이 발생한다
이를 두고 컨텍스트 스위칭 비용, 즉 오버헤드라고 부른다.
하지만 더 큰 문제는 캐시
CPU 에는 캐시라는 것이 있다.
L1, L2, L3 단계로 구성되어 있고 숫자가 작을수록 해당 코어과 가깝고 전용 메모리이며 속도가 빠르다.
그 하위 단계에 우리가 익히 알고있는 DRAM 구간이 있고 속도는 비교적 느리다.
각 메모리 속도 (대략 참고치)
L1: 1ns 이하
L2: 3~5ns
L3: 10~30ns
DRAM: 60~120ns
그리고 영상처리는 용량이 큰 이미지를 건드리는 작업이다.
이미지 파일은 용량이 크다. L 캐시의 캐퍼시티를 초과하기 때문에 L 캐시에 유지되지 못한다.
따라서 코어는 DRAM 에 접근해야 한다.
이 때 컨텍스트 스위칭으로 인해 working set locality가 깨지고 캐시 미스가 증가하면서 DRAM 접근이 급증한다.
즉 개손해다.
핵심은
사실 더 복잡하고 전문용어가 많이 나올 수 있는 내용이다.
하지만 내가 알고있는 지식 선에서 설명하려다 보니 많이 허접하다.
하지만 중요한 핵심은 하나다.
멀티스레드 많다고 무조건 좋은 게 아니다.
각 코어가 처리할 수 있을만큼 적절한 병렬화가 진행되어야 속도최적화로써 의미가 있는 것이다.
작업대는 10개 뿐인데 작업자 100명이라고 일이 10 배 빨라지겠는가??
아니, 서로 작업하겠다고 작업대 쟁탈전 벌이느라 오히려 일만 더뎌질 뿐이다.
끝.
댓글남기기