質問

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

アルゴリズムの実装がより高速になるのはどれでしょうか?

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

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

C# unsafe は JIT コンパイラを経由するため遅いと思いますが、その違いは重要でしょうか?

編集:

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

役に立ちましたか?

解決

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

その後、間違った質問をしていることになります。

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

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

もちろん、「高速にしたいが、C#やC ++の外に出ない程度にしたい」という場合は、答えが異なります;-)

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

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

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

他のヒント

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

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

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

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

自分の状況に最適な解決策を知りたい場合は、両方を試して違いを測定する必要があります。それ以上になるとは思わない

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

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

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

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

また、安全ではないC#が安全よりも高速である必要がある理由も知りません。一般に、コンパイラがはるかに強力な仮定を立てることができるため、安全は良いです。したがって、安全な might はより高速です。しかし、繰り返しますが、それはコンパイルしているコード、使用しているコンパイラー、および他の多くの要因に依存します。

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

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

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

  2. SSE命令を悪用できるかどうかを確認してください。C++またはCのほとんどに便利なAPIを提供するライブラリがあります。インテルのサイトで、便利な最適化ライブラリを確認してください。および" Math Kernel"。

ただし、政治面では、アルゴリズムをOpenCVに組み込んで、他の人にも利益がもたらされるようにしてください。

これは永遠に続く戦いです。 C対C ++対C#対何でも。 C#では、「危険」のロックを解除することが安全でないという概念です。オペレーション。つまり、CおよびC ++でできるように、ポインターの使用、およびvoidポインターなどにキャストできることです。 非常に危険で、非常に強力です!ただし、C#の基になっているものを無効にします。

最近、特に.NETのリリース以降、Microsoftがパフォーマンスの方向に大きく前進しており、C ++のように、次のバージョンの.NETが実際にインラインメソッドをサポートすることがわかります。これにより、非常に特定の状況でパフォーマンスが向上します。私はそれがC#の機能になることを嫌うが、コンパイラが拾う厄介な属性-しかし、あなたはそれをすべて持つことはできない。

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

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

一日の終わりには、C、C ++、およびC#を実行時の速度とほぼ同じであると個人的に見ています。基盤となるハードウェアと非常に密接に、またはそれらのピクセルに非常に近い場所で作業したいという苦痛な状況では、C / C ++の群衆に顕著な利点を見つけるでしょう。

しかし、ビジネスにとって、そして今日のほとんどのものは、C#は真の競争相手であり、「安全」な範囲内にとどまっています。環境は間違いなくボーナスです。
私が持っているように、外に出るとき、あなたは安全でないコードでほとんどのことを成し遂げることができます-そして少年、私はいくつかの極端に行きましたか!しかし、それは価値がありましたか?おそらくない。私は個人的に、C ++のタイムクリティカルなコードの行と、C#のすべてのオブジェクト指向の安全な要素に沿ってもっと考えるべきだったのではないかと思います。しかし、私は思っていたよりも優れたパフォーマンスを持っています!

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

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

うーん。

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

  • C ++ランタイム環境には、組み込みのランタイムチェックがありません(マイナス面は、自分自身を爆破する自由な統治があることです)。 C#ランタイム環境では、少なくとも最初は健全性チェックが行われます。
  • C ++コンパイラは、コードを最適化するために構築されています。理論的には、ICC(またはGCC)が使用するすべての最適化voodoを使用してC#JITコンパイラを実装することは可能ですが、MicrosoftのJITが確実に優れていることは疑わしいです。 JITコンパイラに実行時統計がある場合でも、ICCまたはGCCでのプロファイルガイドによる最適化ほど優れていません。
  • C ++環境では、メモリモデルをより適切に制御できます。アプリケーションがデータキャッシュをスラッシングしたり、ヒープを断片化したりするようになった場合、割り当てに対する追加の制御が本当に感謝されます。動的な割り当てを回避できる場合は、既に十分に改善されています(ヒント: malloc()またはその他の動的なアロケーターの実行時間は非決定的であり、ほとんどすべての非ネイティブ言語はより重いですヒープの使用量、したがってより重い割り当て)。

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

お返事が少し遅れましたが、いくつかの逸話的な経験をお伝えできます。元々はポインターと安全でないコードを使用してC#でコーディングされた行列乗算ルーチンがいくつかありました。これはアプリケーションのボトルネックであることが判明したため、Pinning + P / Invokeを使用してC ++バージョンのMatrix乗算ルーチンを呼び出し、2倍の改善を実現しました。これは.NET 1.1では少し前のことなので、状況は改善されたかもしれません。他の人が指摘するように、これは何も証明しませんが、それは興味深い演習でした。

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

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

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

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

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

彼らはとんでもなく遅かった。必要な機能を C++ で書き直しました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top