AI Architecture 9. Convolution 연산의 3가지 매핑: Direct vs Im2Col vs Winograd

지난 글에서 우리는 하드웨어가 CNN(Convolutional Neural Network)을 사랑하는 이유가 지역성(Locality)과 데이터 재사용(Data Reuse) 때문임을 배웠습니다. 이론적으로 CNN은 완벽한 하드웨어 친화적 알고리즘처럼 보입니다.

하지만 막상 이 알고리즘을 실리콘 칩 위에 구현하려고 하면, 하드웨어는 심각한 난관에 봉착합니다. 바로 복잡한 루프(Loop) 구조입니다. CNN 연산은 기본적으로 6중~7중 루프(Batch, Out Channel, In Channel, Height, Width, Kernel H, Kernel W)로 이루어져 있습니다. 이 복잡한 루프를 그대로 하드웨어로 옮기면(Direct Conv), 메모리 접근 패턴이 뒤죽박죽이 되어 캐시 효율(Cache Hit Rate)이 바닥을 칩니다.

그래서 엔지니어들은 기발한 아이디어를 냅니다. “메모리를 좀 낭비하더라도, 이 복잡한 연산을 단순한 행렬곱(Matrix Multiplication)으로 바꿔버리면 어떨까?”

이번 글에서는 하드웨어와 컴파일러가 Conv 연산을 처리하는 3가지 대표적인 전략인 Direct, Im2Col, Winograd를 비교하고, 그 속에 숨겨진 메모리와 속도의 등가교환 법칙을 알아보겠습니다.

1. Direct Convolution

가장 직관적인 방법은 수식 그대로 구현하는 것입니다. Sliding Window가 이미지를 한 칸씩 훑으면서 곱하고 더하는 방식입니다.

  • 장점: 추가적인 메모리가 전혀 필요 없습니다(Zero Memory Overhead). 입력 이미지와 가중치만 있으면 됩니다.
  • 단점: 하드웨어 구현이 매우 어렵습니다.
    • 불규칙한 메모리 접근: 윈도우가 이동할 때마다 데이터의 주소가 불연속적으로 튑니다.
    • 병렬화의 어려움: SIMD(병렬 처리) 유닛을 꽉 채워서 돌리기가 매우 까다롭습니다.

초기 하드웨어나 메모리가 극도로 부족한 임베디드 환경이 아니라면, Direct 방식은 느린 속도 때문에 잘 사용되지 않습니다.

2. Im2Col (Image to Column)

오늘날 대부분의 GPU(cuDNN)와 딥러닝 프레임워크가 사용하는 표준 방식입니다. 핵심 아이디어는 3차원 합성곱을 2차원 행렬곱(GEMM)으로 변환하자는 것입니다.

작동 원리

  1. Im2Col 변환: 3 * 3 커널이 지나가는 영역(Receptive Field)의 픽셀들을 뜯어내어, 하나의 긴 열(Column) 벡터로 펴버립니다.
  2. 이 과정을 모든 윈도우 위치에 대해 반복하면, 거대한 입력 행렬(Input Matrix)이 만들어집니다.
  3. 필터(Weight)들도 마찬가지로 펴서 가중치 행렬로 만듭니다.
  4. 이제 두 거대한 행렬을 곱합니다(GEMM).

트레이드오프 (Trade-off)

  • 장점 (Speed): 복잡한 Conv 연산이 최적화가 매우 잘 되어 있는 GEMM(General Matrix Multiply) 문제로 바뀝니다. GPU나 NPU의 행렬 연산 유닛을 100% 가동할 수 있어 속도가 비약적으로 빨라집니다.
  • 단점 (Memory): 치명적인 메모리 낭비가 발생합니다. Sliding Window가 겹치는(Overlap) 영역의 픽셀들이 행렬로 변환될 때 중복 복사(Duplication)됩니다.
    • 예를 들어 3 * 3 커널을 사용하면, 원본 이미지보다 데이터 양이 약 9배 뻥튀기됩니다. (Stride=1 기준)

하드웨어 엔지니어는 고민합니다. “메모리 사용량이 9배 늘어나도 괜찮은가?” 대부분의 경우 “그렇다”입니다. 왜냐하면 메모리 용량보다 연산 속도(Throughput)가 더 귀하기 때문입니다.

3. Winograd Algorithm

Im2Col이 구조를 바꿔 속도를 높였다면, Winograd는 수학을 바꿔 연산 횟수 자체를 줄이는 방식입니다.

보통 3 * 3 필터로 2 * 2 출력을 만들려면 2 * 2 * 9 = 36번의 곱셈이 필요합니다. 하지만 Winograd 알고리즘을 쓰면 이를 16번의 곱셈으로 줄일 수 있습니다. (약 2.25배 감소)

작동 원리

입력(d)과 필터(g)를 퓨리에 변환과 유사한 방식으로 변환(Transform)한 뒤, 점별 곱셈(Element-wise Multiplication)을 하고, 다시 역변환(Inverse Transform)을 합니다.

Y=AT[(GgGT)(BTdB)]AY = A^T [(G g G^T) \odot (B^T d B)] A
  • G, B, A: 미리 정의된 변환 행렬 (상수)
  • : 점별 곱셈

트레이드오프 (Trade-off)

  • 장점: 곱셈(MAC) 횟수가 획기적으로 줄어듭니다. 3 * 3 Conv 위주의 모델에서 압도적인 성능을 보입니다.
  • 단점 1 (변환 비용): 곱셈은 줄지만, 변환 과정에서 덧셈(Addition)이 늘어납니다. 또한 변환을 위한 전용 하드웨어 유닛이 필요할 수 있습니다.
  • 단점 2 (정밀도): 변환 행렬에 소수점 상수가 많아, 부동소수점 연산 시 오차(Numerical Error)가 발생할 수 있습니다. INT8 양자화와 결합하기 까다롭습니다.

4. 하드웨어 엔지니어의 선택

그렇다면 우리는 어떤 방식을 선택해야 할까요? “정답은 상황에 따라 다르다”입니다.

  • 메모리가 넉넉하고 고성능이 필요한 GPU: 주저 없이 Im2Col + GEMM을 사용합니다. 메모리 낭비보다 병렬 처리가 중요하니까요.
  • 커널 사이즈가 작은(3 * 3) 모바일 NPU: Winograd를 적극 활용하여 연산 효율을 높입니다.
  • 메모리가 극도로 제한된 IoT MCU: 어쩔 수 없이 Direct Conv를 쓰거나, Im2Col을 아주 작은 타일(Tile) 단위로 쪼개서 수행합니다.

5. 결론

CNN 가속의 역사는 메모리 공간(Space)과 연산 시간(Time) 사이의 끊임없는 줄다리기입니다.

  • Im2Col: 공간을 버리고 시간을 산다.
  • Winograd: 복잡성(덧셈)을 주고 곱셈을 줄인다.

하드웨어 엔지니어로서 우리는 칩이 사용될 환경(메모리 대역폭, 용량, 목표 성능)을 정확히 파악하고, 이 알고리즘 중 최적의 무기를 선택해 하드웨어에 매핑해야 합니다.

다음 글에서는 CNN의 또 다른 필수 요소이자, 간단해 보이지만 하드웨어 라인 버퍼(Line Buffer) 설계를 복잡하게 만드는 주범, “Pooling과 Padding의 하드웨어 이슈”에 대해 알아보겠습니다.

참고: Fast Algorithms for Convolutional Neural Networks

Similar Posts