1

私は学校のプロジェクトに取り組んでおり、SSE のコードの一部を最適化する必要がありますが、一部で数日間立ち往生しています。

このコード(ガウスぼかしアルゴリズムの一部)でベクトルSSE命令(インラインアセンブラー/ instric f)を使用するスマートな方法は見当たりません。少しでもヒントになれば幸いです

for (int x = x_start; x < x_end; ++x)     // vertical blur...
    {
        float sum = image[x + (y_start - radius - 1)*image_w];
        float dif = -sum;

        for (int y = y_start - 2*radius - 1; y < y_end; ++y)
        {                                                   // inner vertical Radius loop           
            float p = (float)image[x + (y + radius)*image_w];   // next pixel
            buffer[y + radius] = p;                         // buffer pixel
            sum += dif + fRadius*p;
            dif += p;                                       // accumulate pixel blur

            if (y >= y_start)
            {
                float s = 0, w = 0;                         // border blur correction
                sum -= buffer[y - radius - 1]*fRadius;      // addition for fraction blur
                dif += buffer[y - radius] - 2*buffer[y];    // sum up differences: +1, -2, +1

                // cut off accumulated blur area of pixel beyond the border
                // assume: added pixel values beyond border = value at border
                p = (float)(radius - y);                   // top part to cut off
                if (p > 0)
                {
                    p = p*(p-1)/2 + fRadius*p;
                    s += buffer[0]*p;
                    w += p;
                }
                p = (float)(y + radius - image_h + 1);               // bottom part to cut off
                if (p > 0)
                {
                    p = p*(p-1)/2 + fRadius*p;
                    s += buffer[image_h - 1]*p;
                    w += p;
                }
                new_image[x + y*image_w] = (unsigned char)((sum - s)/(weight - w)); // set blurred pixel
            }
            else if (y + radius >= y_start)
            {
                dif -= 2*buffer[y];
            }
        } // for y
    } // for x
4

1 に答える 1

1
  1. 使用できるもう 1 つの機能は、論理演算とマスクです。

たとえば、次の代わりに:

  // process only 1
if (p > 0)
    p = p*(p-1)/2 + fRadius*p;

あなたは書ける

  // processes 4 floats
const __m128 &mask = _mm_cmplt_ps(p,0);
const __m128 &notMask = _mm_cmplt_ps(0,p);
const __m128 &p_tmp = ( p*(p-1)/2 + fRadius*p );
p = _mm_add_ps(_mm_and_ps(p_tmp, mask), _mm_and_ps(p, notMask)); // = p_tmp & mask + p & !mask
  1. また、命令をオーバーロードする特別なライブラリを使用することをお勧めします。例: http://code.compeng.uni-frankfurt.de/projects/vc

  2. dif変数は、内側のループの反復を依存させます。外側のループを並列化するようにしてください。しかし、オーバーロードする命令がなければ、コードは管理不能になります。

  3. また、アルゴリズム全体を再考することも検討してください。現在のものは平行に見えません。精度を無視するか、スカラー時間を少し増やすことができますか?

于 2013-12-18T19:08:15.167 に答える