std::offload
이 모듈은 현재 활발히 개발 중입니다. 업스트림에 반영되면 Rust 개발자는 GPU에서 Rust 코드를 실행할 수 있게 됩니다. 저희는 기본적으로 안전하고 편리하며 충분히 빠른 rusty GPU 프로그래밍 인터페이스를 개발하는 것을 목표로 합니다. 여기에는 GPU와 주고받는 데이터를 효율적으로 자동 이동하는 기능이 포함됩니다. (나중에는) 더 높은 수준의 제어가 가능한 고급 인터페이스도 제공할 예정이며, 이 인터페이스는 안전하지 않을 수도 있습니다.
이 구현은 LLVM의 “offload” 프로젝트를 기반으로 합니다. 이 프로젝트는 OpenMP가 GPU에서 Fortran이나 C++ 코드를 실행하는 데 이미 사용하고 있습니다. 프로젝트가 개발 중인 동안에는 사용자가 컴파일 과정을 마치려면 clang 같은 다른 컴파일러를 호출해야 합니다.
상위 수준 컴파일 설계:
저희는 단일 소스, 3패스 컴파일 방식을 사용합니다.
먼저 호스트 코드(예: x86-64)를 컴파일하여, 호스트 코드에 필요한 커널 인스턴스화를 제네릭 인스턴스화까지 포함해 파악합니다. 이 패스는 코드 생성을 수행하지 않습니다. 대신 호스트 코드에 필요한 모든 #[offload_kernel] 인스턴스를 (구체적인 제네릭 인자와 함께) 기록한 매니페스트를 작성합니다.
그다음 디바이스(예: nvptx64, amdgcn-amd-amdhsa, 향후에는 intel)로 오프로드해야 하는 모든 함수를 컴파일하며, 이때 -Zoffload=Device=<manifest>를 통해 매니페스트를 전달합니다. 기록된 커널 인스턴스는 단형화(monomorphization) 루트로 추가되므로, 필요한 제네릭 커널에 대해 코드 생성이 이루어집니다. 현재는 번거로운 #cfg(target_os="") 어노테이션이 필요하지만, 향후에는 오프로드 인트린식을 기반으로 이를 인식할 계획입니다. 이 디바이스 컴파일은 현재 rustc 내부의 쿼리 시스템을 활용하지 않으므로, 지금은 커널을 항상 다시 컴파일합니다. 이 문제는 쉽게 고칠 수 있겠지만, 현재는 기능 추가와 런타임 성능 개선을 우선하고 있습니다. 다만 직접 구현하고 싶으시다면 언제든 연락해 주십시오!
그다음 호스트(예: x86-64)용 코드를 컴파일하며, 오프로딩 로직의 대부분이 이 단계에서 이루어집니다. 호스트 측에서는 openmp 오프로드 런타임을 호출하는 코드를 생성하여 런타임에 타입의 레이아웃(autodiff TypeTree의 단순화된 버전)을 알려 줍니다. 또한 타입 시스템을 사용하여 커널 인자를 디바이스로만 옮겨야 하는지(예: &[f32;1024]), 디바이스에서만 옮겨야 하는지, 아니면 양방향으로 옮겨야 하는지(예: &mut [f64])를 판단합니다. 그런 다음 커널을 실행하고, 실행이 끝나면 런타임에 이 환경을 종료하고 데이터를 (필요한 만큼) 다시 옮기도록 알립니다.
호스트를 위한 세 번째 패스는 디바이스 컴파일에서 생성된 커널 산출물을 불러옵니다. rustc는 일반적으로 빌드 디렉터리 구조를 “추측“하거나 하드코딩해서는 안 되므로, 각 호출에서 커널 산출물과 매니페스트의 경로를 전달받아야 합니다. 이 로직을 cargo에 통합할 수도 있지만, 간단한 cargo 래퍼만 있으면 충분합니다. 더 널리 채택되기 전까지는 이 래퍼를 crates.io를 통해 손쉽게 제공할 수 있습니다.
단일 소스, 단일 패스 컴파일 방식을 고려하고 싶어질 수도 있습니다. 하지만 rustc 프런트엔드(예: AST)의 상당 부분은 죽은 코드(예: 비활성화된 cfg 뒤의 코드)를 모두 제거합니다. 프런트엔드가 두 타깃의 코드를 단순하게 확장하고 로워링(lowering)하도록 하면 같은 심볼이 여러 번 정의되는 문제(및 기타 문제)가 발생합니다. 이제 어떤 심볼이든 두 가지 구현을 가질 수 있다는 점을 rustc의 미들엔드와 백엔드 전체가 인식하도록 만드는 것은 큰 작업입니다. 대안이 약 5줄짜리 cargo 래퍼라면 굳이 컴파일러 전체를 더 복잡하게 만들어야 하는지 의문입니다. 이 방식에서도 저희가 전체 컴파일 파이프라인을 제어하며 호스트 코드와 디바이스 코드를 모두 사용할 수 있으므로, 두 방식 사이에 런타임 성능 차이는 없을 것입니다.