如果我们在内循环中有一个除法,那么添加特殊案例处理以消除划分是明智的:
之前:
int collapseFactorDepth...
for (int i = 0; i < numPixels; i++)
{
pDataTarget[i] += pPixelData[i] / collapseFactorDepth;
}
在:
if (collapseFactorDepth != 1)
{
for (int i = 0; i < numPixels; i++)
{
pDataTarget[i] += pPixelData[i] / collapseFactorDepth;
}
}
else
{
for (int i = 0; i < numPixels; i++)
{
pDataTarget[i] += pPixelData[i];
}
}
编译器可以自己解释这个吗?现代CPU是否包含任何优化此功能的方法?
如果您认为附加代码与性能增益相比有什么好处(有没有?),我特别感兴趣。
背景:
答案 0 :(得分:2)
作为一般规则,答案是否。首先编写清晰的代码,然后在探查器告诉您出现问题时对其进行优化。
回答此特定优化是否有助于此特定热点的唯一方法是:“测量并查看”。
除非collapseFactorDepth
几乎始终 1,或numPixels
非常大(至少数千且可能更多),否则我不希望优化有所帮助(分支是昂贵的)。
您更有可能从使用SSE或类似的SIMD指令中受益。
答案 1 :(得分:0)
int identity(int pixel)
{
return pixel;
}
template<int collapseFactorDepth>
int div(int pixel)
{
return pixel / collapseFactorDepth;
}
struct Div
{
int collapseFactorDepth_;
Div(collapseFactorDepth)
: collapseFactorDepth(collapseFactorDepth_) {}
int operator()(int pixel)
{
return pixel / collapseFactorDepth_;
}
};
template<typename T>
void fn(int* pDataTarget, T fn)
{
for (int i = 0; i < numPixels; i++)
{
pDataTarget[i] += fn(pPixelData[i]);
}
}
void fn(int* pDataTarget)
{
fn(pDataTarget, identity);
}
template<int collapseFactorDepth>
void fnComp()
{
fn(pDataTarget, div<collapseFactorDepth>);
}
void fn(int* pDataTarget, int collapseFactorDepth)
{
fn(pDataTarget, Div(collapseFactorDepth));
}
这为您提供了一个方便的默认行为,一个编译时除法(可能比div-by-int更快)和一种方式(传递Div
)到指定运行时行为。