- Rust로 작성한 하나의 코드베이스가 CUDA, Vulkan(SPIR-V), Metal, DirectX 12, WebGPU, CPU 등 모든 주요 GPU 및 CPU 플랫폼에서 동작하는 데모 프로젝트 공개
- 기존 GPU 프로그래밍은 GLSL, HLSL 등 별도의 언어 사용으로 복잡성과 중복 문제가 발생하지만 이번 데모는 순수 Rust 코드만으로 모든 GPU 타겟 지원
- 주요 구현체로 Rust GPU(SPIR-V), Rust CUDA(NVVM IR), Naga(GPU 언어 변환 계층) 프로젝트를 통- 동일한 비토닉 정렬 알고리듬이 CPU와 모든 GPU에서 동작하며, Rust의 no_std, 조건부 컴파일, Newtype, Enum, Trait 등 언어 기능이 GPU 코드에도 그대로 적용됨
- 아직 공식 rustc 통합, 디버깅, API 일관성 등 개선 과제가 남아 있으나, GPU 크로스플랫폼 컴퓨팅의 전환점이 되는 시도임
Rust 기반 GPU 크로스플랫폼 컴퓨팅의 실현
프로젝트 소개 및 의의
- 하나의 Rust 코드베이스로 CUDA(NVIDIA), Vulkan(SPIR-V), Metal(Apple), DirectX 12(Windows), WebGPU(브라우저), CPU 등에서 동일한 커널 코드 실행
- 셰이더 또는 커널 전용 언어(GLSL, HLSL 등) 사용 없이, 순수 Rust 코드만으로 GPU 및 CPU에서 동일한 연산 처리 가능함
- 이는 GPU·CPU 간 코드 중복 및 복잡도를 대폭 줄이고, Rust 생태계의 도구 및 언어 장점(타입 안정성, 테스트, 문서화, 빌드 관리 등)을 GPU 프로그래밍에도 적용함
배경
- 전통적 GPU 프로그래밍은 각 플랫폼별로 특화된 셰이더 언어(예:GSL, HLSL, MSL, WGSL 등) 사용이 필수임
- 이에 따라 CPU와 GPU 코드가 분리되고 로직 중복 및 개발 복잡성 증가 문제를 낳음
- Rust 커뮤니티는 이에 대응해 일반 Rust를 GPU 대상으로 컴파일하는 접근을 추구 중임
- Rust GPU: Rust 코드를 SPIR-V로 컴파일, Vulkan 및 SPIR-V 호환 GPU에서 동작
- Rust CUDA: Rust 코드를 NVIDIA CUDA용 IR(NVVM IR, PTX)로 컴파일, CUDA에서 실행
- Naga: 다양한 GPU 언어( WGSL, SPIR-V, GLSL, MSL, HLSL) 간 변환을 지원하는 중간 계층(주로 wgpu 프로젝트에서 사용). 백엔드 이식성을 담당
- 각 프로젝트가 독립적으로 시작되어 API, 구조가 달랐으나, 최근 협력을 통해 공동 코드베이스의 GPU 실행이 실현됨
구현 방식
- 예제 데모에서는 비토닉 정렬 알고리듬을 단일 Rust 코드로 구현하고, GPU와 CPU의 모든 대상으로 동일 코드가 실행됨
- 주요 컴포넌트 용어
- Host: CPU에서 실행되는 Rust 코드(작업 시작)
- Device: 커널이 실제로 실행되는 GPU/CPU
- Driver API: CUDA, Vulkan, Metal, DX12 등, 장치와 통신용 저수준 API
- Backend: 러스트에서 드라이버 API 대상으로 추상화 제공(cust, ash, wgpu 등)
- 러스트의 feature 플래그와 타깃 조합을 통해 백엔드 선택 및 빌드 제어 가능
- 예: wgpu, ash, cuda 등 각 백엔드 별 독립 빌드 옵션 제공
- 여러 백엔드를 하나의 바이너리로 빌드해 런타임에서 동적으로 선택하는 구조 구현 가능
커널 컴파일 흐름
- 타깃 및 feature에 따라 GPU 실행 바이너리(SPIR-V, PTX 등)를 빌드 시 생성, 객체 파일에 임베드됨
- 런타임에서 임베드된 커널을 로드, Naga 등을 통해 플랫폼별 요구 포맷으로 변환 후 실행
- 예:
- macOS: SPIR-V를 MSL로 변환→Metal 실행
- Windows: SPIR-V를 HLSL로 변환→DX12 실행
- Linux/Android: SPIR-V→Vulkan 실행
- CUDA: PTX를 SASS로 컴파일, GPU 업로드 및 실행
Rust 친화적 GPU 코딩 기법
-
no_std 지원
- GPU에는 OS 지원이 없으므로 Rust의
no_std사용이 필수임 - 기본 Rust 생태계가 내장적으로 임베디드, 펌웨어, 커널 등 OS 없는 환경을 가정함에 따라 GPU도 별도 "특수 모드" 없이 Rust 표준 방식으로 지원 가능함
- GPU에는 OS 지원이 없으므로 Rust의
-
조건부 컴파일
- cfg 속성과 feature 플래그 조합으로 플랫폼 구분 코드와 GPU/CPU 구분 코드를 명확하고 간결하게 작성 가능함
- IDE와 컴파일러가 모든 코드 경로를 이해하여, 높은 코드 신뢰성 및 생산성 확보
-
newtype 활용
- GPU에서 실수할 수 있는 암묵적 인덱스·구조체 매핑을 newtype 사용으로 타입 레벨에서 오류 방지
- #[repr(transparent)] 속성으로 실질적인 오버헤드 없이 타입 추상화 가능
-
Enum과 안전한 표현
- 매직 넘버 사용 대신 Rust Enum 사용, #[repr(u32)] 적용으로 네이티브 정수 매핑 확보
- 패턴 매칭과 exhaustiveness(모든 경우 분기 처리)로 안전한 코드 구성
- 단, CPU-GPU 간 공유 버퍼에 Enum 값을 주고받을 때는 모든 값이 올바른 Enum이어야 하므로 주의 필요
-
Trait 기반 제네릭 알고리듬
- Trait을 이용해 다양한 값 타입에 대해 공통된 비교, 변환, 연산 등 GPU 연산 추상화 제공
- 제네릭 알고리듬에 trait bound를 명확하게 지정하여 type safety와 최적성 양립
-
#[inline] 및 성능 최적화
- #[inline] 사용으로 추상화 계층이 실제 컴파일 결과에서 사라지도록 유도
- GPU 특성(성능, 스택 부족 등)상 추상화의 비용이 없도록 설계됨
-
Struct 조합 및 의미론적 그룹화
- 복잡한 GPU 파라미터를 의미 단위로 묶어 struct로 관리, 타입 안정성 확보 및 파라미터 폭증 방지
- Smart constructor 패턴으로 invalid 상태를 컴파일 단계에서 차단
-
메모리 레이아웃 및 #[repr(C)] 제어
- GPU와의 데이터 호환성을 위해 #[repr(C)]로 구조체 레이아웃을 명시적으로 지정
- 향후 GPU별 padding 자동화 등 추가 언어 지원 필요성 언급
-
패턴 매칭
- Switch/case의 확장된 개념으로, GPU 코드 내 모든 분기 및 상태를 명확하게 처리할 수 있음
- 컴파일러에 의한 코드 경로 체크 및 성능 최적화 가능
-
제네릭 함수
- 데이타 타입에 구애받지 않고 여러 타입에 대해 동일 로직 구현
- trait bound, 모노모피제이션 등으로 유지보수성·테스트 용이성 강화
-
Derive 매크로
- Copy, Clone, Debug, PartialEq, Pod 등 GPU-적합 트레잇 자동 구현
- 안전성 및 코드 보일러플레이트 최소화
-
모듈 시스템, 워크스페이스 관리
- Rust의 패키지/모듈 시스템으로 호스트 코드, 커널, 타입, 백엔드 별 소스 구조화
- Cargo workspace, workspace dependency로 크레이트 간 의존성 일관성, 유지보수 편의성 확보
-
포매팅, 린트, 문서화
- rustfmt, clippy 등 Rust 표준 도구와 완전히 동일한 방식으로 GPU 코드 관리, 일관된 품질 유지 가능
- Doc comment, cargo doc으로 GPU 코드도 문서화
-
빌드 스크립트
- Cargo의 build.rs를 통해 feature flag 기반 커널 빌드 및 바이너리 임베드 자동화
-
유닛 테스트 및 개발 생산성
- GPU 커널 코드를 CPU에서도 테스트할 수 있어 개발 및 버그 탐지 용이
- println 디버그, gdb/lldb 등 전통 도구 사용 가능
- Vulkan 커널도 소프트웨어 드라이버(SwiftShader, lavapipe)로 CI 테스트 가능
- 테스트 및 코드 커버리지 측정, property-based 테스트 등 서드파티 도구와 원활 연동
미완성된 개발자 경험 및 과제
- GPU 백엔드가 공식 Rust 컴파일러에 내장되지 않아 별도 코드젠 백엔드(spirv, nvvm) 사용 및 nightly 버전 고정 필요
- CUDA 타깃은 NVIDIA의 LLVM 7.1에 종속적이어서 최신 리눅스 배포판에서 별도 빌드 필요
- 커널 빌드·디버깅 경험 부족, 에러 트레이싱/디버그 정보 미흡 문제가 있음
- Rust GPU와 Rust CUDA의 API, 표준 라이브러리 명칭 등이 달라 혼란 야기
- 장기적으로 Rust 언어와 생태계 전반에 GPU 위주의 일관성, 통합성 강화 필요
커뮤니티 참여 및 미래
- Rust로 모든 주요 GPU 플랫폼에서 동일 코드 실행이 실현됨
- 앞으로는 빌드 및 디버깅 개선, Rust 언어 및 API 지원 확대, 성능 튜닝 등이 과제로 남아있음
- 참여 및 기여를 원하는 개발자는 rust-gpu, rust-cuda의 GitHub 레포지토리를 참조할 것