かみのメモ

コンピュータビジョン・プログラムな話題中心の勉強メモ

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");
}

まず、nvccvectorAdd.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を使う方法もあるようですね。

以前試してみたのですが、Windowsarコマンドがなかったり、なぜか実行時にエラーが出たりとハマりどころが多かったので、今回は単純にcuファイルをビルドして混ぜ込む方法でやってみました。

しかし、Windowsのパス周りは本当になんとかしてほしい。。。