24

ビデオフレームのリアルタイム処理を実行する画像処理プログラムを作成しています。これは、OpenCV ライブラリ dll (アンマネージ C++) をラップする Emgu.CV ライブラリ (C#) を使用して C# で記述されています。ここで、独自の特別なアルゴリズムを作成する必要があり、できるだけ高速にする必要があります。

アルゴリズムのより高速な実装はどれですか?

  1. C# で「安全でない」関数を作成する

  2. 関数を OpenCV ライブラリに追加し、Emgu.CV を介して呼び出す

C# unsafe は JIT コンパイラを通過するため遅いと思いますが、その違いは大きいのでしょうか?

編集:

VS2008 で .NET 3.5 用にコンパイル

4

10 に答える 10

71

できるだけ速くする必要があります

それでは、あなたは間違った質問をしています。

サポートする重要なアーキテクチャ バリアントごとに異なるバージョンを使用して、アセンブラでコーディングします。

最適化された優れた C++ コンパイラからの出力をガイドとして使用してください。しかし、C++ は必ずしも最適化に役立つ可能性のあるすべての情報をコンパイラーに伝えるとは限らないため、おそらくいくつかの改善点を考えることができるでしょう。たとえば、C++ には C99 キーワードの restrict がありません。その特定のケースでは、多くの C++ コンパイラ (MSVC を含む) が現在それをサポートしているため、可能な場合は使用してください。

もちろん、「高速にしたいが、C# や C++ の外に出るほどではない」という意味であれば、答えは異なります ;-)

多くの場合、C# は少なくとも似たような C++ のパフォーマンスに近づくことを期待しています。もちろん、プログラムは JIT 自体にかかる時間は関係ないほど長く実行されると思いますが、多くのビデオを処理している場合は、そうなる可能性が高いと思われます。しかし、安全でないC#でそれらを実行すると、C++で同等のものよりもはるかに遅くなる特定のこともあると思います。JIT に関する私の経験はすべて CLR ではなく Java にあるため、それらが何であるかはわかりません。たとえば、アルゴリズムが C# コードへの呼び出しを行う場合など、C++ の方が遅い場合もあります。

残念ながら、それがどれだけ近いかを確認する唯一の方法は、両方を作成してテストすることです。これでは、C++ バージョンを作成するのに余分な労力が必要であるという点を見逃しています。ただし、実行したい処理に近い簡単なコードをハッキングすることで、大まかなアイデアを得ることができる場合があります。必ずしもすべてを実行したり、正しく処理したりする必要はありません。アルゴリズムがすべてのピクセルをループし、ピクセルごとにいくつかの FP ops を実行する場合、大まかなベンチマークを一緒にハッキングするには 30 分かかります。

通常、「これはできるだけ速くする必要がある」と考えて始めることはお勧めしません。要件は達成可能である必要があり、定義上、「可能な限り X として」は達成可能な境界線にすぎません。要件もテスト可能である必要があり、理論上の最大値を何らかの方法で知っていない限り、「可能な限り X として」はテストできません。より友好的な要件は、「これはこれこれの速度の CPU でリアルタイムでこれこれの解像度のビデオ フレームを処理する必要がある」または「これは主要な競合他社の製品よりも高速である必要がある」ということです。C# バージョンがそれを行う場合、ユーザーのセットアップにおける予期しない小さな問題を考慮して少し余裕を持たせれば、仕事は完了です。

于 2008-11-11T11:36:29.037 に答える
6

C#は通常、C++よりも低速です。マネージコードにはランタイムチェックがあります。結局のところ、これらがそれを管理するものです。たとえば、C ++は、配列の境界を超えているかどうかをチェックする必要はありません。

私の経験から、固定メモリを使用すると非常に役立ちます。.NET 4.0には、将来役立つ可能性のある新しいSystem.IO.UnmanagedMemoryAccessorクラスがあります。

于 2008-11-11T12:43:07.560 に答える
6

アルゴリズム、実装、C++ コンパイラ、および JIT コンパイラに依存します。ほとんどの場合、C++ 実装の方が高速になると思います。しかし、これは変わるかもしれません。

JIT コンパイラは、C++ コンパイラのようにコードが実行される可能性のあるすべてのプラットフォームの平均ではなく、コードが実行されているプラ​​ットフォームに合わせてコードを最適化できます。これは、新しいバージョンの JIT コンパイラがますます得意とすることであり、場合によっては JITted コードに利点をもたらす可能性があります。したがって、答えはあなたが期待するほど明確ではありません。たとえば、新しい Java hotspot コンパイラはこれを非常にうまく処理します。

マネージ コードが C++ よりも優れている可能性があるその他の状況では、多数の小さなオブジェクトの割り当てと割り当て解除が必要になります。.net ランタイムは、再利用できる大きなメモリ チャンクを事前に割り当てるため、メモリを割り当てる必要があるたびに os を呼び出す必要はありません。

安全でない C# が通常の C# よりもはるかに高速に実行されるかどうかはわかりません。これも試してみる必要があります。

状況に最適なソリューションを知りたい場合は、両方を試して違いを測定する必要があります。以上になるとは思えない

于 2008-11-11T11:20:09.723 に答える
6

言語に「速さ」はありません。コンパイラとコードに依存します。どんな言語でも非効率なコードを書く可能性があり、巧妙なコンパイラはソースの言語に関係なく最適に近いコードを生成します。

C# と C++ の間のパフォーマンスにおける唯一の避けられない要因は、C# アプリが起動時に多くのことを行う必要がある (.NET フレームワークを読み込み、おそらくコードを JIT する) ことです。その後は場合によりますが、ある言語が常に別の言語よりも高速でなければならない根本的な理由はありません。

また、安全でない C# が安全よりも高速であるべき理由もわかりません。一般に、コンパイラがより強力な仮定を行うことができるため、セーフは優れています。ただし、コンパイルしているコード、使用しているコンパイラ、およびその他のさまざまな要因によって異なります。

要するに、言語のパフォーマンスを測定できるという考えをあきらめてください。できません。言語は決して「速い」とか「遅い」ということはありません。

于 2008-11-11T11:26:39.133 に答える
4

永遠に続く戦いです。C 対 C++ 対 C# 対その他。C# では、安全でないという概念は、"危険な" 操作のロックを解除することです。つまり、C および C++ でできるように、ポインタの使用、および void ポインタなどへのキャストが可能です。非常に危険で、非常に強力です!しかし、C# が基づいていたものを打ち負かします。

最近では、特に .NET のリリース以降、Microsoft がパフォーマンスの方向に進歩を遂げていることがわかります。.NET の次のバージョンでは、C++ と同様にインライン メソッドが実際にサポートされる予定です。これにより、非常に特定の状況でのパフォーマンスが向上します。それが ac# の機能ではなく、コンパイラが拾う厄介な属性になるのは嫌ですが、すべてを手に入れることはできません。

個人的には、C# とマネージ DirectX を使用してゲームを作成しています (なぜ XNA を使用しないのですか?? この投稿の範囲を超えています)。私はグラフィカルな状況で安全でないコードを使用しています。これは、他の人が言ったことの方向にうなずきます。

GDI++ ではピクセル アクセスがとてつもなく遅いため、代替手段を探すようになりました。しかし、全体として、c# コンパイラは非常に優れており、コード比較 (記事を見つけることができます) では、パフォーマンスが c++ に非常に匹敵することがわかります。コードを書くためのより良い方法がないと言っているわけではありません。

結局のところ、個人的には、C、C++、および C# の実行速度はほぼ同じであると考えています。ただ、基盤となるハードウェアと非常に緊密に連携したり、それらのピクセルに非常に近い部分で作業したい場合など、いくつかのつらい状況では、C/C++ クラウドに顕著な利点があることがわかります。

しかし、ビジネスや最近のほとんどの場合、C# は真の競争相手であり、「安全な」環境にとどまることは間違いなくボーナスです。
外に出ると、ほとんどのことは安全でないコードで行うことができます。しかし、それは価値がありましたか?おそらくそうではありません。個人的には、C++ のタイム クリティカルなコードや、C# のすべてのオブジェクト指向の安全なコードに沿って、もっと考えるべきだったのではないかと思います。でも、思った以上にパフォーマンスがいい!

行う相互運用呼び出しの量に注意している限り、両方の長所を活かすことができます。私は個人的にそれを避けてきましたが、どのくらいの費用がかかるのかわかりません。

したがって、私が試したことはありませんが、実際に C++ .NET を使用してライブラリを開発する際の冒険を聞きたいと思います.C# がこれらの特別なグラフィカルな状況に対して安全ではないよりも高速でしょうか? それは、ネイティブの C++ コンパイル済みコードと比べてどうですか? では質問です!

うーん..

于 2013-07-18T13:30:59.983 に答える
4

アルゴリズムを標準的な方法で実装する場合、それは無関係だと思います。ただし、一部の言語には、非標準的なブーストを提供できる API またはライブラリへのバインディングがあります。

  1. GPU 処理を使用できるかどうかを検討してください。nvidia と ati は CUDA と CTM フレームワークを提供しており、khronos グループ (openGL) による継続的な標準化の取り組みがあります。また、amd が将来のチップに少なくとも 1 つのストリーミング プロセッサ コアを追加するという予感もあります。ですから、その分野にはかなりの見込みがあると思います。

  2. SSE 命令を利用できるかどうかを確認してみてください。便利な API を提供するほとんどのライブラリが C++ または C にあります。Intel のサイトで最適化された便利なライブラリを確認してください。「Intel Performance Primitives」と「Math Kernel」を思い出します。

しかし、政治的な面では、アルゴリズムを OpenCV に組み込んで、他の人も利益を得ることができるようにしてください。

于 2008-11-11T13:45:32.037 に答える
3

環境が分かっていて、優れたコンパイラーを使用している場合 (Windows でのビデオ処理には、インテル C++ コンパイラーがおそらく最良の選択です)、C++ はいくつかの理由で C# を完全に打ち負かします。

  • C++ ランタイム環境には、組み込みのランタイム チェックがありません (欠点は、自分を爆破する自由があることです)。C# ランタイム環境では、少なくとも最初はサニティ チェックが行われます。
  • C++ コンパイラは、コードを最適化するために構築されています。ICC (または GCC) が使用するすべての最適化 voodo を使用して C# JIT コンパイラを実装することは理論的には可能ですが、Microsoft の JIT が確実にうまくいくかどうかは疑わしいです。JIT コンパイラーにランタイム統計があったとしても、それは ICC や GCC でのプロファイルに基づく最適化ほど優れたものではありません。
  • C++ 環境では、メモリ モデルをより適切に制御できます。アプリケーションがデータ キャッシュをスラッシングしたり、ヒープを断片化したりする段階に達した場合は、割り当てをさらに制御できることを高く評価するでしょう。動的割り当てを回避できる場合は、すでにはるかに優れています (ヒント:malloc()またはその他の動的アロケーターの実行時間は非決定論的であり、ほとんどすべての非ネイティブ言語はより重いヒープ使用を強制し、したがってより重い割り当てを強制します)。

貧弱なコンパイラを使用している場合、または優れたチップセットをターゲットにできない場合、すべての賭けはオフになります.

于 2008-11-26T04:11:46.690 に答える
2

正直なところ、どの言語でそれを書くかは、どのアルゴリズムを使用するかほど重要ではありません (とにかく IMO です)。ネイティブ コードを使用することで、アプリケーションが高速になるかもしれませんが、遅くなる可能性もあります。これは、コンパイラ、プログラムの作成方法、使用している場合に発生する相互運用コストの種類によって異なります。混合環境など。プロファイリングしないと何とも言えません。(さらに言えば、アプリケーションのプロファイルを作成しましたか?アプリケーションがどこで時間を費やしているかを実際に知っていますか? )

より優れたアルゴリズムは、選択した言語に完全に依存しません。

于 2009-06-10T00:40:21.973 に答える
1

返信が遅くなりましたが、体験談を教えてください。ポインターとアンセーフ コードを使用して C# でコーディングされた行列乗算ルーチンがいくつかありました。これがアプリケーションのボトルネックであることが判明したため、pinning+P/Invoke を使用して行列乗算ルーチンの C++ バージョンを呼び出すと、2 倍の改善が得られました。これは .NET 1.1 の少し前のことなので、現在は改善されている可能性があります。他の人が指摘するように、これは何の証明にもなりませんが、興味深い演習でした。

thAAAnos にも同意します。アルゴリズムを本当に「できるだけ速く」する必要がある場合は、IPL を活用するか、必要に応じて GPU の実装を検討してください。

于 2008-11-28T20:56:56.290 に答える
-7

CPU での実行は、CPU 上の VM での実行よりも常に高速になります。人々が別のことを主張しようとしているなんて信じられない。

たとえば、キュ​​ーに入れられた Web サーバーでかなり負荷の高い画像処理作業が行われているとします。最初にそれを機能させるために、PHP の GD 関数を使用しました。

彼らは地獄のように遅かった。必要な機能を C++ で書き直しました。

于 2008-11-11T11:37:41.967 に答える