使い方
この機能は開発中であり、まだ使用できる状態ではありません。
ここにある手順は、コントリビューター、または最新の進捗を追いたい人向けです。
現在、GPU 上で次の Rust カーネルを起動する作業を進めています。
一緒に試すには、これを src/lib.rs ファイルにコピーしてください。
#![feature(abi_gpu_kernel)]
#![feature(rustc_attrs)]
#![feature(core_intrinsics)]
#![no_std]
#[cfg(target_os = "linux")]
extern crate libc;
#[cfg(target_os = "linux")]
use libc::c_char;
#[cfg(target_os = "linux")]
use core::mem;
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
#[cfg(target_os = "linux")]
#[unsafe(no_mangle)]
#[inline(never)]
fn main() {
let array_c: *mut [f64; 256] =
unsafe { libc::calloc(256, (mem::size_of::<f64>()) as libc::size_t) as *mut [f64; 256] };
let output = c"The first element is zero %f\n";
let output2 = c"The first element is NOT zero %f\n";
let output3 = c"The second element is %f\n";
unsafe {
let val: *const c_char = if (*array_c)[0] < 0.1 {
output.as_ptr()
} else {
output2.as_ptr()
};
libc::printf(val, (*array_c)[0]);
}
unsafe {
kernel(array_c);
}
core::hint::black_box(&array_c);
unsafe {
let val: *const c_char = if (*array_c)[0] < 0.1 {
output.as_ptr()
} else {
output2.as_ptr()
};
libc::printf(val, (*array_c)[0]);
libc::printf(output3.as_ptr(), (*array_c)[1]);
}
}
#[inline(never)]
unsafe fn kernel(x: *mut [f64; 256]) {
core::intrinsics::offload(kernel_1, [256, 1, 1], [32, 1, 1], (x,))
}
#[cfg(target_os = "linux")]
unsafe extern "C" {
pub fn kernel_1(array_b: *mut [f64; 256]);
}
#[cfg(not(target_os = "linux"))]
#[unsafe(no_mangle)]
#[inline(never)]
#[rustc_offload_kernel]
pub extern "gpu-kernel" fn kernel_1(x: *mut [f64; 256]) {
unsafe { (*x)[0] = 21.0 };
}
コンパイル手順
rustc と同じ LLVM でビルドされた clang コンパイラを使用することが重要です。
フルパスなしで clang を呼び出すだけでは、おそらくシステムの clang が使用され、それはおそらく互換性がありません。
そのため、以下の clang/lld 呼び出しを絶対パスに置き換えるか、PATH を適切に設定してください。
まず、デバイス(GPU)コードを生成します。
target-cpu(gfx90a)を、お使いの GPU に適したコードに置き換えてください。これらはしばしば「LLVM ターゲット名」と呼ばれます1。
RUSTFLAGS="-Ctarget-cpu=gfx90a --emit=llvm-bc,llvm-ir -Zoffload=Device -Csave-temps -Zunstable-options" cargo +offload build -Zunstable-options -r -v --target amdgcn-amd-amdhsa -Zbuild-std=core
その後、次の手順の前に、現時点では target/release/deps/<lib_name>.bc を lib.bc にコピーする必要があるかもしれません。
次に、ホスト(CPU)コードを生成します。
RUSTFLAGS="--emit=llvm-bc,llvm-ir -Csave-temps -Zoffload=Host=/p/lustre1/drehwald1/prog/offload/r/target/amdgcn-amd-amdhsa/release/deps/device.bin -Zunstable-options" cargo +offload build -r
この呼び出しも多くの処理を行い、LLVM オフロード用に複数の中間ファイルを生成します。 現時点ではオフロード手順の大部分を rustc に統合済みですが、まだ 1 つのバイナリ呼び出しが残っています。
"clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=/ABSOlUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "bare" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/ABSOLUTE_PATH_TO/crtbeginS.o" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "target/<GPU_DIR>/release/host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/ABSOLUTE_PATH_TO/crtendS.o" "/lib/../lib64/crtn.o"
これらのファイルへのパスを自分のシステム上で探してみることもできます。
ただし、パスを修正するのではなく、ベアモードの OpenMP の例をコピーして、それを自分の clang でコンパイルすることで再生成することをお勧めします。
clang 呼び出しに -### を追加すると、個々の手順を確認できます。
複数の手順が表示されるので、clang-linker-wrapper の例を探してください。
次の呼び出しで c++ の例をコンパイルしたときに得られた一時ファイルではなく、必ず host.o ファイルへのパスを含めるようにしてください。
myclang++ -fuse-ld=lld -O3 -fopenmp -fopenmp-offload-mandatory --offload-arch=gfx90a omp_bare.cpp -o main -###
最後の手順では、これでバイナリを実行できます。
./main
The first element is zero 0.000000
The first element is NOT zero 21.000000
The second element is 0.000000
メモリ転送に関する詳細情報を得るには、次のようにして情報出力を有効にできます。
LIBOMPTARGET_INFO=-1 ./main
-
https://rocm.docs.amd.com/en/latest/reference/gpu-arch-specs.html または https://developer.nvidia.com/cuda/gpus。あるいは、
rustc --print target-cpusを確認してください。 ↩