RustからCUDAのカーネルを呼んでみた【Windows】
RustとCUDAを連携させて遊んでみた。
参考にしたのはこちらのサイト↓ qiita.com
ほとんどこの記事の通りに書けばよいのですが、私の環境はWindowsで、build.rs周りで若干苦戦したのでその辺りについてまとめてみます。
環境
普通にVS Community 2017、CUDA Toolkit、Rustをインストールした環境です。 RustはNightlyを使っていますが、Stableでも動くはずです。
Windows 10 Pro Visual Studio 2017 nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2018 NVIDIA Corporation Built on Wed_Apr_11_23:16:30_Central_Daylight_Time_2018 Cuda compilation tools, release 9.2, V9.2.88 rustc 1.28.0-nightly (e3bf634e0 2018-06-28)
build.rs
今回書いたbuild.rsです。
use std::env; use std::process::Command; fn main() { let out_dir = env::var("OUT_DIR").unwrap(); Command::new("nvcc") .args(&["src/vectorAdd.cu", // static library (.lib) を出力させる "-lib", // Cコンパイラのパスを指定 "-ccbin", r"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\Hostx64\x64\cl.exe", // Cコンパイラにwarning 4819を無視するよう指示 "-Xcompiler", "-wd4819", "-o"]) .arg(&format!("{}/kernel.lib", out_dir)) .status() .unwrap(); println!("cargo:rustc-link-search=native=C:/PROGRA~1/NVIDIA~2/CUDA/v9.2/lib/x64"); println!("cargo:rustc-link-search=native={}", out_dir); println!("cargo:rustc-link-lib=cudart"); println!("cargo:rustc-link-lib=kernel"); }
まず、nvcc
でvectorAdd.cu
をビルドする部分について解説します。
Visual Cのコンパイラcl.exe
はPATHに追加されていないので、nvcc
に場所を教えてやる必要があります。
ついでに、CUDAのヘッダファイルの文字コードのせいでC4819の警告が大量に出てくるので、これを無視するように指定しておきます。
Rustのビルドに混ぜ込むためにはオブジェクトファイルではなく静的ライブラリファイルが必要らしいので、-lib
オプションを付け、kernel.lib
を吐き出すように指定しておきます。
次に、rustc
のオプションを指定する部分について。
やっていることは、単にライブラリのサーチパスを追加しているだけです。
ただしWindowsの場合、パスにスペースを含むケースがあります。
スペースを含んだままrustc
に渡すとオプションが正しく認識されないのでビルドに失敗してしまいます。
また、いまのところcargo:rustc-link-search=native='path~~'
のようにクォーテーションで囲っても正しく認識してくれないようです。
ということで、PROGRA~1
のような短縮記法を使ってパスを指定します(短縮したパス名の調べ方はこちらのページなどを参考に)。
ちなみにライブラリのサーチパスの追加等はcargoのconfigファイルからでも行えるようです(ドキュメント)。
自分の環境ではこれで動きました。
雑感
この他にも、nvptxとかaccelとかのcrateを使う方法もあるようですね。
以前試してみたのですが、Windowsにar
コマンドがなかったり、なぜか実行時にエラーが出たりとハマりどころが多かったので、今回は単純にcuファイルをビルドして混ぜ込む方法でやってみました。
しかし、Windowsのパス周りは本当になんとかしてほしい。。。