지난 Conv 연산의 3가지 매핑에서 우리는 일반적인 합성곱(Standard Convolution)을 하드웨어에서 처리할 때, Im2Col 방식을 통해 메모리를 희생하고 연산 속도(GEMM)를 얻는 전략을 살펴보았습니다.
2017년, 구글이 발표한 MobileNet은 모바일 환경을 위한 혁명적인 모델이었습니다. 기존 모델 대비 연산량(FLOPs)과 파라미터 수를 1/10 수준으로 줄이면서도 준수한 정확도를 보여주었기 때문입니다. 그 비결은 Depthwise Separable Convolution이라는 독특한 구조에 있었습니다.
하지만 이 구조는 하드웨어 엔지니어들에게 MobileNet의 역설”이라고 불리는 흥미로운 현상을 안겨주었습니다.
“연산량은 90%가 줄었는데, 왜 실제 실행 속도(Latency)는 그만큼 빨라지지 않는가?”
이번 글에서는 소프트웨어적으로는 완벽해 보이는 모델이, 하드웨어(NPU/GPU) 내부에서는 왜 가동률(Utilization)의 급락이라는 부작용을 낳는지, 하드웨어 엔지니어의 관점에서 그 물리적 원인을 파헤쳐 보겠습니다.
1. Depthwise Separable Convolution
먼저, MobileNet이 어떻게 연산량을 줄였는지 간단히 짚고 넘어갑시다. 표준 Conv 연산을 두 단계로 쪼개는 것이 핵심입니다.
- Depthwise Conv: 각 입력 채널마다 별개의 필터를 적용합니다. (채널 간 정보 교환 없음)
- Pointwise Conv: 1 * 1 크기의 필터로 채널 간의 정보를 섞어줍니다.
입력 데이터가 H * W * C, 커널 크기가 K * K일 때, 연산량은 다음과 같이 감소합니다.
- Standard Conv:
- Depthwise Separable:
수식적으로 계산하면 약 8~9배의 연산량 감소 효과가 있습니다. 숫자만 보면 하드웨어가 9배 덜 일해도 되니 9배 빨라져야 할 것 같습니다. 하지만 현실은 그렇지 않습니다.
2. 역설의 원인 1: 낮은 연산 강도 (Low Arithmetic Intensity)
하드웨어 성능을 결정하는 핵심 지표는 Arithmetic Intensity (연산 강도)입니다. 즉, “메모리에서 데이터 1바이트를 가져왔을 때 몇 번의 연산을 수행하는가?”입니다.
- Standard Conv: 입력 채널 하나가 N개의 출력 채널 필터와 모두 연산됩니다. 데이터 재사용(Reuse)이 아주 높습니다.
- Depthwise Conv: 입력 채널 C는 오직 커널 채널 C 하고만 연산됩니다. Cross-channel Reuse가 전혀 없습니다.
Depthwise Conv는 데이터를 메모리에서 힘들게 가져와서, 고작 몇 번 곱하고 끝납니다. 이는 7번 글에서 다룬 [MLP와 메모리 장벽] 문제와 유사합니다. 연산기가 바쁘게 돌아가기도 전에, 메모리 대역폭이 병목(Memory-Bound)이 되어 성능 저하를 일으킵니다.
3. 역설의 원인 2: MAC 가동률(Utilization)의 파편화
대부분의 고성능 NPU나 GPU는 거대한 행렬곱(GEMM)을 처리하기 위해 수십, 수백 개의 MAC 유닛을 하나의 거대한 배열(Systolic Array 등)이나 넓은 벡터 레지스터(SIMD)로 묶어 놓습니다.
예를 들어, 64개의 MAC이 한 묶음으로 동작하는 NPU가 있다고 가정해 봅시다.
- Pointwise Conv (1 * 1, 채널 섞기): 채널 간 연산이므로 64개 MAC이 꽉 차서(Dense) 100% 효율로 돌아갑니다.
- Depthwise Conv (채널 별 독립): 각 채널이 독립적입니다. 만약 하드웨어 스케줄러가 채널 단위로 병렬화를 시도하는데, 메모리 레이아웃이나 데이터 의존성 문제로 한 번에 1개 채널씩만 처리해야 한다면?
- 64개 중 1개만 일하고 63개는 놉니다. (가동률 1.5%)
이것이 MAC Starvation 현상입니다. Depthwise 연산은 하드웨어 입장에서 너무 잘게 쪼개진 일감이라, 대규모 병렬 처리 장치의 효율을 떨어뜨립니다.
4. 메모리 레이아웃의 충돌: Channel-First vs Channel-Last
하드웨어 효율성은 데이터가 메모리에 어떻게 놓여있느냐(Layout)에 따라 결정됩니다.
- NCWH (Channel-First): 채널이 먼저 나옵니다.
- NHWC (Channel-Last): 픽셀 위치별로 채널이 뭉쳐 있습니다.
일반적으로 고성능 NPU는 벡터 연산을 위해 NHWC를 선호합니다. 1 * 1 Pointwise Conv를 할 때 특정 픽셀의 모든 채널을 한 번에 가져오기 좋기 때문입니다.
하지만 Depthwise Conv는 공간적(Spatial) 연산이므로 3 * 3 영역의 픽셀들이 필요합니다. NHWC 구조에서는 이웃한 픽셀들이 메모리상에서 멀리 떨어져 있어, 캐시 미스(Cache Miss)를 유발하거나 복잡한 셔플(Shuffle) 로직을 필요로 합니다.
5. 결론: FLOPs는 속도가 아니다
MobileNet은 분명 훌륭한 모델입니다. 하지만 연산량이 적다(Low FLOPs)는 것이 반드시 하드웨어에서 빠르다(Low Latency)를 의미하지 않는다는 것을 증명한 대표적인 사례이기도 합니다.
- Standard Conv: 연산량은 많지만, 하드웨어 효율(Utilization)이 높아 가성비 좋은 노동을 합니다.
- Depthwise Conv: 연산량은 적지만, 메모리 병목과 하드웨어 유휴 상태(Idle)를 유발하여 비효율적인 노동을 합니다.
최근의 NPU 아키텍처들은 이 문제를 해결하기 위해 Depthwise 전용 가속 엔진을 별도로 탑재하거나, Pointwise Conv와 융합(Fusion)하는 방식으로 진화하고 있습니다. Hardware engieer로서 우리는 단순히 FLOPs 수치에 현혹되지 않고, 실제 하드웨어 파이프라인이 겪을 부하를 꿰뚫어 볼 수 있어야 합니다.
다음 글에서는 ResNet이 가져온 딥러닝의 혁명 뒤에 숨겨진 하드웨어적 골칫거리, “ResNet과 병목: Skip Connection이 하드웨어 메모리 관리와 버퍼 스케줄링에 주는 문제”에 대해 알아보겠습니다.
참고: Efficient Convolutional Neural Networks for Mobile Vision Applications