A11에서 시작된 설계를 다시 보는 이유
애플은 A11 Bionic부터 뉴럴 엔진을 제품에 넣었다. M1의 뉴럴 엔진을 다시 역설계한 의미는 단순히 연산량을 세는 데 있지 않다. 어떤 연산을 빠르게 처리했는지보다, 입력과 부분 결과를 어디에 두고 언제 이동시켰는지를 살펴봐야 당시 애플이 상정한 머신러닝 작업을 이해할 수 있다.
M1의 구조는 범용 명령 프로세서라기보다, 미리 정해진 데이터 흐름을 효율적으로 통과시키는 실행 장치에 가깝다. 전체 흐름은 다음과 같이 정리된다.
16개 코어와 2048개 MAC 레인
M1 뉴럴 엔진에는 16개 컴퓨트 코어가 있다. 각 코어는 FP16 기준 128개의 병렬 MAC 레인을 가지며, 전체로는 2048개의 병렬 MAC 레인이 된다. INT8 경로에서는 코어당 256개의 MAC 레인이 동작한다.
MAC는 두 입력을 곱한 뒤 누산기의 기존 값에 더한다. 한 레인이 여러 사이클 동안 이 과정을 반복하면 내적이 된다. 따라서 같은 하드웨어가 내적, 행렬 곱, 합성곱으로 보이는지는 MAC 자체가 아니라 입력과 가중치를 어떤 순서로 배치하고 예약하느냐에 달려 있다. 뉴럴 엔진의 핵심 특성은 MAC의 존재보다 MAC 주변의 데이터 흐름에 있다.
각 레인의 누산 값은 외부 메모리로 매번 나가지 않고 로컬 피드백 경로에 남는다. 이 설계는 같은 입력과 가중치가 일정한 방식으로 재사용되는 작업에서 메모리 왕복을 줄이는 데 유리하다.
32비트 누산기와 포화 연산
내부 데이터 경로는 곱셈기, 덧셈기, 그리고 32비트 누산기 레지스터로 구성된다. 매 사이클 곱셈 결과가 이전 합에 더해지고, 그 결과가 다음 사이클의 입력이 된다.
누산은 FP16 값을 그대로 계속 더하는 방식이 아니라 고정소수점 형태로 이뤄진다. 확인된 동작은 Q16.16 형식의 32비트 누산이며, 결과를 읽을 때 FP16으로 변환한다. 누산기의 상한은 FP16 출력의 일반적인 오버플로와 달랐다. 실험에서는 값이 2의 15승에서 포화됐고, 음의 방향에서도 대응하는 범위 제한이 나타났다.
이 차이는 중요하다. 중간 합이 충분히 큰 값까지 유지되므로 긴 내적에서 FP16만 사용할 때와 다른 결과 특성이 생긴다. 반대로 포화 지점에 도달하면 이후의 증가분은 결과에 반영되지 않는다. 즉, 정밀도는 입력 형식뿐 아니라 누산 형식과 포화 위치에 의해 결정된다.
MAC 직후 적용되는 활성화 LUT
합성곱이나 내적의 결과는 중간 메모리에 저장된 뒤 다시 읽히지 않는다. 완성된 MAC 합은 곧바로 활성화 블록으로 전달된다. 활성화 함수가 각 스칼라에 독립적으로 적용되는 점을 이용한 구성이다.
ReLU는 비교적 단순한 경로를 사용하지만, tanh에는 33개의 FP16 값으로 이뤄진 표가 확인됐다. 이 값들은 0부터 4까지 간격 1/8로 계산한 tanh 샘플과 일치한다. 활성화 모드 2는 이 33개 항목 LUT를 선택하고, 입력을 LUT 좌표로 변환한 다음 인접한 두 값을 이용한다.
단일 항목만 1로 만들고 나머지를 0으로 둔 시험에서는 출력이 한 지점에서 갑자기 바뀌지 않고 삼각형 모양으로 선형 상승과 하강을 보였다. 따라서 이 경로는 단순한 구간 선택이 아니라 구간별 선형 보간 LUT로 동작한다. 입력 스케일을 정하는 값이 커질수록 표의 절점 간격은 좁아진다.
선형 스케일과 바이어스도 컴파일 과정에서 이 데이터 경로에 맞게 합쳐진다. 예를 들어 활성화 앞의 변환이 합성곱 가중치와 바이어스에 접혀 들어가면, 실행 시 별도의 일반 산술 명령을 추가하지 않고 같은 후처리 경로에서 결과를 만들 수 있다.
명령어보다 컴파일된 작업 묶음
M1의 실행 모델에서 드라이버는 실행 시점에 CONV, MATMUL, RELU 같은 고수준 연산 명령을 하나씩 보내지 않는다. Core ML 모델을 컴파일할 때 연산과 데이터 이동이 작업 디스크립터 묶음으로 미리 만들어진다.
드라이버가 하는 일은 이 묶음을 메모리에 적재하고, 작업 주소와 크기를 지정한 뒤 제출 신호를 보내는 것이다. 작업 큐와 스케줄러는 이미 정해진 묶음을 해석해 16개 코어에 전달한다. 이 구조는 예측 가능한 모델을 빠르게 실행하는 데는 효율적이지만, 실행 중 데이터 의존성이 크게 바뀌는 작업을 유연하게 재구성하는 장치와는 거리가 있다.
CNN의 재사용과 트랜스포머 디코드의 충돌
여기서부터는 해석이다. CNN은 입력 텐서의 창과 커널이 규칙적으로 겹치며, 같은 값이 예측 가능한 방식으로 반복 사용된다. M1의 데이터 경로는 이런 조밀한 재사용을 전제로 설계됐을 가능성이 큽니다.
트랜스포머의 내적도 수학적으로는 MAC의 연속일 뿐이다. 하지만 오토리그레시브 디코드에서는 토큰이 한 단계씩 추가되고, 이전 키와 값이 누적된 상태에서 다음 단계의 계산이 이어진다. 특히 순서가 긴 상태 데이터를 매 단계 다루는 방식은 CNN의 고정된 창 재사용과 다르다. 따라서 M1 뉴럴 엔진이 트랜스포머의 MAC을 수행하지 못했다기보다, MAC 주변의 데이터 흐름이 효율적으로 맞물리지 않았을 가능성이 큽니다.
실제로 한 독자는 트랜스포머를 뉴럴 엔진에 올리면서 시퀀스 축을 마지막 축으로 둔 4차원 텐서와 1×1 합성곱을 사용해 행렬 곱을 CNN처럼 보이게 만들었다고 설명했다. 이 사례는 연산 자체보다 하드웨어가 기대하는 배치와 재사용 규칙에 맞추는 일이 더 어려울 수 있음을 보여준다.
M4 이후와 GPU 내부 가속기를 구분해야 한다
M5 이후의 변화를 독립형 NPU의 종말로 단정하는 것은 조심해야 한다. 한 독자 zozbot234는 M5 이후 GPU 코어 안에 들어간 Neural Accelerators, 즉 NAX 계열과 기존 ANE를 서로 다른 장치로 봐야 한다고 지적했다. 또한 M4 이후 ANE가 단순히 같은 설계의 고속판인지, 추가 기능을 제공하는지는 별도로 확인해야 할 문제라고 말했다.
같은 독자는 M6와 A20에서 ANE 블록이 두 배가 될 것이라는 관측도 언급했지만, 이 글에서 그 사양을 확인된 사실로 단정할 수는 없다. 반면 Apple이 소개한 Core AI는 CPU, GPU, Neural Engine을 함께 활용하는 방향을 제시한다. 이는 앞으로의 모델 실행이 하나의 가속기만으로 끝나기보다 작업 특성에 따라 여러 실행 자원을 조합할 가능성을 보여준다.
따라서 M1에서 확인되는 결론은 뉴럴 엔진이 쓸모없었다는 것이 아니다. M1 뉴럴 엔진은 CNN에 맞춘 데이터 재사용과 컴파일된 실행 모델을 실리콘에 깊게 새긴 설계였고, 이후의 변화는 그 MAC 능력을 어떤 데이터 흐름 안에 배치하느냐의 문제로 보는 편이 정확하다.