0

最近、ピクセル レベルで画像を操作するさまざまな方法を調べているときに、この記事を目にしました。

http://www.codeproject.com/Articles/16403/Fast-Pointerless-Image-Processing-in-NET

そして著者は次のように述べています。

ポインターの代わりにマネージ配列を使用する場合のパフォーマンス コストは? マネージ配列を使用すると、ポインターを使用するより遅くなりませんか? 驚かれるかもしれませんが、私のテストによると、答えはノーです。私のテストでは、配列メソッドはポインター メソッドよりも少なくとも 10% 高速であることがわかりました。

ピクセル レベルで画像を操作する最初の試みはGetPixel/SetPixelメソッドを使用することでしたが、これは信じられないほど遅いものでした。その後、このリンクに誘導されましたが、かなり高速でした。

記事に記載されている方法を試したことはありませんが、サポートしてくれる人はいますか? それとも、特定の条件下でのみ高速になるのでしょうか?

4

2 に答える 2

3

これは、配列へのアクセス方法に大きく依存します。

ループ内で配列の長さを使用している場合、コンパイラはこれを認識し、インデックスの境界をチェックする必要がないことを認識します。これは、ループ自体によってインデックスが境界外になることが不可能になるためです。配列にアクセスするこの方法は、ポインターを使用する場合とパフォーマンスが似ています。

任意のインデックスで配列にアクセスしている場合、コンパイラはインデックスの境界をチェックするコードを追加する必要があります。これにより、すべてのアクセスにいくつかの命令が追加されます。配列にアクセスするこの方法は、ポインターを使用するよりも遅くなります。

また、ポインターを使用するコードの効率性にも依存します。最終的には、配列へのアクセスにインデックスを使用している場合でも、配列データへのアクセスには常にポインターが使用されるため、少なくともインデックスで配列にアクセスするコードと同じくらい効率的なポインター コードを記述することは常に可能です。

また、処理量にもよります。マーシャリングを使用して画像との間でデータを移動するということは、すべてのデータを既に 2 回移動していることを意味します。処理をほとんど行っていない場合、その場でデータにアクセスするほど高速になることはありません。


注: 記事内のデータをマーシャリングするために使用される方法は、Stride値が正の場合にのみ機能します。イメージがメモリに逆さまに格納されている場合 (ビットマップ ファイルで一般的)、Stride値は負になり、計算されたデータ サイズは負になります。

于 2012-08-04T18:47:06.500 に答える
1

10%のパフォーマンスの違いは、統計的に意味がありません。マネージコードでの配列アクセスは、範囲外チェックが追加されているため、遅くなる傾向があります。これはジッターによって最適化できますが、1次元配列としてアクセスする2次元構造ではそれほど簡単ではありません。ポインタは、主にそのようなチェックなしで使用されるため、安全ではありません。

ただし、重要なサイズのビットマップを格納するために必要な量のように、大量のRAMをアドレス指定し始めると、コード速度は無意味になります。このようなコードのパフォーマンスは、メモリバスの帯域幅によって抑制されます。これは、プロセッサがデータを消費できる速度よりも倍も遅いです。現在重要になり始めていることの1つは、L1プロセッサキャッシュの使用を最適化する方法でデータにアクセスすることです。これはビットマップピクセルにアクセスする自然な方法です。行の順序ではなく、列(X)の順序でピクセルを作成する必要があります。つまり、X変数は内側のループである必要があり、Yは外側のループである必要があります。

おそらく、特にこのような主張を含むコードをコピーした場合は、できるだけ速く進んでいます。それを証明する唯一の方法は、C#を必要とするポインターを使用するコードを実際に記述して比較することです。

于 2012-08-04T19:01:04.607 に答える