処理時間かかりすぎな手法(C++/CLIを使う)
高速化を目指し、C#で処理を書き、C++で呼ぶ構成にしたのに、
C++/CLIでdllを実行すると、処理時間が大幅に長くなりました。
実装した方法と、実行時間を短縮するために考察した事をまとめました。
C++/CLIでdllを呼び出す際の実装方法
①.プロパティーページで共通言語ランタイムサポートを有効にする。
「プロジェクト(P)」→「プロパティー(E)」→「構成プロパティ」→「詳細」→「共通言語ランタイムサポート」
の設定を
「共通言語ランタイムサポート(/clr)」
に変更する。
②.参照に使用したいDLLを指定する。
プロジェクトのフォルダにDLLを移動しておく。(移動しなくても大丈夫ですが移動しておいた方が確認しやすいので・・・)
「ソリューションエクスプローラ」内の「参照」で右クリックし「参照の追加」を選択
左の「参照」タブをクリックし、使用したいDLLを選択する。
③.使用したいDLLを呼び出す
呼び出したいソースで「::」を利用し、クラスを呼び出す。
考察
「C++/CLR」を有効にし、呼び出す事で、C++で「COMオブジェクト」を呼び出すのと同様になってしまい、処理時間が長くなっているのではないか?
実測値
ネットで「マネージ関数とネイティブ関数を1つのプロジェクト内に混在させた場合」の実行速度を計測してくれている方が居ました。
実行方式 | 実行時間 |
---|---|
ネイティブ関数 → ネイティブプラグマ内のネイティブ関数 | 31 ms |
ネイティブ関数 → マネージドプラグマ内のネイティブ関数 | 1047 ms |
マネージ関数 → ネイティブプラグマ内のネイティブ関数 | 4281 ms |
マネージ関数 → マネージドプラグマ内のネイティブ関数 | 266 ms |
マネージ関数 → マネージドプラグマ内のネイティブ関数(__clrcall規約) | 266 ms |
マネージ関数 → マネージド関数 | 281 ms |
処理時間をかけないために、どうするべきか?
CLRを利用せずに、C#の関数を呼び出せるようにしなければならない。
C#側で関数をDLLにエクスポートする必要がある。
候補①.DllExport.batの利用
これは、Nugetで取得すると怒られるので公式サイトから落とす。
DllExportのGitHub
候補②.Unmanaged Exportsの利用
これは、Nugetで取得できる模様
Unmanaged Exportsのページ
用語集
ネイティブコード
コンピュータのCPU(MPU/マイクロプロセッサ)が理解できる形式で記述されたコンピュータプログラム。 プロセッサに対する命令の仕様を定義した機械語(マシン語)で書かれており、人間が直接読み書きすることは困難である。
アンマネージコード(アンマネージドコード)
Microsoft . NETにおける実行可能形式のプログラムコードの形式の一つで、. NETの共通中間言語(CIL)以外の形式で記述されたもの。
マネージコード(マネージドコード)
Microsoft .NETにおける実行可能形式のプログラムコードの形式の一つで、.NETの共通中間言語(CIL)によって記述されたもの。CILを解釈・実行できるCLR(Common Language Runtime/共通言語ランタイム)が用意されている環境であれば、どこでも等しく実行することができる。
CIL
共通言語基盤 (Common Language Infrastructure、CLI) で定義された最も低水準な人間が解読可能なプログラミング言語であり、.NET FrameworkやMonoにより使用される。
ガベージコレクション(GC)
誰からも参照されなくなったオブジェクトを自動的に回収し解放する機能
マネージリソース
GCの管理下にあるリソース
アンマネージリソース
GCの管理下にないリソース
ファイルハンドル、ウィンドウハンドル(HWND)、データベース接続 など。
参考サイト
C++/CLR時に参考にしたサイト
ガベージコレクション(GC)とは?
StringとCString(gcnewについて)
C++(EXE)からC#(DLL)の関数を呼び出す
速度向上調査時に参考にしたサイト
[C++/CLI] マネージド、アンマネージド間の関数呼び出し速度調査
C#のメソッドをC++から呼ぶ方法
C#側で関数をDLLにエクスポート時に参考にしたサイト
C++からC# DLL 超超超入門
[C++/C#]C#をC++/CLIでラップしてC++アプリから呼ぶ
セキュリティの「ブロックの解除」について
依存関係の一つが読み込めないDLLエラーの対策と原因
複数ファイルの「ブロックの解除」を一括で行う方法
Windowsで、複数のファイルのブロック解除を簡単に行う(スクリプトで!)
備忘録メモ
CファイルをC++としてコンパルする場合のコンパイルオプション
①「共通言語ランタイムサポート(/clr)」を有効にする。
②「基本ランタイム チェック」を規定にする。
③「C/C++」→「詳細設定」→「コンパイラ言語の選択」を「C++ コードとしてコンパイル(/TP)」に変更