ラインスキャンカメラからのデータを毎秒約2000ライン(フレーム)で処理するアプリケーションの開発を検討しています。このリアルタイムアプリケーションには、C/C++が最適だと思います。 (それは私の気持ちであり、他の人はマネージコードがこのタスクに適していないことに同意するでしょう。)
しかし、私は非常に小さなMFC、または他のC++ GUIを実行しました。ただし、C#GUIを非常にうまく実行できるようになりました。
したがって、データ集約型のコードをC/C++で記述し、GUIをC#で記述するのは自然なことのように思えます。 GUIは、セットアップ/キャリブレーション/オンライン監視に使用されます(C#の方が簡単なため、UDPを介したデータの出力も可能です。
それで、最初に、これが進むべき道であることに誰かが同意するかどうかを見たいと思います。私のプログラミング経験(低レベルのCアルゴリズムと高レベルのC#GUI設計が得意)に基づくと、それはちょうどいい感じです。
第二に、私はそれについて行く正しい方法がわかりません。 VS2005で、いくつかの(extern "C")DLL C#アプリからの関数を呼び出すソリューションをまとめました。それができることを確認するために、次のいくつかのグローバル変数に書き込みました。 DLL、およびそれらから読み取ります:
test.h
_int globaldata;
extern "C" __declspec(dllexport) void set(int);
extern "C" __declspec(dllexport) int get();
_
test.cpp
_extern int data=0;
__declspec(dllexport) void set(int num) {
data = num;
}
__declspec(dllexport) int get() {
return data;
}
_
test.cs
_[DllImport("test")]
private static extern void set(int num);
[DllImport("test")]
private static extern int get();
_
get()
とset()
を呼び出すと、正しく機能します(get()
は、set()
に渡した番号を返します)。
これで、C++クラスもエクスポートできることがわかりましたが、管理する必要がありますか?それはどのように機能しますか?私はこれを正しい方法で行っていますか?
ご協力ありがとうございます!
_*** EDIT ***
_
まず第一に、これまでの素晴らしい答えをありがとう!私はいつもStackOverflowに非常に感銘を受けています...
私がもっと打つべきだった1つのことは、必ずしも生の速度ではなかったと思います(これはプロトタイプ化してベンチマークすることができます)。私がもっと心配していることの1つは、ガベージコレクターの非決定論的な動作です。このアプリケーションは、ガベージコレクションの実行中に500ミリ秒の遅延を許容しません。
私はすべて純粋なC#でこれをコーディングして試してみていますが、GCやその他の非決定論的な.NETの動作(?)が問題を引き起こすことが事前にわかっている場合は、コーディングに時間を費やしたほうがよいと思います。 C/C++と最高のC#インターフェースを見つけ出す。
高性能コードをC#で完全に記述できない理由はありません。
同じ/類似のトピックに関するSOの質問:
その他の記事:
私の意見では、あなたの解決策は健全なものです:
あなたの解決策は、まだ理解していない場合は、「混合モード」と呼ばれます。これは、基本的に、同じプロジェクトでマネージド(C#)コードとアンマネージド(C/C++)コードを組み合わせることを意味します。 VSプロジェクトを稼働させるのは面倒ですが(LNK2020エラー..argh ..)、適切な設定が見つかったら、問題なく動作するはずです。
唯一のネガティブなことは、混合モードのアセンブリは完全信頼で実行する必要があるということです。それで問題がなければ、何をすべきか知っていると思います。
もう1つ見たいのは、 [〜#〜] swig [〜#〜] というオープンソースプロジェクトです。 SWIGはC/C++コードを取得し、そこから.NETアセンブリを作成します。私はそれを自分で TM ++ オープンソースプロジェクトで使用しました。 SWIGの詳細については、ここを参照してください http://www.swig.org/ 。
リアルタイムアプリケーションの場合:C++をお勧めします。使用するフレームワークに応じて、メモリ管理がより柔軟になり、より高速になり、さらにはマルチプラットフォームになります...!
フレームワークとGUIについては、 Qt をご覧になることをお勧めします。 Qtは、C++ソフトウェア開発のための優れたフレームワークです。
私はそれがあなたの問題の解決策だと思います!
あなたがする必要がある最初のことはあなたの仮定をテストすることです。パフォーマンスの制約は何ですか?アプリケーションをホストするためにどのような種類のハードウェアを期待していますか?コアの問題を処理し、実行速度を測定する小さなプログラムをC#で作成します。
事実を把握して初めて、マネージドソリューションでC/C++を使用するかどうかを決定できます。
コメントした他の人たちと一緒に、特に 。NET Parallel Extensions を利用する場合は、C#/マネージドソリューションで問題なく動作すると思います。
最終的にC/C++ルートを使用する場合は、相互運用に2つのオプション、つまりpInvokeと COM相互運用 があります。 .NETから直接アンマネージC++クラスにアクセスするクリーンな方法があるとは思いません。このためには、 マネージ/アンマネージC++アセンブリの実装 を考慮する必要があります。
私の会社は非常に似たようなことをしていますが、ラインスキャンカメラの代わりにCCDカメラを使用しています。 GUI、ネットワーク通信、高レベルの「配管」にはC#を使用し、低レベルのアルゴリズムにはC++/CLIを使用しています。それは非常にうまく機能します。 Windowsで最大応答時間が保証された真のリアルタイムシステムを作成することは決してできませんが、私の経験から、GCはここでの問題の中で最も少ないものになります。 1つには、GCはメモリを割り当てたときにのみ実行されます。 C/C++のmalloc/newも同様であり、それらにも時間が必要です(メモリの断片化を考えてください)。私たちが行った測定から、完全なGCは10〜50ミリ秒かかり、その間、他のスレッドを必ずしも停止することはありません(管理されたメモリを割り当てようとしない限り)、これは問題ありません。しかし、これらの数値をあらゆる種類のアプリケーションに一般化できるかどうかはわかりません。確実に、独自のプロファイリングを行う必要があります。
GUIがリアルタイムの制約を破る可能性がある場合は、実際の画像処理を別のプロセスに入れ、パイプ/ソケットを使用してGUIと通信することを検討してください。または、システムを設計するときは少なくともそのオプションを念頭に置いてください。そうすれば、予期しないパフォーマンスの問題が実際に発生した場合に、最悪の場合のオプションとして使用できます。
2番目の質問は、実際のアルゴリズムにC++とC#のどちらを使用する必要があるかということでした。個人的には、複雑な画像処理アルゴリズムを作成すると、C++の方が快適に感じます。この言語はこのタスクに適していると思います。C/ C++にはC#よりもはるかに多くの数値計算ライブラリがあります。しかし、それは個人的な好みの問題かもしれません。パフォーマンスの観点から、C++には、C++インラインが.NETJITインラインよりも優れているという利点があります(つまり、小さな関数呼び出しをより多くインライン化できます)。
C++を使用する場合は、C++/CLIを使用することをお勧めします。そうすれば、マネージコードにコンパイルされるC++クラスを記述できます。 C++オプティマイザーはそれらを最適化し、ネイティブコードへの最後のコンパイルステップのみが.NETJITによって実行されます。大きな利点は、C++/CLIから.NETクラスに直接アクセスでき、C#からアクセスできるC++/CLIでマネージクラスを簡単に作成できることです。フェンスの両側にラッパーコードを記述する必要はありません。 (C++/CLIには、マネージプログラミングおよびアンマネージプログラミング用の言語構造が含まれているため、少し扱いにくいですが、アンマネージC++およびC#に既に精通している場合は、おそらく問題なく理解できます。)
C++の場合、C++/CLIを使用します。これは実際にはそれほど悪くはありません。古いマネージド拡張機能よりもはるかに優れています。
パフォーマンスについてコメントします。それは本当に依存します。 C++コードとC#コードの間にはどのくらいの距離がありますか? C++でデータを収集し、それを定期的にC#コードに送信するバックグラウンドスレッドがありますか?デバイスとのインターフェースをとる場合、シリアル、USB、提供されているAPIを使用しますか?
私はミッチに100%同意します。
彼のリソースを調査した後でも、アンマネージコードを使用する必要があると感じた場合は、C++で「ビジネス」レイヤー(この場合は実際には機能レイヤー)を記述し、C#でUIを記述できます。 COM相互運用 を使用して、C#/マネージコードからアンマネージコードを呼び出します。
繰り返しになりますが、私の考えでは、これを行う必要はありません。
私はC++。NETでそれをしました
C++。NETとC#の両方が管理されているので、なぜそれができなかったのかわかりません。重要なのは、それをどのように行うかです。
私のスキャナーは最大3000行/秒でしたが、重要な戦略は一度に32行のブロックを表示することでした。厳しいリアルタイム要件がなかったので、時々少し遅れることがありました。リアルタイムが非常に重要な場合は、プラットフォームの切り替えを検討する必要があります。
「InTimeOS」と呼ばれるリアルタイムウィンドウソリューションがありますが、使用するのは本当に面倒です。
あなたが持つことができる別のアプローチは、ハードリアルタイムを別のdllまたはライブラリに分離し、C#にそれ自身の速度で何ができるかを表示させることです。実際、ユーザーはインターフェースが2000fpsか500fpsかを判断できません。
フロントエンドのwpfおよびc ++バックエンド(pinvoke)は高速ですが、スレッドでGUI作業を行う場合、GUIスレッドがバックグラウンドコードによってブロックされることはありません。そうすると、プログラムはより速く、軽量になります。
私はネイティブC/C++およびC#の非常に低遅延のシステムでの経験があります。
c/C++では、確定的mallocメソッドでプロセッサ時間の80%が失われますが、ネイティブコードはmsilコードよりも10倍高速です
c#では、非同期プロセスであるため、メモリ割り当てが高速になります
選択は、処理時間/ malloc番号の比率で行う必要があります。
だから粒度!!!
C/C++のソリューションは、メモリ内のすべてのバッファを事前に割り当てることです(必要に応じてプリフェッチL2/L3キャッシュを使用します)
C#のソリューションは、P-Invoke変換メカニズムを最小限に抑えることです。
プロジェクトおめでとう、ポール
選択する言語は、パフォーマンスにはあまり影響しません(たとえば、速度に5/10%影響する可能性があります)。違いを生むのは、使用するアルゴリズム、データの処理方法、アプリケーションのプロファイリングなどです(パフォーマンスは10倍の比率で変化する可能性があります)。