1

レンダリング パイプラインからさらにパフォーマンスを絞り出そうとしています。(はるかに) 最も遅い部分は、大きな画像に対して java.awt.imaging.LookupOp を実行することです。

画像サイズは約2048x2048です。

描画操作と一緒にフィルターを実行すると、フィルター メソッドを呼び出すよりもはるかに高速であることがわかりました。ただし、これでも約 250 ミリ秒 (または 4 fps) かかるルックアップ操作が残っています。レンダリングのヒントはありますか?

基本的に私たちがやっていることは次のとおりです。

public void paint(Graphics g)
{
    if(recalcLUT)
    {
        Graphics2D g2d = (Graphics2D) displayImage.getGraphics();
        g2d.drawImage(srcImage, lut, 0, 0);
    }

    Graphics2D g2d = (Graphics2D) g;
    g2d.clearRect(0, 0, this.getWidth(), this.getHeight());
    AffineTransform at = new AffineTransform();
    at.setToIdentity();
    at.scale(scale, scale);
    g2d.drawImage(displayImage, at, null);
}

lut 変数は LookupOp で、通常は ShortLookupOp で、画像は 16 ビットのグレースケール画像です

ありがとう

ライアン・ブッチャー:

ここで実行できる明らかなパフォーマンスの最適化が他にもいくつかあることは知っています。しかし、大きな問題は単に LookupOp 操作を行うことなので、それに関するアドバイスを探しています。

ルックアップ Ops は基本的に配列を作成する場所であり、画像の各ピクセルをその色としてレンダリングする代わりに、その色を配列のインデックスとして使用し、その色をインデックスの値としてレンダリングします。この特定の例では、単純な明るさ/コントラスト操作を行うために使用しています。これは、基本的にすべてのピクセルの値に線形関数を適用する方法である rescaleOp を使用して実装することもできます。しかし、これは遅くなることが判明しました。

4

2 に答える 2

1

私は 8 年近く Java を使用していないので、一部の構文は無関係かもしれません。

ループに関するあらゆる種類のパフォーマンスの鍵は、できるだけ多くのものをループの外に押し出すことです。できない場合は、変更されたときにのみ計算を実行します。多くの場合、複数の変更をキャッシュできるように、最後の最後まで再計算を待つ方が適切です。

  1. すべてのオブジェクト構築をレンダー ループの外に移動します。事前に必要なオブジェクトの数がわかっている場合は、それらを渡します。オブジェクトプールを使用せず、ファクトリにrenderloopの外にオブジェクトを作成させる場合。これにより、建設/破壊の時間を節約できます。

  2. スケールが変更された場合にのみ、AffineTransform を計算します。これをペイント ループの外側にプッシュして渡します (const 参照として...Java にも存在しますか?私は C++ を長く使いすぎています)。

  3. At.setToIdentity() を呼び出す必要はない場合があります。これは、AffineTransform がデフォルトでアイデンティティ マトリックスに設定されている必要があるためです (これを確認してください)。

  4. recalcLUT はフレームごとに呼び出される必要がありますか? if ステートメントの実行後に recalcLUT を false に設定するのは理にかなっていますか?

LookupOp の目的がわかりません。それが何をしているのかについてもう少し情報をくれれば、もっと提案できるかもしれません。

うまくいけば、これが役に立ちます。

于 2008-11-07T14:38:51.243 に答える
0

この処理を GPU にプッシュする機能はありますか? 複数のハードウェア パイプラインにより、処理が大幅に高速化されます。

それができない場合は、CPU で LookupOp を並列化することを検討する必要があります。私が理解していることから、各ルックアップは個別に実行できます。したがって、複数のスレッドをスピンアップし (CPU アーキテクチャと同時に実行されている他の処理に依存する数)、各スレッドに画像の一部を検索させることができます。すべてのスレッドが終了するのを待つために、各更新の実行時にセマフォが必要になります。

いずれの場合も、次のようにして、変更のないすべてのフレームのメモリ消費をトレードオフする必要があります。フレームレートが制限されていない限り、フレーム数が多ければ多いほど、何も変わっていない可能性が高くなります。これにより、不要な作業を省くことができます。

//Has filter or source image changed?
//   yes, recalculate filter and cache
//   no, render cached image

最後に、LookupOp の実装を確認できますか? それは何をしているのか、実装を自分で書くことによって収集できるパフォーマンスの向上はありますか (これは最後の手段にする必要があります)。

于 2008-11-07T15:23:39.767 に答える