SlideShare a Scribd company logo
.NET から CUDA を使うひとつの方法
C++/CLI による WRAPPER のつくりかた
episthmh epi@c.zaq.jp
Microsoft MVP for Visual C++ Jan.2004~
NVIDIA CUDA Ambassador for Apr.2015~
2015-1075
Hall-B1 16:20~
WINDOWS APPLICATION
CUI
Console (stdin/stdout)
GUI
Win API
MFC
Windows Forms
WPF
native : C/C++
managed : .NET (C#,VB etc.)
legacy…
MANAGED は直接 CUDA を呼べない…
host
memory
device
memory
PCI-bus
CLR
managed app.
MANAGED と NATIVE の仲介役
host
memory
device
memory
PCI-bus
CLR
managed app.
native assembly
call
C++/CLI で作る「仲介役」
見た目(インタフェース)はmanaged
ナカミ(実装)はnative
native assembly
PCI-bus
サンプル : SAXPY
Y[i] = alpha * X[i] + Y[i] (i = 0..N-1)
C# / Windows Forms app.
絵ヅラはC#, 計算はCUDA
C++/CLIが両者を仲介
WRAPPERのつくりかた 1: CLR クラスライブラリ
WRAPPERのつくりかた 2: ビルド カスタマイズ
※ C++/CLI プロジェクト内で デバイス・コード(~.cu) をコンパイルできます
WRAPPERのつくりかた 3: CUDA RUNTIME
WRAPPERのつくりかた 4: 64BIT PLATFORM
※ CUDA 7.0 以降、多くのCUDAライブラリは 64bit-only です
SAXPY DEVICE/HOST CODE
__global__ void kernel_saxpy(float alpha, const float* x, float* y,
unsigned int size) {
unsigned int i = blockDim.x * blockIdx.x + threadIdx.x;
if ( i < size ) { y[i] = alpha * x[i] + y[i]; } // Saxpy!
}
__host__ void device_saxpy(float alpha, const float* x, float* y,
unsigned int size) {
unsigned int block = 256U; unsigned int grid = (size + block -1U)/block;
kernel_saxpy<<<grid,block>>>(alpha, x, y, size);
}
※ device-code および それを呼び出すhost-codeは ~.cu に記述します
REF CLASS SAXPY : ~.h public部
namespace CUDA {
public ref class Saxpy {
private:
…
public:
Saxpy(); // コンストラクタ
~Saxpy(); // デストラクタ
!Saxpy(); // ファイナライザ
void calculate(float alpha, cli::array<float>^ x, cli::array<float>^ y);
};
} ※ C++/CLI: cli::array<float>^ は C#: float[] に相当します
REF CLASS SAXPY : ~.h private部
namespace CUDA {
public ref class Saxpy {
private:
float* dx_; // device-memory X[]
float* dy_; // device-memory Y[]
size_t bsize_; // dx_/dy_の大きさ(bytes)
void allocate(size_t new_bsize); // dx_/dy_を確保する
void deallocate() { // dx_/dy_を解放する
cudaFree(dx_); dx_ = nullptr;
cudaFree(dy_); dy_ = nullptr;
}
…
}
※利用者(C#,VB)に成り代わって device-memory を確保/解放します
namespace CUDA {
Saxpy::Saxpy() : dx_(nullptr), dy_(nullptr), bsize_(0U) {}
Saxpy::~Saxpy() { this->!Saxpy(); } // 明示的にファイナライザを呼ぶ
Saxpy::!Saxpy() { deallocate(); } // device-mem. を解放する
…
}
※ ファイナライザ : !クラス名() をお忘れなく
REF CLASS SAXPY : ~.cpp
namespace CUDA {
void Saxpy::allocate(size_t new_bsize) {
// 足りないときは一旦解放し、再確保
if ( bsize_ < new_bsize ) {
deallocate();
bsize_ = new_bsize;
float* ptr;
cudaMalloc(&ptr, bsize_); dx_ = ptr;
cudaMalloc(&ptr, bsize_); dy_ = ptr;
}
}
}
※ cudaMalloc(&dx_, bsize_) とは書けません
namespace CUDA {
void Saxpy::calculate(float alpha, array<float>^ x, array<float>^ y) {
unsigned int size = x->Length; if ( size != y->Length ) return;
allocate((size_t)(size*sizeof(float)));
// host → device
pin_ptr<float> hx = &x[0];
cudaMemcpy(dx_, hx, size*sizeof(float), cudaMemcpyHostToDevice);
pin_ptr<float> hy = &y[0];
cudaMemcpy(dy_, hy, size*sizeof(float), cudaMemcpyHostToDevice);
// kernel-call
device_saxpy(alpha, dx_, dy_, size);
// device → host
cudaMemcpy(hy, dy_, size*sizeof(float), cudaMemcpyDeviceToHost);
}
}
※ pin_ptr<float> でピン留めします
HOW TO USE IN .NET
※ 参照設定をお忘れなく
HOW TO USE IN C# : ~.cs
public partial class Form1 : Form {
private CUDA.Saxpy saxpy = new CUDA.Saxpy(); // 作って
private void btnCalc_Click(object sender, EventArgs e) {
if ( lstX.Items.Count != lstY.Items.Count ) return;
float[] x = …;
float[] y = …;
float alpha = …;
saxpy.calculate(alpha, x, y); // 呼ぶ!
…
}
※ インスタンスを生成(new)し、メソッドを呼び出すだけ
BITMAPを扱うには?
CUDAで画像処理
構造はSaxpyとおなじ。
配列じゃなく、
Bitmapの先頭アドレスを
CUDAに渡します。
namespace CUDA {
public ref class SepiaConverter {
public:
SepiaConverter();
~SepiaConverter();
!SepiaConverter();
// image(元画像)をcolor_にコピーし、モノクロ化
void LoadImage(System::IntPtr image, int width, int height, int stride);
// モノクロ画像を色調変換し、imageにコピー
void ConvertSepia(System::IntPtr image, float u, float v);
…
};
}
※ System::IntPtr が void* に相当します
namespace CUDA {
void SepiaConverter::ConvertSepia(System::IntPtr image, float u, float v) {
// 色調変換し、結果を color_ に
…
// 結果をコピー
size_t bsize = height_ * stride_;
void* ptr = static_cast<void*>(image);
cudaMemcpy(ptr, color_, bsize, cudaMemcpyDeviceToHost);
}
}
※ System::IntPtr は void* にキャストできます
// セピア変換
private CUDA.SepiaConverter converter_; // C++/CLIで作ったwrapper
private void convert_sepia(float u, float v) {
// Bitmapを生成し、 LockBitsで固定
var bmp = new Bitmap(幅, 高さ);
var data = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
// 色調変換
converter_.ConvertSepia(data.Scan0, u, v);
bmp.UnlockBits(data);
picOutput.Image = bmp;
picOutput.Invalidate();
}
※ IntPtr BitmapData.Scan0 が画像の先頭アドレスです
HAVE FUN!
BLOG http://blog.zaq.ne.jp/fareastprogramming
https://www.facebook.com/cppepisteme
@epitwit
http://codezine.jp/author/352CodeZine

More Related Content

PDF
C#, C/CLI と CUDAによる画像処理ことはじめ
PDF
1070: CUDA プログラミング入門
PDF
2015年度GPGPU実践プログラミング 第5回 GPUのメモリ階層
PDF
いまさら聞けない!CUDA高速化入門
PDF
1076: CUDAデバッグ・プロファイリング入門
PPTX
Gstreamer Basics
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
Intro to SVE 富岳のA64FXを触ってみた
C#, C/CLI と CUDAによる画像処理ことはじめ
1070: CUDA プログラミング入門
2015年度GPGPU実践プログラミング 第5回 GPUのメモリ階層
いまさら聞けない!CUDA高速化入門
1076: CUDAデバッグ・プロファイリング入門
Gstreamer Basics
ARM CPUにおけるSIMDを用いた高速計算入門
Intro to SVE 富岳のA64FXを触ってみた

What's hot (20)

PDF
CUDAプログラミング入門
PDF
TVM の紹介
PDF
CUDAメモ
PDF
QEMUでARM64bitベアメタルプログラミング
PPTX
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
PDF
コンテナにおけるパフォーマンス調査でハマった話
PDF
2015年度先端GPGPUシミュレーション工学特論 第9回 偏微分方程式の差分計算 (移流方程式)
PDF
2015年度GPGPU実践プログラミング 第10回 行列計算(行列-行列積の高度な最適化)
PDF
Hopper アーキテクチャで、変わること、変わらないこと
PDF
1072: アプリケーション開発を加速するCUDAライブラリ
PDF
2015年度先端GPGPUシミュレーション工学特論 第6回 プログラムの性能評価指針 (Flop/Byte,計算律速,メモリ律速)
PPTX
TVMの次期グラフIR Relayの紹介
PDF
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
PDF
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
PDF
2015年度先端GPGPUシミュレーション工学特論 第2回 GPUによる並列計算の概念と メモリアクセス
PDF
ソフト高速化の専門家が教える!AI・IoTエッジデバイスの選び方
PDF
プログラムを高速化する話Ⅱ 〜GPGPU編〜
PDF
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
PDF
ソフトウェア品質技術の歴史を振り返る - ソフトウェア品質測定を中心に -
PPTX
ゲーム向けマネジメントツール 「Hansoft」の概要と コンシューマ開発で1年間 運用した事例
CUDAプログラミング入門
TVM の紹介
CUDAメモ
QEMUでARM64bitベアメタルプログラミング
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
コンテナにおけるパフォーマンス調査でハマった話
2015年度先端GPGPUシミュレーション工学特論 第9回 偏微分方程式の差分計算 (移流方程式)
2015年度GPGPU実践プログラミング 第10回 行列計算(行列-行列積の高度な最適化)
Hopper アーキテクチャで、変わること、変わらないこと
1072: アプリケーション開発を加速するCUDAライブラリ
2015年度先端GPGPUシミュレーション工学特論 第6回 プログラムの性能評価指針 (Flop/Byte,計算律速,メモリ律速)
TVMの次期グラフIR Relayの紹介
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
2015年度先端GPGPUシミュレーション工学特論 第2回 GPUによる並列計算の概念と メモリアクセス
ソフト高速化の専門家が教える!AI・IoTエッジデバイスの選び方
プログラムを高速化する話Ⅱ 〜GPGPU編〜
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
ソフトウェア品質技術の歴史を振り返る - ソフトウェア品質測定を中心に -
ゲーム向けマネジメントツール 「Hansoft」の概要と コンシューマ開発で1年間 運用した事例
Ad

Similar to 1075: .NETからCUDAを使うひとつの方法 (20)

KEY
NVIDIA Japan Seminar 2012
PDF
Maxwell と Java CUDAプログラミング
PDF
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
PDF
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
KEY
CUDAを利用したPIV解析の高速化
PDF
200625material naruse
KEY
関東GPGPU勉強会 LLVM meets GPU
PDF
C base design methodology with s dx and xilinx ml
DOC
GPGPUによるパーソナルスーパーコンピュータの可能性
PDF
第12回 配信講義 計算科学技術特論B(2022)
PPTX
C++ AMPを使ってみよう
PDF
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
PDF
20130126 sc12-reading
PDF
20190625 OpenACC 講習会 第2部
PDF
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
PDF
怪しいWindowsプログラミング
PDF
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
PDF
2015年度GPGPU実践プログラミング 第12回 偏微分方程式の差分計算
KEY
PyOpenCLによるGPGPU入門
NVIDIA Japan Seminar 2012
Maxwell と Java CUDAプログラミング
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
CUDAを利用したPIV解析の高速化
200625material naruse
関東GPGPU勉強会 LLVM meets GPU
C base design methodology with s dx and xilinx ml
GPGPUによるパーソナルスーパーコンピュータの可能性
第12回 配信講義 計算科学技術特論B(2022)
C++ AMPを使ってみよう
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
20130126 sc12-reading
20190625 OpenACC 講習会 第2部
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
怪しいWindowsプログラミング
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
2015年度GPGPU実践プログラミング 第12回 偏微分方程式の差分計算
PyOpenCLによるGPGPU入門
Ad

More from NVIDIA Japan (20)

PDF
HPC 的に H100 は魅力的な GPU なのか?
PDF
NVIDIA cuQuantum SDK による量子回路シミュレーターの高速化
PDF
Physics-ML のためのフレームワーク NVIDIA Modulus 最新事情
PDF
20221021_JP5.0.2-Webinar-JP_Final.pdf
PDF
開発者が語る NVIDIA cuQuantum SDK
PDF
NVIDIA Modulus: Physics ML 開発のためのフレームワーク
PDF
NVIDIA HPC ソフトウエア斜め読み
PDF
HPC+AI ってよく聞くけど結局なんなの
PDF
Magnum IO GPUDirect Storage 最新情報
PDF
データ爆発時代のネットワークインフラ
PDF
GPU と PYTHON と、それから最近の NVIDIA
PDF
GTC November 2021 – テレコム関連アップデート サマリー
PDF
テレコムのビッグデータ解析 & AI サイバーセキュリティ
PDF
必見!絶対におすすめの通信業界セッション 5 つ ~秋の GTC 2020~
PDF
2020年10月29日 プロフェッショナルAI×Roboticsエンジニアへのロードマップ
PDF
2020年10月29日 Jetson活用によるAI教育
PDF
2020年10月29日 Jetson Nano 2GBで始めるAI x Robotics教育
PDF
COVID-19 研究・対策に活用可能な NVIDIA ソフトウェアと関連情報
PDF
Jetson Xavier NX クラウドネイティブをエッジに
PDF
GTC 2020 発表内容まとめ
HPC 的に H100 は魅力的な GPU なのか?
NVIDIA cuQuantum SDK による量子回路シミュレーターの高速化
Physics-ML のためのフレームワーク NVIDIA Modulus 最新事情
20221021_JP5.0.2-Webinar-JP_Final.pdf
開発者が語る NVIDIA cuQuantum SDK
NVIDIA Modulus: Physics ML 開発のためのフレームワーク
NVIDIA HPC ソフトウエア斜め読み
HPC+AI ってよく聞くけど結局なんなの
Magnum IO GPUDirect Storage 最新情報
データ爆発時代のネットワークインフラ
GPU と PYTHON と、それから最近の NVIDIA
GTC November 2021 – テレコム関連アップデート サマリー
テレコムのビッグデータ解析 & AI サイバーセキュリティ
必見!絶対におすすめの通信業界セッション 5 つ ~秋の GTC 2020~
2020年10月29日 プロフェッショナルAI×Roboticsエンジニアへのロードマップ
2020年10月29日 Jetson活用によるAI教育
2020年10月29日 Jetson Nano 2GBで始めるAI x Robotics教育
COVID-19 研究・対策に活用可能な NVIDIA ソフトウェアと関連情報
Jetson Xavier NX クラウドネイティブをエッジに
GTC 2020 発表内容まとめ

1075: .NETからCUDAを使うひとつの方法

  • 1. .NET から CUDA を使うひとつの方法 C++/CLI による WRAPPER のつくりかた episthmh epi@c.zaq.jp Microsoft MVP for Visual C++ Jan.2004~ NVIDIA CUDA Ambassador for Apr.2015~ 2015-1075 Hall-B1 16:20~
  • 2. WINDOWS APPLICATION CUI Console (stdin/stdout) GUI Win API MFC Windows Forms WPF native : C/C++ managed : .NET (C#,VB etc.) legacy…
  • 3. MANAGED は直接 CUDA を呼べない… host memory device memory PCI-bus CLR managed app.
  • 4. MANAGED と NATIVE の仲介役 host memory device memory PCI-bus CLR managed app. native assembly call
  • 6. サンプル : SAXPY Y[i] = alpha * X[i] + Y[i] (i = 0..N-1) C# / Windows Forms app. 絵ヅラはC#, 計算はCUDA C++/CLIが両者を仲介
  • 7. WRAPPERのつくりかた 1: CLR クラスライブラリ
  • 8. WRAPPERのつくりかた 2: ビルド カスタマイズ ※ C++/CLI プロジェクト内で デバイス・コード(~.cu) をコンパイルできます
  • 10. WRAPPERのつくりかた 4: 64BIT PLATFORM ※ CUDA 7.0 以降、多くのCUDAライブラリは 64bit-only です
  • 11. SAXPY DEVICE/HOST CODE __global__ void kernel_saxpy(float alpha, const float* x, float* y, unsigned int size) { unsigned int i = blockDim.x * blockIdx.x + threadIdx.x; if ( i < size ) { y[i] = alpha * x[i] + y[i]; } // Saxpy! } __host__ void device_saxpy(float alpha, const float* x, float* y, unsigned int size) { unsigned int block = 256U; unsigned int grid = (size + block -1U)/block; kernel_saxpy<<<grid,block>>>(alpha, x, y, size); } ※ device-code および それを呼び出すhost-codeは ~.cu に記述します
  • 12. REF CLASS SAXPY : ~.h public部 namespace CUDA { public ref class Saxpy { private: … public: Saxpy(); // コンストラクタ ~Saxpy(); // デストラクタ !Saxpy(); // ファイナライザ void calculate(float alpha, cli::array<float>^ x, cli::array<float>^ y); }; } ※ C++/CLI: cli::array<float>^ は C#: float[] に相当します
  • 13. REF CLASS SAXPY : ~.h private部 namespace CUDA { public ref class Saxpy { private: float* dx_; // device-memory X[] float* dy_; // device-memory Y[] size_t bsize_; // dx_/dy_の大きさ(bytes) void allocate(size_t new_bsize); // dx_/dy_を確保する void deallocate() { // dx_/dy_を解放する cudaFree(dx_); dx_ = nullptr; cudaFree(dy_); dy_ = nullptr; } … } ※利用者(C#,VB)に成り代わって device-memory を確保/解放します
  • 14. namespace CUDA { Saxpy::Saxpy() : dx_(nullptr), dy_(nullptr), bsize_(0U) {} Saxpy::~Saxpy() { this->!Saxpy(); } // 明示的にファイナライザを呼ぶ Saxpy::!Saxpy() { deallocate(); } // device-mem. を解放する … } ※ ファイナライザ : !クラス名() をお忘れなく REF CLASS SAXPY : ~.cpp
  • 15. namespace CUDA { void Saxpy::allocate(size_t new_bsize) { // 足りないときは一旦解放し、再確保 if ( bsize_ < new_bsize ) { deallocate(); bsize_ = new_bsize; float* ptr; cudaMalloc(&ptr, bsize_); dx_ = ptr; cudaMalloc(&ptr, bsize_); dy_ = ptr; } } } ※ cudaMalloc(&dx_, bsize_) とは書けません
  • 16. namespace CUDA { void Saxpy::calculate(float alpha, array<float>^ x, array<float>^ y) { unsigned int size = x->Length; if ( size != y->Length ) return; allocate((size_t)(size*sizeof(float))); // host → device pin_ptr<float> hx = &x[0]; cudaMemcpy(dx_, hx, size*sizeof(float), cudaMemcpyHostToDevice); pin_ptr<float> hy = &y[0]; cudaMemcpy(dy_, hy, size*sizeof(float), cudaMemcpyHostToDevice); // kernel-call device_saxpy(alpha, dx_, dy_, size); // device → host cudaMemcpy(hy, dy_, size*sizeof(float), cudaMemcpyDeviceToHost); } } ※ pin_ptr<float> でピン留めします
  • 17. HOW TO USE IN .NET ※ 参照設定をお忘れなく
  • 18. HOW TO USE IN C# : ~.cs public partial class Form1 : Form { private CUDA.Saxpy saxpy = new CUDA.Saxpy(); // 作って private void btnCalc_Click(object sender, EventArgs e) { if ( lstX.Items.Count != lstY.Items.Count ) return; float[] x = …; float[] y = …; float alpha = …; saxpy.calculate(alpha, x, y); // 呼ぶ! … } ※ インスタンスを生成(new)し、メソッドを呼び出すだけ
  • 20. namespace CUDA { public ref class SepiaConverter { public: SepiaConverter(); ~SepiaConverter(); !SepiaConverter(); // image(元画像)をcolor_にコピーし、モノクロ化 void LoadImage(System::IntPtr image, int width, int height, int stride); // モノクロ画像を色調変換し、imageにコピー void ConvertSepia(System::IntPtr image, float u, float v); … }; } ※ System::IntPtr が void* に相当します
  • 21. namespace CUDA { void SepiaConverter::ConvertSepia(System::IntPtr image, float u, float v) { // 色調変換し、結果を color_ に … // 結果をコピー size_t bsize = height_ * stride_; void* ptr = static_cast<void*>(image); cudaMemcpy(ptr, color_, bsize, cudaMemcpyDeviceToHost); } } ※ System::IntPtr は void* にキャストできます
  • 22. // セピア変換 private CUDA.SepiaConverter converter_; // C++/CLIで作ったwrapper private void convert_sepia(float u, float v) { // Bitmapを生成し、 LockBitsで固定 var bmp = new Bitmap(幅, 高さ); var data = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); // 色調変換 converter_.ConvertSepia(data.Scan0, u, v); bmp.UnlockBits(data); picOutput.Image = bmp; picOutput.Invalidate(); } ※ IntPtr BitmapData.Scan0 が画像の先頭アドレスです