2

編集済み: Windows プラットフォームでの作業。

問題:問題は少なく、アドバイスが多い。私は現在、低レベルのプログラムに非常に精通しているわけではありませんが、コード全体のパフォーマンスを向上させるために、以下のコードを最適化しようとしています。このアプリケーションは、非常に高速な画像処理に依存しています。

現在のパフォーマンス:私のコンピューターでは、これは現在、512x512 の画像に対して約 4 ~ 6 ミリ秒で計算されます。できれば半分に減らしたいと思っています。

制限:このプロジェクトはサイズが大きいため、アプリケーションの根本的な変更を行うのは非常に困難です。そのため、DirectX やその他の GPU メソッドへの移植などはあまり選択肢になりません。プロジェクトは現在機能しています。私は単にそれをより速く機能させる方法を見つけようとしています。

これに対する私の使用に関する特定の情報:このメソッドに入る画像は常に正確に正方形になり、128 の増分になります(ほとんどの場合 512 x 512)。常に同じサイズになります。それ以外には、他にはあまりありません。行列は別の場所で計算されるため、これは行列を画像に適用するだけです。元の画像と新しい画像の両方が使用されているため、画像のコピーが必要です。

これが私の現在の実装です:

void ReprojectRectangle( double *mpProjMatrix, unsigned char *pDstScan0, unsigned char *pSrcScan0, 
        int NewBitmapDataStride, int SrcBitmapDataStride, int YOffset, double InversedAspect, int RectX, int RectY, int RectW, int RectH)
        {
            int      i, j;
            double   Xnorm, Ynorm;
            double  Ynorm_X_ProjMatrix4, Ynorm_X_ProjMatrix5, Ynorm_X_ProjMatrix7;;         
            double   SrcX, SrcY, T;
            int      SrcXnt, SrcYnt;
            int      SrcXec, SrcYec, SrcYnvDec;
            unsigned char   *pNewPtr, *pSrcPtr1, *pSrcPtr2, *pSrcPtr3, *pSrcPtr4;
            int      RectX2, RectY2;

            /* Compensate (or re-center) the Y-coordinate regarding the aspect ratio */
            RectY -= YOffset;   

            /* Compute the second point of the rectangle for the loops */
            RectX2 = RectX + RectW;
            RectY2 = RectY + RectH;

            /* Clamp values (be careful with aspect ratio */
            if (RectY < 0) RectY = 0;
            if (RectY2 < 0) RectY2 = 0;
            if ((double)RectY > (InversedAspect * 512.0)) RectY = (int)(InversedAspect * 512.0);
            if ((double)RectY2 > (InversedAspect * 512.0)) RectY2 = (int)(InversedAspect * 512.0);

            /* Iterate through each pixel of the scaled re-Proj */
            for (i=RectY; i<RectY2; i++)
            {      
            /* Normalize Y-coordinate and take the ratio into account */
            Ynorm = InversedAspect - (double)i / 512.0;

            /* Pre-compute some matrix coefficients */
            Ynorm_X_ProjMatrix4 = Ynorm * mpProjMatrix[4] + mpProjMatrix[12];
            Ynorm_X_ProjMatrix5 = Ynorm * mpProjMatrix[5] + mpProjMatrix[13];
            Ynorm_X_ProjMatrix7 = Ynorm * mpProjMatrix[7] + mpProjMatrix[15];

            for (j=RectX; j<RectX2; j++)
            {
                 /* Get a pointer to the pixel on (i,j) */
                 pNewPtr = pDstScan0 + ((i+YOffset) * NewBitmapDataStride) + j;

                 /* Normalize X-coordinates */
                 Xnorm = (double)j / 512.0;                  

                 /* Compute the corresponding coordinates in the source image, before Proj and normalize source coordinates*/
                 T =    (Xnorm * mpProjMatrix[3] + Ynorm_X_ProjMatrix7);
                 SrcY = (Xnorm * mpProjMatrix[0] + Ynorm_X_ProjMatrix4)/T;
                 SrcX = (Xnorm * mpProjMatrix[1] + Ynorm_X_ProjMatrix5)/T;

                // Compute the integer and decimal values of the coordinates in the sources image                     
                SrcXnt = (int) SrcX;
                SrcYnt = (int) SrcY;
                SrcXec = 64 - (int) ((SrcX - (double) SrcXnt) * 64);
                SrcYec = 64 - (int) ((SrcY - (double) SrcYnt) * 64);

                // Get the values of the four pixels up down right left
                pSrcPtr1 = pSrcScan0 + (SrcXnt * SrcBitmapDataStride) + SrcYnt;
                pSrcPtr2 = pSrcPtr1 + 1;
                pSrcPtr3 = pSrcScan0 + ((SrcXnt+1) * SrcBitmapDataStride) + SrcYnt;
                pSrcPtr4 = pSrcPtr3 + 1;

                SrcYnvDec = (64-SrcYec);

                (*pNewPtr) = (unsigned char)(((SrcYec * (*pSrcPtr1) + SrcYnvDec * (*pSrcPtr2)) * SrcXec + 
                                         (SrcYec * (*pSrcPtr3) + SrcYnvDec * (*pSrcPtr4)) * (64 - SrcXec)) >> 12);
            }
        }
    }
4

1 に答える 1

1

マルチプロセッシングと SIMD の 2 つが役に立ちます。マルチプロセッシングを使用すると、出力画像をタイルに分割し、各プロセッサを次に利用可能なタイルで動作させることができます。SIMD命令 (SSE、AVX、AltiVec など) を使用して、複数の座標に対して同じ行列演算を同時に行うなど、同時に複数のことを計算できます。2 つを組み合わせることもできます。SIMD 命令を実行する複数のプロセッサを使用して、可能な限り多くの作業を行います。作業しているプラ​​ットフォームについては言及していません。

于 2012-05-30T23:57:13.563 に答える