37

ビューにかなり大きなパスを描画していますが、パフォーマンスの問題が発生しています。パスの長さは現在32,000ポイントですが、私のアプリケーションは少なくとも128,000ポイントに拡張する必要があります。データセットが非常に大きいため、パスのサイズについては実際には何もできません。パス全体を一度に表示してズームインできるようにする必要があります。

Android4.2を実行しているNexus10を使用しています。これは、明示的に無効にしないアプリケーションに対して、デフォルトでハードウェアアクセラレーションが有効になっています。

パスは次のコードで作成されます(セットアップやその他の無関係な部分は省略しました)。

dataPath.moveTo(0, offset - (float) data[leftLimit]/ scalingFactor);
        for (int i = leftLimit; i < rightLimit; ++i) {
            x = (i - leftLimit) * dx;
            y = offset - (float) data[i]/ scalingFactor;
            dataPath.lineTo(x, y);
        }

そして、onDraw()メソッドで描画されます:

canvas.drawColor(Color.WHITE);
canvas.drawPath(dataPath, linePaint);

ハードウェアアクセラレーションを使用した場合と使用しない場合を使用してビューを描画するのにかかる時間を測定しましたがadb shell dumpsys gfxinfo、驚いたことに、ハードウェアアクセラレーションははるかに遅いです。

ハードウェアアクセラレーションの場合:

ここに画像の説明を入力してください

ハードウェアアクセラレーションなし:

ここに画像の説明を入力してください

ハードウェアアクセラレーションバージョンは、フレームあたり約200〜300ミリ秒かかり、ほとんどがプロセス段階で費やされます。非加速バージョンは約50ミリ秒かかり、描画段階で2/3、プロセス段階で1/3になります。

明らかに、ハードウェアアクセラレーションのない高速バージョンでさえ、60 fpsを達成するには遅すぎるか、より大きなデータセットに移動するときにほとんど使用できません。

私の場合、ビットマップへのパスをレンダリングしてから、そのビットマップのみを画面に合わせて変換するというアイデアも問題があります。パスの非常に遠いズームインをサポートする必要があり、パスの品質を大幅に悪化させることなくズームインを有効にするには、パスの特大のビットマップをレンダリングする必要があります(メモリ制限とテクスチャサイズ制限に遭遇する可能性があります)。また、ズームインするときは、パスの一部のみの新しい画像を作成するか、パスを直接レンダリングするように切り替える必要があります。これにより、パフォーマンスが適切なものと同じである場合、フレームレートよりも大きな遅延が発生する可能性があります。今。

私が今疑問に思っているのは

  • 線/パスの描画はGPUが得意ではないものであり、ハードウェアの高速化を試みるべきではありませんか、それともパフォーマンスの低下を引き起こす何か間違ったことをしている可能性がありますか?
  • 許容できるパフォーマンスでこのような巨大なパスを描くために私にできることはありますか?
4

3 に答える 3

51

線/パスの描画はGPUが得意ではないものであり、ハードウェアの高速化を試みるべきではありませんか、それともパフォーマンスの低下を引き起こす何か間違ったことをしている可能性がありますか?

パスは常にCPUを使用してレンダリングされます。アプリがハードウェアアクセラレーションされている場合、これは、レンダラーが最初にCPUを使用してパスをビットマップに描画し、次にそのビットマップをテクスチャとしてGPUにアップロードし、最後に画面にテクスチャを描画することを意味します。

回線は完全にハードウェアアクセラレーションされています。この場合、を使用する代わりに使用するPathことをお勧めします。Canvas.drawLines()

許容できるパフォーマンスでこのような巨大なパスを描くために私にできることはありますか?

パスを自分で使用するCanvas.drawLines()か、自分で管理するパスにレンダリングする必要がありBitmapます。

于 2013-03-04T18:46:52.287 に答える
5

GPUの一般的なボトルネックに遭遇しているようです。次のリンクをご覧ください。

ルート描画をより効率的にする方法

Androidキャンバスパスのリアルタイムパフォーマンス

キャンバスからOpenGLへの切り替え

特に最初のものは、ビットマップを作成し、代わりにそれを描画することを提案します。openGLに変更すると、パフォーマンスが向上するようです。既存のメソッドを機能させるための魔法の方法があるかもしれませんが、現時点ではそのことに気づいていません。

自分が行っている動作が表示されるのは、おそらく、各描画の間にすべてのデータをGPUに送信するためです。GPUにキャッシュし、代わりに変換を使用する必要があります。データを再作成してすべてをGPUに送信するのではありません。おそらくI/Oバウンドです。つまり、CPUとGPU間の伝送速度がパフォーマンスを制限していることを意味します。あなたが提供したデータに基づいてこれを100%確信することはできませんが、それが私の最善の推測です。さまざまなキャッシュ手法、主にリンク#1のpngキャッシュを試してください。

于 2013-02-23T12:15:42.653 に答える
3

パスを描画するには、GPUに線を描画するように「指示」するだけでは不十分です。パスには多くの特性があります。たとえば、線の端がどのように扱われるか、線が点線であるか、GPUで高速化されていないものなどです。CPUとGPUのアクセラレーションの組み合わせを遅くする多くの回線に遭遇すると、おそらく別の問題が発生します。canvas.drawLines代わりに移動しcanvs.drawPath、派手な方法を使用しないようにする上記の推奨される解決策Paintが役立つ場合があります。

それでも問題が解決しない場合は、GLSurfaceViewを使用して、代わりにラインを直接レンダリングしてみてください。これにはOpenGLESの知識が含まれますが、信じられないほど難しいことではなく、はるかに効果的かもしれません。

于 2013-03-06T22:52:20.050 に答える