title: 벡터/SIMD 아키텍처
date: 2025-06-26
category: arch
tags: [SIMD, vector, AVX, NEON, SVE, GPU-SIMD, RISC-V-V, SIMD-instructions]
벡터/SIMD 아키텍처 (Vector/SIMD Architecture)
개요
벡터 처리(Vector Processing)와 SIMD(Single Instruction, Multiple Data)는 하나의 명령어로 여러 데이터 요소를 동시에 연산하는 병렬 처리 기법이다. SIMD 아키텍처는 프로세서 내의 넓은 레지스터에 여러 데이터 요소를 묶어(pack) 병렬로 사칙연산, 비교, 시프트 등의 연산을 수행한다. 이를 통해 같은 명령어 스트림에서 처리량(throughput)을 레지스터 폭에 비례하여 높일 수 있다.
현대 프로세서에서 SIMD는 필수적인 기능이다. Intel/AMD x86의 SSE/AVX, ARM의 NEON/SVE, RISC-V의 V Extension, 그리고 GPU의 SIMT 모델은 모두 SIMD 개념을 기반으로 한다. SIMD는 수치 해석, 이미지/영상 처리, 머신러닝 추론, 암호화, 신호 처리 등 대량 데이터를 반복 처리하는 워크로드에서 수 배에서 수십 배의 성능 향상을 제공한다. 최근에는 AMX(Advanced Matrix Extensions), Tensor Core, FMMLA 등 매트릭스 연산 전용 유닛으로 발전하여 딥러닝 워크로드를 더욱 가속화한다.
핵심 개념
SIMD 아키텍처 분류
벡터/SIMD 아키텍처는 레지스터 폭의 고정 여부와 프로그래밍 모델에 따라 크게 네 가지로 분류할 수 있다:
| 분류 | 특성 | 대표 ISA | 레지스터 폭 |
|---|---|---|---|
| 고정 폭 SIMD | 고정된 레지스터 크기 (128/256/512비트) | SSE, AVX, NEON | 128~512비트 |
| 확장 벡터 (VLA) | 벡터 길이에 무관한 바이너리 호환 | ARM SVE/SVE2 | 128~2048비트 |
| 런타임 설정 벡터 | VLEN/LMUL로 레지스터 묶음 조절 | RISC-V V Extension | 128~8192비트 |
| SIMT (GPU) | 다중 스레드가 lockstep 실행 | NVIDIA PTX, AMD RDNA | 워프당 32~64 스레드 |
SSE/AVX (x86 SIMD)
x86 SIMD는 1999년 SSE로 시작하여 20년 이상 진화해왔다.
SSE 계보
| 세대 | 연도 | 레지스터 | 폭 | 데이터 타입 |
|---|---|---|---|---|
| SSE | 1999 | XMM0-XMM15 | 128비트 | 4x FP32 |
| SSE2 | 2001 | XMM0-XMM15 | 128비트 | 2x FP64, 정수 |
| SSE3 | 2004 | XMM0-XMM15 | 128비트 | 수평 연산 추가 |
| SSSE3 | 2006 | XMM0-XMM15 | 128비트 | PSHUFB 등 16개 명령어 |
| SSE4.1 | 2006 | XMM0-XMM15 | 128비트 | DPPS(내적), BLENDPS |
| SSE4.2 | 2007 | XMM0-XMM15 | 128비트 | POPCNT, CRC32, 문자열 |
AVX 계보
| 세대 | 연도 | 레지스터 | 폭 | 주요 특징 |
|---|---|---|---|---|
| AVX | 2011 | YMM0-YMM15 | 256비트 | VEX 인코딩, 3-operand |
| AVX2 | 2013 | YMM0-YMM15 | 256비트 | 정수 256비트, Gather |
| AVX-512F | 2016 | ZMM0-ZMM31 | 512비트 | k0-k7 마스크, EVEX 인코딩 |
| AVX-512 VL | 2016 | YMM/ZMM | 128/256/512비트 | 3가지 폭 EVEX 지원 |
| AVX-512 VNNI | 2019 | ZMM0-ZMM31 | 512비트 | INT8 내적 (신경망 가속) |
| AVX-512 BF16 | 2020 | ZMM0-ZMM31 | 512비트 | BFloat16 지원 |
| AMX | 2022 | 8x 타일 (1KB each) | 16x64B | 매트릭스 곱셈 누적 |
AVX-512는 EVEX 인코딩을 도입하여 4-operand 형식(dest, src1, src2, mask), 임베디드 브로드캐스팅, 임베디드 라운딩 컨트롤, 압축 디스플레이스먼트 주소 지정을 지원한다. k0-k7 오퍼마스크 레지스터를 통해 요소별 조건부 연산이 가능하다.
AMX (Advanced Matrix Extensions)
AMX는 2022년 Intel Sapphire Rapids부터 도입된 매트릭스 연산 전용 확장이다. 각 타일 레지스터는 16줄 x 64바이트 = 1KB이며, BF16/INT8/FP16 데이터 타입의 행렬 곱셈 누적(MMA) 연산을 하드웨어로 수행한다. 코어당 클럭당 2048 INT8 또는 1024 BF16 연산이 가능하다.
AVX10 (2023)
AVX10은 AVX와 AVX-512 계열의 기능 플래그를 정리해 더 단순한 호환성 모델을 제공하려는 확장이다. 2023년 공개 초기에는 256비트와 512비트 프로파일을 함께 제시했지만, 이후 공개 문서 개정에서는 512비트 벡터를 기본 모델로 수렴시키는 방향이 제시되었다.
NEON (ARM Advanced SIMD)
ARM NEON은 ARMv7 NEON(128비트 고정 폭)에서 시작하여 AArch64에서 32 x 128비트 V 레지스터로 확장되었다.
레지스터 구조
- AArch64: 32 x 128비트 V 레지스터 (V0-V31), Q/D/S 별칭 지원
- 데이터 타입: 8/16/32/64비트 정수 (부호/무부호), 16/32비트 부동소수점
- 구조체 로드/스토어: LD2/3/4, ST2/3/4로 인터리빙 패턴 지원
주요 명령어
| 카테고리 | 명령어 예시 | 설명 |
|---|---|---|
| 사칙연산 | ADD, SUB, MUL, MLA, MLS | 팩된 정수/부동소수점 연산 |
| 곱셈 누적 | VQDMULH, FMLA | 포화 곱셈, 곱셈 누적 |
| 비교 | CMEQ, CMGT, CMGE | 요소별 비교 |
| 시프트 | SHL, SSHR, USRA | 논리/산술 시프트 |
| 순열 | TBL, EXT, TRN1/2, ZIP1/2 | 요소 재배치 |
| 내적 | SDOT, UDOT, BFDOT | 정수/BFloat16 내적 |
| 매트릭스 | FMMLA, BFMMLA | 부동소수점 매트릭스 곱셈 누적 |
ARMv8.6-A부터 BFloat16 dot product(BFDOT)와 매트릭스 곱셈 누적(BFMMLA)이 추가되어 머신러닝 워크로드를 가속화한다.
SVE/SVE2 (ARM Scalable Vector Extension)
SVE는 ARMv8.2-A에서 도입된 확장 벡터 ISA로, Vector Length Agnostic (VLA) 프로그래밍 모델을 채택한 것이 핵심 특징이다.
VLA 프로그래밍 모델
SVE에서 하드웨어는 128비트에서 2048비트까지 128비트 단위로 구현할 수 있으며, 소프트웨어는 벡터 길이에 의존하지 않는 바이너리를 작성할 수 있다. 동일한 바이너리가 128비트 ARM 코어와 512비트 ARM 코어에서 모두 실행 가능하다.
// VLA 프로그래밍 예시: 요소별 벡터 덧셈
// 하드웨어 벡터 길이에 무관하게 동작
svint32_t a = svld1_s32(pg, ptr_a);
svint32_t b = svld1_s32(pg, ptr_b);
svint32_t c = svadd_s32_x(pg, a, b);
svst1_s32(pg, ptr_c, c);
레지스터 구조
| 레지스터 타입 | 수 | 크기 | 설명 |
|---|---|---|---|
| Z0-Z31 | 32개 | 128-2048비트 | 벡터 레지스터 (B/H/S/D 별칭) |
| P0-P15 | 16개 | 벡터당 비트 수 | 범용 프레디케이트 (P8-P15: governing) |
| FFR | 1개 | 벡터당 비트 수 | First-Fault 레지스터 |
| VLBI/VLS/VLMAX | 1개 | - | 벡터 길이 관련 레지스터 |
프레디케이트 연산
SVE의 프레디케이트 레지스터는 각 벡터 요소에 대응하는 비트 마스크이다:
PTRUE: 모든 비트가 1인 프레디케이트WHILELT/LE/LO/LB: 루프 카운터 기반 프레디케이트 생성FIRST/LAST: 첫/마지막 참인 요소 반환PAND/POR/PEOR: 프레디케이트 논리 연산
메모리 접근 패턴
| 패턴 | 명령어 | 설명 |
|---|---|---|
| 연속 (Contiguous) | LD1W/D/H/B | 연속 메모리 접근 (프레디케이트 적용) |
| 갭 (Strided) | LD1W/D/H/B (scalar+scalar) | 고정 간격 접근 |
| 인덱스 (Scatter/Gather) | LD1W/D/H/B (scalar+vector) | 임의 인덱스 기반 접근 |
| First-Fault | LDFF1W/D/H/B | 페이지 폴트까지 연속 로드 |
First-Fault 로딩은 SVE의 독특한 기능으로, 가변 길이 배열에서 페이지 폴트 없이 최대한 많은 요소를 로드하고 FFR에 성공한 요소를 기록한다.
SVE2 추가 기능 (ARMv9-A)
SVE2는 SVE의 모든 명령어를 포함하며 추가로:
- 암호화: AESD/AESE/AESMC, SHA256/SHA512 명령어
- 복소수: CADD, CMLA, CADDrot90/180/270
- 정수 N-ary: EOR3, BCAX, SM3SS1/TT/TF/TB/FF
- 히스토그램: HISTCNT
- 비트 조작: BDEP, BEXT, BGRP
GPU SIMD / SIMT
GPU는 SIMT(Single Instruction, Multiple Threads) 모델을 사용하여 대규모 병렬 스레드를 실행한다.
NVIDIA GPU
| 구조 | 설명 |
|---|---|
| Grid | 스레드 블록들의 집합 |
| Thread Block (CTA) | 공유 메모리를 공유하는 스레드 그룹 |
| Warp | 32개 스레드가 lockstep으로 실행 (SIMT) |
- 레지스터 파일 (Volta+): SM당 65,536 x 32비트 레지스터
- Warp 연산:
__shfl_sync()(셔플),__ballot_sync()(투표),__all_sync()/__any_sync()(서술자) - 분기 다이버전스: 워프 내 스레드가 분기 조건에서 갈라지면 양쪽 경로를 순차 실행 후 재수렴
Tensor Cores: FP16, BF16, TF32, FP64, INT8, INT4를 지원하는 매트릭스 곱셈 누적 전용 유닛. SM당 클럭당 최대 2048 INT8 연산이 가능하다.
AMD GPU (RDNA)
| 아키텍처 | 워프 크기 | SIMD 폭 |
|---|---|---|
| GCN (이전) | 64 워프 | SIMD16 x 4 |
| RDNA 1+ | 32 워프 (네이티브) | SIMD32 |
- 레지스터 파일 (RDNA): CU당 256KB 벡터 레지스터
- 캐시 계층: L0 (64KB/WGP) → L1 (256KB/SA) → L2 (2-8MB) → Infinity Cache (최대 128MB)
- 버퍼 연산: BUFFER_LOAD/STORE로 인덱스 기반 접근 지원
RISC-V V Extension
RISC-V V 확장은 런타임에 벡터 설정을 유연하게 조절할 수 있는 점이 특징이다.
벡터 설정
| 파라미터 | 옵션 | 설명 |
|---|---|---|
| SEW | e8/e16/e32/e64 | 표준 요소 폭 |
| LMUL | 1/8, 1/4, 1/2, 1, 2, 4, 8 | 레지스터 묶음 비율 |
| Tail | agnostic/undisturbed | 미사용 요소 처리 방식 |
| Mask | agnostic/undisturbed | 마스크 미사용 비트 처리 |
// RISC-V V 설정 예시
vsetvli t0, a0, e32, m1, ta, ma // SEW=32, LMUL=1, tail=agnostic, mask=agnostic
레지스터 및 메모리 접근
- 벡터 레지스터: 32개 (v0-v31), v0는 마스크 레지스터로도 사용
- VLEN: 최소 128비트, 최대 8192비트
- 메모리 접근: 유닛 스트라이드 (vle32.v), 스트라이드 (vlse32.v), 인덱스 (vluxei32.v/vloxei32.v)
주요 명령어
| 카테고리 | 명령어 예시 |
|---|---|
| 사칙연산 | vadd.vv, vsub.vv, vmul.vv |
| 곱셈 누적 | vmacc.vv, vmadd.vv, vfmacc.vv |
| 비교 | vmseq.vv, vmslt.vv, vmsgt.vx |
| 순열 | vslide1up.vx, vrgather.vv, vcompress.vm |
| 마스크 | vfirst.m, cpop.m, vmsbf.m |
비교/분석
SIMD ISA 종합 비교
| 특성 | x86 AVX-512 | ARM NEON | ARM SVE/SVE2 | NVIDIA GPU | AMD RDNA | RISC-V V |
|---|---|---|---|---|---|---|
| 벡터 폭 | 128/256/512비트 | 128비트 고정 | 128-2048비트 | 워프 32레인 | Wave32/SIMD32 | VLEN 128-8192비트 |
| 레지스터 수 | 32 ZMM | 32 V (AArch64) | 32 Z + 16 P | 65K/SM | 256KB/CU | 32 벡터 |
| 마스크/프레디케이트 | k0-k7 | 없음 | P0-P15 | 스레드 서술자 | 레인 마스크 | v0 마스크 |
| Scatter/Gather | AVX2+ | 구조체 로드만 | 네이티브 지원 | 임의 접근 | 버퍼 연산 | 인덱스 로드 |
| VLA 지원 | 아니오 | 아니오 | 예 | N/A | N/A | 예 (LMUL) |
| 매트릭스 연산 | AMX | FMMLA | FMMLA | Tensor Core | Matrix Core | 없음 (미래) |
| 런타임 벡터 길이 조절 | 불가 | 불가 | 불가 (구현별) | N/A | N/A | vsetvli |
| 복소수 연산 | 제한적 | ARMv8.3-A | SVE2 | 없음 | 없음 | 없음 (미래) |
| 암호화 가속 | AES-NI | crypto 확장 | SVE2 | 없음 | 없음 | 없음 |
레지스터 폭 진화 비교
메모리 접근 패턴 비교
| 접근 패턴 | 설명 | x86 | ARM NEON | SVE | RISC-V V |
|---|---|---|---|---|---|
| 유닛 스트라이드 | 연속 메모리 | MOVAPS | LD1 | LD1W | vle32.v |
| 스트라이드 | 고정 간격 | VPBROAD캐스트 + 인덱스 | 없음 (직접 없음) | LD1W (scalar+scalar) | vlse32.v |
| 인덱스 (Gather) | 임의 위치 | VGATHERDPS | 없음 | LD1W (scalar+vector) | vluxei32.v |
| First-Fault | 폴트 안전 로드 | 없음 | 없음 | LDFF1W | 없음 |
| 구조체 | 인터리빙 로드 | 없음 | LD2/3/4 | 없음 | 없음 |
데이터 타입 지원 비교
| 데이터 타입 | x86 SSE/AVX | ARM NEON | SVE/SVE2 | RISC-V V |
|---|---|---|---|---|
| INT8 | 16/32/64개 | 16개 | VLEN/8개 | VLEN/8개 |
| INT16 | 8/16/32개 | 8개 | VLEN/16개 | VLEN/16개 |
| INT32 | 4/8/16개 | 4개 | VLEN/32개 | VLEN/32개 |
| INT64 | 2/4/8개 | 2개 | VLEN/64개 | VLEN/64개 |
| FP32 | 4/8/16개 | 4개 | VLEN/32개 | VLEN/32개 |
| FP64 | 2/4/8개 | 2개 | VLEN/64개 | VLEN/64개 |
| BFloat16 | AVX-512 BF16 (32개) | BFDOT (별도) | SVE2 (VLEN/16개) | 없음 |
| FP16 | AVX-512 FP16 (32개) | FP16 (8개) | SVE2 (VLEN/16개) | 없음 |
동작 원리
SIMD 명령어 파이프라인
SIMD 명령어는 일반 명령어와 동일한 파이프라인을 사용하지만, 실행 유닛이 훨씬 넓다:
- Fetch/Decode: SIMD 명령어를 디코딩하고 실행 유닛에 배정
- Operand Read: 레지스터 파일에서 128~512비트 피연산자를 읽음
- Execute: 여러 데이터 요소에 병렬로 연산 적용
- Writeback: 결과를 벡터 레지스터에 기록
FMA (Fused Multiply-Add) 파이프라인
┌─────────────────────────────────────────┐
│ 512비트 FMA 유닛 │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ FP32│ │ FP32│ │ FP32│ │ FP32│ ... │
│ │ FMA │ │ FMA │ │ FMA │ │ FMA │ x16 │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────────┘
AVX-512의 경우 512비트 레지스터에 16개의 FP32 요소가 들어가며, FMA 유닛은 이 16개에 대해 동시에 곱셈-누적 연산을 수행한다. 클럭당 최대 32 FP64 FLOPs (2 FMA 유닛 x 8 요소 x 2 FLOP)가 가능하다.
마스크/프레디케이트 메커니즘
x86 AVX-512 마스크
AVX-512는 k0-k7 오퍼마스크 레지스터를 사용하여 요소별 조건부 연산을 수행한다:
ZMM0: [a0, a1, a2, a3, a4, a5, a6, a7] (8x FP64)
k1: [ 1, 0, 1, 1, 0, 1, 0, 1] (마스크)
결과: [a0, -, a2, a3, -, a5, -, a7] (k1=1인 요소만 연산)
VMASKMOVPS, VADDPS zmm1{k1}, zmm2, zmm3 등으로 마스크를 지정할 수 있다.
ARM SVE 프레디케이트
SVE는 벡터당 하나의 비트에 대응하는 프레디케이트 레지스터를 사용한다:
Z0: [a0, a1, a2, a3, a4, a5, a6, a7] (VLEN=256비트, 8x FP32)
P0: [ 1, 1, 0, 1, 1, 1, 0, 1] (각 요소별 비트)
결과: [a0, a1, -, a3, a4, a5, -, a7]
WHILELT 명령어로 루프 카운터 기반 프레디케이트를 자동 생성할 수 있다:
WHILELT P0.B, X0, X1 // X0 < X1이면 P0의 각 비트를 1로 설정
메모리 접근 최적화
연속 접근 (Unit-Stride)
가장 효율적인 접근 패턴으로, 캐시 라인에 맞춰 데이터를 연속적으로 로드한다:
// x86: 8개 FP32 벡터 로드
__m256 v = _mm256_load_ps(ptr); // 256비트 (8x FP32)
// ARM NEON: 4개 FP32 벡터 로드
float32x4_t v = vld1q_f32(ptr); // 128비트 (4x FP32)
Gather (인덱스 기반 접근)
비연속 메모리에 요소를 로드할 때 사용한다:
// x86 AVX2 Gather
__m256i idx = _mm256_set_epi32(28, 24, 20, 16, 12, 8, 4, 0);
__m256 v = _mm256_i32gather_ps(base, idx, 4); // 간격 4바이트
// RISC-V V indexed load
vle32.v v8, (a0), v12 // v12에 바이트 오프셋이 들어있음
SVE First-Fault 로딩
페이지 폴트를 안전하게 처리하면서 최대한 많은 요소를 로드한다:
svuint32_t pg = svwhilelt_b32(i, n);
svfloat32_t v = svldff1_f32(pg, &array[i]); // 폴트 전까지 로드
svbool_t success = svcntp_b32(svptrue_b32(), pg); // 성공한 요소 수
장단점
장점
| 장점 | 설명 |
|---|---|
| 처리량 향상 | 레지스터 폭에 비례하여 연산 처리량 증가 (최대 16x FP32 FMA) |
| 전력 효율 | 명령어 디코딩 오버헤드가 하나이므로 에너지당 FLOP이 높음 |
| 캐시 활용 | 연속 데이터 로드로 캐시 라인 활용도 극대화 |
| 표준화 | SSE/AVX, NEON 등 널리 지원되어 생태계가 성숙 |
| 하드웨어 가속 | Tensor Core, AMX 등 전용 가속기로 AI 워크로드 가속 |
단점
| 단점 | 설명 |
|---|---|
| 프로그래밍 복잡도 | SIMD 전용 컴파일러 최적화, 인트린식 사용 필요 |
| 벡터화 가능 제약 | 데이터 의존성, 조건부 분기로 인해 완전한 벡터화가 어려움 |
| 메모리 정렬 | x86은 정렬되지 않은 접근 시 페널티, SVE/RISC-V V는 더 유연 |
| 다이버전스 비용 | GPU SIMT에서 분기 다이버전스 발생 시 워프 내 스레드가 순차 실행 |
| ** ISA 분열** | x86/ARM/RISC-V 각각 다른 SIMD ISA로 이식성 문제 |
| 리소스 경쟁 | SIMD 실행 유닛이 범용 유닛과 파이프라인 공유 시 경쟁 발생 |
관련 기술
표준 및 사양
| 표준 | 설명 | 비고 |
|---|---|---|
| Intel SDM Vol. 1-4 | x86 ISA 공식 사양 | SSE/AVX/AVX-512/AMX 포함 |
| ARM Architecture Reference Manual | ARM ISA 공식 사양 | NEON/SVE/SVE2 포함 |
| RISC-V V Extension Specification | RISC-V 벡터 ISA 사양 | v1.0 (2021) |
| NVIDIA PTX ISA | NVIDIA GPU 명령어 세트 | SIMT, Tensor Core 포함 |
| AMD RDNA ISA Reference | AMD GPU 명령어 세트 | SIMD32, Wave32 |
관련 문서
참고 문헌
- Intel Corporation. Intel 64 and IA-32 Architectures Optimization Reference Manual. 2023.
- ARM Limited. ARM Architecture Reference Manual for A-profile Architecture. 2023.
- RISC-V International. The RISC-V Vector Extension. v1.0, 2021.
- NVIDIA Corporation. NVIDIA A100 Tensor Core GPU Architecture. 2020.
- AMD Inc. AMD RDNA 2 Architecture. 2020.
- Hennessy, J.L. and Patterson, D.A. Computer Architecture: A Quantitative Approach. 6th Edition. Morgan Kaufmann, 2019.
- Fog, A. Optimizing subroutines in x86 assembly for x86 processors. Technical University of Denmark, 2023.
- NVIDIA Corporation. CUDA C++ Programming Guide. 2023.
핵심 정리
SIMD 아키텍처는 하나의 명령어로 여러 데이터 요소를 동시에 처리하여 수치 해석, 머신러닝, 신호 처리 등의 워크로드에서 높은 처리량을 제공한다. x86은 SSE에서 AVX-512/AMX로, ARM은 NEON에서 SVE/SVE2로, RISC-V는 V Extension로 각각 진화하여 벡터 처리 능력을 지속적으로 확장하고 있다. ARM SVE의 VLA 프로그래밍 모델과 RISC-V V의 런타임 설정은 소프트웨어 호환성과 하드웨어 유연성의 균형을 추구한다. GPU의 SIMT 모델은 대규모 병렬 처리에 최적화되어 있으며, Tensor Core/AMX 같은 매트릭스 전용 가속기는 AI 추론의 핵심 인프라로 자리잡았다. 각 아키텍처의 SIMD 특성을 이해하는 것은 현대 프로세서의 성능 최적화에 필수적이다.