0

我目前正在尝试优化我的代码以更快地运行。目前更新大约 3776000 字节大约需要 +30 毫秒。如果我删除outPx函数内部的更新,它会以大约 3 毫秒的速度运行,这意味着更新outPx是使函数变慢的原因。

任何有关如何提高下面我的功能速度的潜在反馈将不胜感激。

uint8_t* outPx = (uint8_t*)out.data;
for (int px=0; px<pxSize; px+=4)
    {
        newTopAlpha = (alpha*inPx[px+3]);

        if (0xff == newTopAlpha)
        {
            // top is opaque covers entire bottom

            // set copy over BGR colors
            outPx[px] = inPx[px];
            outPx[px+1] = inPx[px+1];
            outPx[px+2] = inPx[px+2];
            outPx[px+3] = 0xff; //Fully opaque
        }
        else if (0x00 != newTopAlpha)
        {
            // top is not completely transparent
            topAlpha = newTopAlpha/(float)0xff;
            bottomAlpha = outPx[px+3]/(float)0xff;
            newAlpha = topAlpha + bottomAlpha*(1-topAlpha);
            alphaChange = bottomAlpha*(1-topAlpha);

            outPx[px] = (uint8_t)((inPx[px]*topAlpha + outPx[px]*alphaChange)/newAlpha);
            outPx[px+1] = (uint8_t)((inPx[px+1]*topAlpha + outPx[px+1]*alphaChange)/newAlpha);
            outPx[px+2] = (uint8_t)((inPx[px+2]*topAlpha + outPx[px+2]*alphaChange)/newAlpha);
            outPx[px+3] = (uint8_t)(newAlpha*0xff);
        }
    }
4

3 回答 3

2

uint8_t是一个精确宽度的整数类型,这意味着您要求编译器为您的类型准确分配那么多内存。如果您的系统有对齐要求,这可能会导致代码运行速度变慢。

更改uint8_tuint_fast8_t。这告诉编译器您希望这个变量尽可能为 8 位,但如果它使代码更快,则可以使用更大的大小。

除此之外,还有很多事情可能会导致性能下降,在这种情况下,您需要说明您正在使用的系统和编译器。

于 2013-05-06T11:02:25.180 回答
2

您的代码正在执行浮点除法,并从字节转换为浮点数并再次转换。如果您使用整数数学,它很可能更有效。

即使将这种简单的转换为乘法而不是除法也可能会有所帮助:

newAlpha = 1/(topAlpha + bottomAlpha*(1-topAlpha)); 

... 

outpx = (uint8_t)((inPx[px]*topAlpha + outPx[px]*alphaChange)*newAlpha);

乘法往往比除法快得多。

于 2013-05-06T11:02:36.420 回答
0

好的,如果这确实是瓶颈,并且由于某种随机原因您不能使用 GPU / 内置方法,那么您可以做很多事情:

uint8_t *outPx = (uint8_t*) out.data;
const int cAlpha = (int) (alpha * 256.0f + 0.5f);
for( int px = 0; px < pxSize; px += 4 ) {
    const int topAlpha = (cAlpha * (int) inPx[px|3]) >> 8; // note | not + for tiny speed boost

    if( topAlpha == 255 ) {
        memcpy( &outPx[px], &inPx[px], 4 ); // might be slower than per-component copying; benchmark!
    } else if( topAlpha ) {
        const int bottomAlpha = (int) outPx[px|3];
        const int alphaChange = (bottomAlpha * (255 - topAlpha)) / 255;
        const int newAlpha    = topAlpha + alphaChange;

        outPx[px  ] = (uint8_t) ((inPx[px  ]*topAlpha + outPx[px  ]*alphaChange) / newAlpha);
        outPx[px|1] = (uint8_t) ((inPx[px|1]*topAlpha + outPx[px|1]*alphaChange) / newAlpha);
        outPx[px|2] = (uint8_t) ((inPx[px|2]*topAlpha + outPx[px|2]*alphaChange) / newAlpha);
        outPx[px|3] = (uint8_t) newAlpha;
    }
}

主要的变化是不再有浮点运算(我可能错过了一个/255或什么,但你明白了)。我还删除了重复计算并尽可能使用位运算符。另一个优化是使用固定精度算术将 3 个除法更改为一次除法和 3 个乘法/位移。但是您必须进行基准测试以确认确实有帮助。memcpy 可能会更快。同样,您需要进行基准测试。

最后,如果您对图像有所了解,则可以向编译器提供有关分支的提示。例如,在 GCC 中,您可以说if( __builtin_expect( topAlpha == 255, 1 ) )如果您知道大部分图像是纯色的,并且alpha是 1.0。


根据评论更新:

出于对理智的热爱,永远不要从不)关闭优化的基准测试。

于 2013-05-06T11:23:17.183 回答