我目前正在尝试优化我的代码以更快地运行。目前大约需要30ms来更新大约3776000字节。如果我删除了我的函数中的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);
}
}
答案 0 :(得分:2)
您的代码正在执行浮点除法,并且从字节转换为浮点数并再次返回。如果使用整数数学,则很可能更有效。
即使这样简单的转换乘法而不是除法也可能有所帮助:
newAlpha = 1/(topAlpha + bottomAlpha*(1-topAlpha));
...
outpx = (uint8_t)((inPx[px]*topAlpha + outPx[px]*alphaChange)*newAlpha);
乘法往往比分裂快得多。
答案 1 :(得分:1)
uint8_t
是精确宽度整数类型,这意味着您要求编译器为您的类型准确分配那么多内存。如果您的系统具有对齐要求,则可能导致代码运行速度变慢。
将uint8_t
更改为uint_fast8_t
。这告诉编译器如果可能的话,你希望这个变量是8位,但是如果它使代码更快就可以使用更大的大小。
除此之外,还有许多可能导致性能不佳的事情,在这种情况下,您需要说明您正在使用的系统和编译器。
答案 2 :(得分: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 ) )
是1.0,则可以说alpha
。
根据评论更新:
对于对理智的热爱,永远不会(从不)基准优化关闭。