【问题标题】:SSE optimization of Gaussian blur高斯模糊的 SSE 优化
【发布时间】:2014-01-07 02:26:04
【问题描述】:

我正在做一个学校项目,我必须优化 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

【问题讨论】:

  • 您在学校了解 SSE 吗?这很酷。
  • 是的 :),它是关于高级汇编程序的自愿主题,但截止日期即将到来,我在这方面坚持了很长时间:/
  • 不幸的是,如果您想使用 SSE,我认为您将不得不完全重新实现它。您应该预先计算一维系数内核,然后使用 SSE 在每个轴上执行卷积。

标签: c++ optimization sse simd gaussianblur


【解决方案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. 还可以考虑重新考虑整个算法。当前的一个看起来并不平行。也许你可以忽略精度,或者增加一点标量时间?

【讨论】:

  • 我希望我能正确理解你,伙计,我已经尝试过了,它有效,但问题在于 sum += dif + fRadius*p; ,我需要使用前一个周期的差异,当我尝试一次计算 4 个周期时我无法获得
  • @user2174310,我明白了。您应该尝试并行化外循环。但是如果没有指令重载,代码将变得难以管理。
  • 快 4.7 倍(大约),外循环并行化,感谢各位的建议
猜你喜欢
  • 2020-10-18
  • 2017-08-27
  • 2018-05-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 2011-12-07
相关资源
最近更新 更多