딥러닝 하드웨어 담론 (2)
이전에 작성한 딥러닝 하드웨어 담론 (1) 글은 맥클러스터를 구축하여 상용으로 공급되는 nvidia gpu 장비를 대체할 수 있을까? 라는 궁금증에 대해 대답해보려는 내용을 담고 있습니다. 링크드인에 글 소개를 올릴 때에는 동료 개발자분들과 이런 주제로 나눈 대화를 정리한 것이라고 언급드린 바 있습니다.
임베디드 개발자로 근무하시는 한 분과 이런 대화를 나누게 되었습니다.



램슬롯이 4개 가량 부착가능한 보드를 통해 ddr5 메모리를 256gb 정도 장착한 데스크탑을 구성하면 맥클러스터를 구성하는 것보다 더 저렴하게 구성할 수 있다는 것이 핵심이었습니다. 당연히(?) 추론연산의 속도가 매우 느릴테니 metal api 등으로 하드웨어 가속을 지원받으면 더 쓸모있어질 것이라는 내용입니다.
저는 여기까지 이야기했을 때, gpu memory가 아닌 일반 메모리를 사용하는 방식이므로 cuda operation을 사용하지 못하고(?) 따라서 추론속도가 느릴 것이다. 정도로 피상적으로 이해를 하고 있었습니다. 물론 아주 틀린 키워드가 언급된 것은 아니지만 명료하게 알고 있다고 할 수는 없습니다.
그래서 방에 계신 괴수 개발자분들에게 여러가지 질문을 남기기도 하고, 제 스스로도 이해가 잘 안가는 부분들을 찾아보면서 알게 된 내용들을 정리해보았습니다.
제가 가장 궁금했던 부분은 gpu 연산가속이 어떠한 방식으로 일어나기에 nvidia는 좋고 mac과 일반 desktop은 성능이 좋지 않을까? 하는 것입니다. 이러한 궁금증을 해결하기 위해서는 microprocessor에 대한 이해부터 필요했습니다.
CISC vs RISC

마이크로프로세서는 디지털 데이터를 입력받고, 메모리에 저장된 명령어들을 가져와 처리하고, 결과를 출력으로 내놓는 다목적의 프로그램 가능한 기기입니다. 그리고 대부분의 경우, 명령어들은 순차적으로 처리가 됩니다.
이러한 명령어들을 어떻게 관리하느냐에 따라 CISC(Complex Instruction Set Computer)와 RISC(Reduced Instruction Set Computer)로 구분하게 됩니다.
특징만을 요약해본다면...
- CISC는 복잡하고 꽤 많은 명령어를 가지고 있고, 가변길이의 명령어를 사용합니다. 하드웨어들과의 호환성은 좋지만 속도가 느리고 설계가 어렵습니다.
- RISC는 단순하고 적은 수의 명령어를 가지고 있고, 불변길이의 명령어를 사용합니다. 하드웨어들과 조금만 버전이 틀어져도 성능이 저하되지만 처리속도가 빠르고 명령어처리 파이프라이닝이 효율적입니다.
라고 하는데 사실 이런 표현으로는 쉽게 와닿지 않습니다. 실제로 어떻게 명령어를 다루는지 살펴보면 될 것 같습니다.
# CISC
MOVE [2000], [1000]
설명:
이 하나의 명령어로 메모리 주소 1000번지의 데이터를 2000번지로 복사
하나의 명령어가 메모리 읽기와 쓰기를 모두 수행
복잡한 동작을 하나의 명령어로 처리
# RISC
LOAD R1, [1000] ; 메모리 1000번지 값을 R1 레지스터에 로드
STORE R1, [2000] ; R1 레지스터 값을 메모리 2000번지에 저장
설명:
같은 작업을 두 개의 단순한 명령어로 분리
각 명령어는 한 가지 기본적인 동작만 수행
레지스터 기반 연산을 주로 사용
한편, 이런 명령어들을 어셈블리로 표현할 때에는 다음과 같이 나타납니다.
# CISC
MOV AX, BX ; 2바이트
MOV EAX, [BX+SI+4] ; 4바이트
PUSH [0x1234] ; 3바이트
설명:
명령어마다 길이가 다름 (2~15바이트까지 다양)
복잡한 명령어는 더 많은 바이트 필요
장점: 메모리를 효율적으로 사용 가능
단점: 명령어 해석(디코딩)이 복잡하고 시간 소요
# RISC
ADD R1, R2, R3 ; 4바이트
LDR R1, [R2, #4] ; 4바이트
STR R1, [R2, #8] ; 4바이트
설명:
모든 명령어가 동일한 길이 (보통 32비트 = 4바이트)
단순하고 규칙적인 형식
장점: 명령어 해석이 빠르고 단순
단점: 간단한 명령어도 동일한 크기를 차지해서 메모리 낭비 가능
CISC는 검증된 명령어들을 필요한 경우마다 전부 정의해놓고 사용하기 때문에 컴파일이 쉽고 instruction set을 상속받을테니 호환성 측면에서 유리하겠지만 명령어의 종류가 많아 복잡하고 중구난방입니다. RISC의 경우에는 쉽고 일정한 연산들의 조합만으로 효율적인 데이터처리가 가능하다는 것을 직관적으로 파악할 수 있습니다.
딥러닝은 왜 GPU를 사용할까?

만약 딥러닝 모델의 학습과 추론의 근간이 되는 행렬연산을 CISC와 RISC 방식으로 간단하게 표현해본다면 다음과 같을 것입니다.
- CISC
- MATRIX_MULTIPLY [output_addr], [input_addr], [weight_addr], [matrix_size]
- 하나의 복잡한 명령어로 전체 행렬 곱셈을 처리
- RISC
- LOAD R1, [input_ptr] ; 입력 데이터 로드
- LOAD R2, [weight_ptr] ; 가중치 로드
- MUL R3, R1, R2 ; 곱셈 수행
- ADD R4, R4, R3 ; 누적 합
- ADD input_ptr, #4 ; 다음 입력으로
- ADD weight_ptr, #4 ; 다음 가중치로
- STORE R4, [output_ptr] ;
- 결과 저장
눈으로 보여지는 인터페이스 상으로는 CISC가 훨씬 간단해보이지만, 실제로는 instruction set에서 matrix multiply를 수행하도록 구현된 assembly 코드를 지원해야지만 동작하는 함수입니다. 또한, cpu의 코어수는 일반적으로 (gpu대비) 매우 낮은 개수이므로 딥러닝 모델사이즈가 커질수록 하나의 행렬곱 명령어를 수행하는데에 아주 오랜시간이 걸리는 것을 예상할 수 있습니다.
RISC 방식의 경우 단순하고 반복적인 연산들을 여러 번 수행하는 것이 번잡해보이지만, 해당 연산(명령어)들을 수행할 수 있는 core를 scale-up 하는 방식으로 문제를 해결할 수 있습니다. 이전 글에서 살펴본 nvidia a100 장비가 바로 이러한 방식에 해당됩니다!
- Tensor Float 32(TF32) 156TFLOPS | 312TFLOPS*
- FP16 Tensor 코어 312TFLOPS | 624TFLOPS*
- 인터커넥트: NVIDIA® NVLink® 2개의 GPU를 위한 브리지: 600GB/s ** PCIe Gen4: 64GB/s
- INT8 Tensor 코어 624TOPS | 1,248TOPS*
- BFLOAT16 Tensor 코어 312TFLOPS | 624TFLOPS*
- GPU 메모리 대역폭 1,935GB/s
Float, BFloat, FP16, INT8 등 딥러닝에서 사용하는 자료형들에 대해 초당 156조에서 624조번의 연산을 수행할 수 있습니다. 연산 이후의 데이터 복사를 대량으로 지원하기 위해서 메모리 대역폭 또한 1,935GB/s로 대단히 넓습니다.
따라서 대단히 큰 모델에 대한 행렬곱 연산을 수행하더라도, 초당 수백조번의 병렬처리와 데이터복사를 효율적으로 수행하며 사용가능한 time-scale을 보장합니다
CUDA

우리들이 사용하는 컴퓨터의 운영체제는 gpu device가 아닌 전통적인 폰 노이만 구조로부터 유래되었기 때문에, 실제로는 위 그림과 같이 host와 device(gpu)로 구분되고 이들 사이의 통신을 통해 연산처리를 하게됩니다.
CUDA를 이용해 GPU 프로그래밍을 하면 처리되는 과정은 다음과 같습니다.
- Data가 CPU에서 GPU로 복사
- GPU에서 커널 함수를 실행하여 처리
- 결과를 GPU에서 CPU로 복사
통상적인 cpu-memory 구조의 연산과 차별화된 성능을 보이기 위해 device 내부적으로 다양한 기법들이 적용됩니다. 다음과 같은 것들이 있습니다.
- tensor core
- L1 데이터 캐시(L1 Data Cache)와 공유 메모리(Shared Memory)의 통합
- 스레드 블록 클러스터(Thread Block Clusters)
- 분산 공유 메모리(Distributed Shared Memory)
- 비동기적 수행(Asynchronous Execution)
- 텐서메모리 가속기(Tensor Memory Accelerator)
- 비동기적 트랜잭션 장벽(Asynchronous Transaction Barrier)
nvidia에서는 컴퓨터 애플리케이션과 딥러닝 발전 트렌드에 맞추어 좀더 효율적인 컴퓨팅 연산을 지원하기 위해 연구하고 있습니다. 따라서 gpu device의 세대가 너무 오래된 경우에는 모델의 특정 연산을 구현하는데에 꼭 필요한 명령어가 존재하지 않는 경우들도 종종 발생합니다.
결론
이 글에서 작성된 내용들을 통해 기존의 평범한(?) 컴퓨팅 머신에서 gpu device를 추가하고, 여기에서 risc 아키텍쳐에 가까운 구조를 채택한 nvidia gpu device가 어떠한 방식으로 연산을 가속하는지를 알 수 있게 되었습니다.
그렇다면 처음 맥클러스터의 이야기가 나왔을 때로 돌아가보겠습니다.
m 시리즈 자체 칩 등장 이후로 애플 컴퓨터가 꽤 괜찮은 gpu vram을 제공하는 하드웨어 단말로 여겨지고 있다는 이야기를 했는데, 우리가 일반적으로 아는 선에서는 애플은 별도로 nvidia 혹은 기타 gpu 제품을 탑재하고 있지 않습니다.
도대체 어떤 마법이 씌였기에 로컬 맥북에서 일정 수준의 크기까지 llm을 추론에 활용할 수 있는걸까요?
참고자료
- nvidia gpu architecture: https://www.samsungsds.com/kr/insights/nvidia-gpu-architecture.html
- CISC vs RISC: https://www.guru99.com/ko/risc-vs-cisc-differences.html