29
C#, C++/CLI CUDA による 画像処理ことはじめ επιστημη [email protected] Microsoft MVP for Visual C++ Jan.2004for Visual Studio and Development Technologies Oct.2015NVIDIA Ambassador for CUDA Apr.2015

C#, C/CLI と CUDAによる画像処理ことはじめ

Embed Size (px)

Citation preview

Page 1: C#, C/CLI と CUDAによる画像処理ことはじめ

C#, C++/CLI と CUDA による

画像処理ことはじめεπιστημη [email protected]

・Microsoft MVP

for Visual C++ Jan.2004~for Visual Studio and Development Technologies Oct.2015~

・NVIDIA Ambassador for CUDA Apr.2015~

Page 2: C#, C/CLI と CUDAによる画像処理ことはじめ

MAXWELL ARCHITECTUREGEFORCE GTX800/900 SERIESGEFORCE GTX750, TEGRA X1

Streaming Multiprocessor■ 128 CUDA-cores

■ L1-cache

■ shared memory

■ …and more

Page 3: C#, C/CLI と CUDAによる画像処理ことはじめ

GPU

GPU

memory

L2 cache

PCI

bus

V

I

D

E

O

(だいたいあってる) グラボ の なかみ

Giga Thread Engine

Page 4: C#, C/CLI と CUDAによる画像処理ことはじめ

※ ココ↑はそんなに速くない

Page 5: C#, C/CLI と CUDAによる画像処理ことはじめ

native(C++) application

Page 6: C#, C/CLI と CUDAによる画像処理ことはじめ

NATIVE はフツーにCUDAを呼べるけど…

host

memorydevice

memory

PCI

native app.

コレな。

Page 7: C#, C/CLI と CUDAによる画像処理ことはじめ

仲介役

managed

⇔native

managed(C#) application

↑ コレが必要

Page 8: C#, C/CLI と CUDAによる画像処理ことはじめ

MANAGED は NATIVE を直接呼べない

host

memorydevice

memory

PCI

CLR

managed app.

コレな。

Page 9: C#, C/CLI と CUDAによる画像処理ことはじめ

MANAGED と NATIVE の仲介役

host

memorydevice

memory

PCI

CLR

managed app.

native assembly

call

Page 10: C#, C/CLI と CUDAによる画像処理ことはじめ

C++/CLI で作る「仲介役」

見た目(インタフェース)はmanaged

ナカミ(実装)はnative

native assembly

Page 11: C#, C/CLI と CUDAによる画像処理ことはじめ

CUDAプログラミングで用意するもの

Graphic-cardNVIDIA-GPU を積んだやつなら大抵OK

Visual Studio 2013 (Community edition でも無問題)

2015はCUDA Toolkitが未対応 (´・ω・`) ショボーン /

CUDA Toolkit 7.5コンパイラ(nvcc)+runtime, ライブラリ, profiler etc. / Visual Studio の add-on

Page 12: C#, C/CLI と CUDAによる画像処理ことはじめ

HOST CODE と DEVICE CODE

__host__ __global__ __device__

※ __global__ : host から呼べる device 側の関数

Host(CPU) で動く関数 Device(GPU) で動く関数

Page 13: C#, C/CLI と CUDAによる画像処理ことはじめ

CUDAのコードはHOST/DEVICE混在(1)__device__ int device_increment(int n) { return n+1; }

__global__ void kernel_increment(int* data, unsigned int size) {

unsigned int i = blockDim.x * blockIdx.x + threadIdx.x;

if ( i < size ) {

data[i] = device_increment(data[i]);

}

}

__host__ void launch_increment(int* data, unsigned int size) {

kernel_increment<<<2000,100>>>(data, size);

} 100スレッドを1ブロックとして2000ブロック分着火せよ!

Page 14: C#, C/CLI と CUDAによる画像処理ことはじめ

CUDAのコードはHOST/DEVICE混在(2)int main() {

vector<int> array; // host-memory

size_t bytesize = array.size()*sizeof(int);

int* d_array; // device-memory

cudaMalloc(&d_array, bytesize); // allocate device-memory

// host→device , launch kernel , device→host

cudaMemcpy(d_array, array.data(), bytesize, cudaMemcpyHostToDevice);

launch_increment(d_array, array.size());

cudaMemcpy(array.data(), d_array, bytesize, cudaMemcpyDeviceToHost);

cudaFree(d_array); // deallocate device-memory

}

Page 15: C#, C/CLI と CUDAによる画像処理ことはじめ

コンパイルのからくり

device

host

nvcc

Visual

C++

PTX

OBJ

~.cu ~.obj

GPU機械語

CPU機械語

Link

CUDA runtime ~.exe

Page 16: C#, C/CLI と CUDAによる画像処理ことはじめ

WRAPPERのつくりかた 1: CLR クラスライブラリ

Page 17: C#, C/CLI と CUDAによる画像処理ことはじめ

WRAPPERのつくりかた 2: ビルド カスタマイズ

Page 18: C#, C/CLI と CUDAによる画像処理ことはじめ

WRAPPERのつくりかた 3: CUDA RUNTIME

Page 19: C#, C/CLI と CUDAによる画像処理ことはじめ

WRAPPERのつくりかた 4: 64BIT-BUILD

Page 20: C#, C/CLI と CUDAによる画像処理ことはじめ

C++/CLI によるwrapper

• constructor

• allocate device-mem

• methods

• pin managed (raw)

• copy raw → device-mem

• launch kernel

• copy device-mem → raw

• un-pin managed (raw)

• destructor

• deallocate device-mem

managed(C#) application

Page 21: C#, C/CLI と CUDAによる画像処理ことはじめ

public ref class Wrapper {

private:

managed側には見せたくない/見せる必要のないもの

public:

// コンストラクタ

Wrapper() { 前準備 }

// デストラクタ

~Wrapper() { this->!Wrapper(); }

// ファイナライザ

!Wrapper() { あとしまつ }

void do_something() {

nativeなナニかを操作する

}

};

Page 22: C#, C/CLI と CUDAによる画像処理ことはじめ

public ref class Wrapper {

private:

float* data_; // device-memory

int size_;

public:

// コンストラクタ

Wrapper(int n) : size_(n) {

float* ptr;

cudaMalloc(&ptr, size_*sizeof(float));

data_ = ptr;

}

// デストラクタ

~Wrapper() { this->!Wrapper(); }

// ファイナライザ

!Wrapper() {

cudaFree(data_);

}

たとえば…こんなコード。

Page 23: C#, C/CLI と CUDAによる画像処理ことはじめ

public ref class Wrapper {

// method

void do_something(cli::array<float>^ buffer) {

if ( buffer->Length <= size_ ) {

pin_ptr<float> pin = &buffer[0];

cudaMemcpy(data_, pin, …); // host -> device

launch_kernel(…); // launch kernel

cudaMemcpy(pin, data_, …); // device -> host

}

}

たとえば…こんなコード。

Page 24: C#, C/CLI と CUDAによる画像処理ことはじめ

おまけ: C++/CLIがめんどくせーならこんなのも

http://kunzmi.github.io/managedCuda/

JCuda の .NET 版

Page 25: C#, C/CLI と CUDAによる画像処理ことはじめ

DEMO

Page 26: C#, C/CLI と CUDAによる画像処理ことはじめ

画像をキャプチャし 処理を施して Windowに表示

Page 27: C#, C/CLI と CUDAによる画像処理ことはじめ

Camera Capture

Image Processing

C++/CLI wrapper-1

CUDA

OpenCV

WPF Application

C++/CLI wrapper-2

C#

Page 28: C#, C/CLI と CUDAによる画像処理ことはじめ

BGR BGR Gray Gray

SobelV

SobelH

floatuchar3 ucharuchar3

float

float

NPP

cudaMemcpy

BGR

uchar3

Page 29: C#, C/CLI と CUDAによる画像処理ことはじめ

THANK YOU, LET’S ENJOY CUDA!

επιστημη

mail: [email protected]

blog: http://blog.zaq.ne.jp/fareastprogramming/

facebook: https://www.facebook.com/cppepisteme

twitter: @epitwit