2012-04-04 12 views
6

私はWinFormsを使用して従来のマップビューアアプリケーションを持っています。それはsloooooowです。 (速度は許容されるが、Google Maps、Google Earthが登場し、ユーザーは腐敗してしまった。)もっと速くすればもっと速く作ることができるようになりました:GPUに座標変換をオフロード

明白な速度向上何も描画する必要はありません、など)、私のプロファイラは私が実際の窒息ポイントは座標変換であることを私に示してマップスペースからスクリーンスペースにポイントを変換するとき。 通常、変換コードは次のようになります。

public Point MapToScreen(PointF input) 
    { 
     // Note that North is negative! 
     var result = new Point(
      (int)((input.X - this.currentView.X) * this.Scale), 
      (int)((input.Y - this.currentView.Y) * this.Scale)); 
     return result; 
    } 

実際の実装はトリッキーです。緯度/経度は整数で表されます。精度が失われないように、それらは2^20(〜100万)倍になります。これが座標の表現方法です。

public struct Position 
{ 
    public const int PrecisionCompensationPower = 20; 
    public const int PrecisionCompensationScale = 1048576; // 2^20 
    public readonly int LatitudeInt; // North is negative! 
    public readonly int LongitudeInt; 
} 

ことが可能スケールファクタはまた、明示的にこれは、私たちはビットシフトとの乗算を交換することを可能にする2のべき乗にバインドされていることが重要です。だから、本当のアルゴリズムは次のようになります。

public Point MapToScreen(Position input) 
    { 
     Point result = new Point(); 
     result.X = (input.LongitudeInt - this.UpperLeftPosition.LongitudeInt) >> 
        (Position.PrecisionCompensationPower - this.ZoomLevel); 
     result.Y = (input.LatitudeInt - this.UpperLeftPosition.LatitudeInt) >> 
        (Position.PrecisionCompensationPower - this.ZoomLevel); 
     return result; 
    } 

(UpperLeftPositionは、マップスペースの画面の左上隅をrepresentents。) 私はGPUにこの計算をオフロードするの、今考えています。誰も私に例を示すことができますか?

私たちは.NET4.0を使用しますが、コードはWindows XPでも実行するのが望ましいです。さらに、GPLの下にあるライブラリは使用できません。

答えて

1

ここ1年後、問題が再び発生し、非常に珍しい答えが見つかりました。私は少し前にそれを実現していない愚かな気がします。地理的要素を通常のWinForms GDI経由でビットマップに描画します。 GDIはハードウェアアクセラレーションです。 は、System.Drawing.Graphicsオブジェクトの縮尺パラメータをに設定しています。 Graphics.TranslateTransform(...)とGraphics.ScaleTransform(...) 私たちは自分で変換するのではなく、ビットシフトでもトリックが必要です。

:)

2

私はあなたがこれを行うにはOpenCLのを使用してClooで見てください - vector add exampleを見てみると、2つのComputeBuffer秒(各ポイントでLatitudeIntLongitudeIntごとに1つずつ)にを使用して値をマッピングするために、これを変更します2出力ComputeBuffer s。 OpenCLコードは次のようになります:

__kernel void CoordTrans(__global int *lat, 
         __global int *lon, 
         __constant int ulpLat, 
         __constant int ulpLon, 
         __constant int zl, 
         __global int *outx, 
         __global int *outy) 
{ 
    int i = get_global_id(0);   
    const int pcp = 20; 

    outx[i] = (lon[i] - ulpLon) >> (pcp - zl); 
    outy[i] = (lat[i] - ulpLat) >> (pcp - zl); 
} 

ただし、コアごとに複数のcoord-transformを実行します。私は急いでする必要があります、私はあなたがこれを行う前にopenclで読むことをお勧めします。

また、coordsの数が合理的である場合(< 100,000/1,000,000)、非gpuベースのソリューションはおそらくより高速になります。

1

私はCUDAのバックグラウンドから来ており、NVIDIA GPUでしか話すことができませんが、ここに入ります。

これをGPUで行う際の問題は、操作/転送時間です。

要素ごとに実行する操作の順序は1つです。本当にスピードを上げるには、要素ごとにこれ以上のことをしたいと思っています。グローバルメモリとGPU上のスレッド間の帯域幅は約100GB/sです。したがって、1つのFLOPを実行するために1つの4バイト整数をロードする必要がある場合、理論上の最大速度は100/4 = 25 FLOPSです。これは広告された何百ものFLOPSからは遠いです。

これは理論上の最大値であることに注意してください。実際の結果は悪化する可能性があります。また、複数の要素を読み込んでいる場合は、これはさらに悪化します。あなたのケースでは、2のように見えるので、最大12.5 FLOPSを得ることができます。実際には、それはほぼ確実に低くなります。

これがあなたには大丈夫だと聞こえたら、それを聞いてください!

+0

+1理論的境界を示すため。 – user256890

+0

数字をパースペクティブに入れるだけで、平均2コアCPUのおよその速度はどのくらいですか? – user256890

+0

これはあなたがFLOPと呼ぶものによって異なります。たとえば、2コアCPUのクロック速度が2 GHzで、FLOPが4クロックサイクルかかるとします。あなたは2 * 2/4 = 1 GFLOPを行うことができます。それは非常に原油の推定値です。 –

関連する問題