如何优化此线描例程? memcpy的工作会更快吗?
void ScreenDriver::HorizontalLine(int wXStart, int wXEnd, int wYPos,
COLORVAL Color, int wWidth)
{
int iLen = wXEnd - wXStart + 1;
if (iLen <= 0)
{
return;
}
while(wWidth-- > 0)
{
COLORVAL *Put = mpScanPointers[wYPos] + wXStart;
int iLen1 = iLen;
while(iLen1--)
{
*Put++ = Color;
}
wYPos++;
}
}
答案 0 :(得分:4)
我认为你的意思是说“memset”而不是“memcpy”。替换这段代码:
while (iLen--)
{
*Put++ = Color;
}
与
memset(Put, Color, iLen);
可能更快,但这取决于您的目标CPU,内存架构和遇到的iLen的典型值。这不太可能是一场大胜利,但是如果你有时间我会鼓励你去测量替代方案,因为这种练习是真正理解优化的唯一方法。
当然,只有COLORVAL的字符大小才能使用这个memset()。
答案 1 :(得分:1)
不,不是真的。 memcpy复制内存,这是一个读取和写入,您不需要读取。 memset只写入,只写字节,因此也不会起作用,除非COLORVAL也是一个字节。不,保持原样,编译器应该生成相当多的代码。不要忘记您可能受内存带宽的限制。
答案 2 :(得分:1)
在做任何其他事情之前,最好的选择是使用您可用的任何低级分析工具。至少得到一个大型测试案例的整体时间或3.没有基线测量你在黑暗中拍摄。 (我应该知道,我和其他人一样对此感到内疚!)
那就是说我注意到你的代码看起来每个像素都有相当多的开销,
memset()调用可能是胜利(如果COLORVAL是sizeof(char))。
或者,展开循环可能会有所帮助 - 这在很大程度上取决于您的输入数据,机器架构等。
如果您的iLen值合理有限,您可以考虑为每个完全展开的iLen值编写一个自定义函数(内联开关中的前几个小的情况),并通过一组函数指针调用更大的情况。
当然,最快的选择通常是采用装配。
答案 3 :(得分:0)
我通过个人经验发现,memcpy比直接指针访问稍微快一些......但只是略微,它通常不是一个突破性的优化。
答案 4 :(得分:0)
在汇编中绘制水平线(也就是用数值填充数组)的最快方法之一是使用stosb, stosw, stosd
指令。 memset已优化为使用stosb
。要使用双字值,我们可以编写如下所示的代码来绘制一条线,
__asm {
cld
mov eax, color
mov ecx, screen_width
mov edi, video_buffer
rep stosd
}
但是我很确定编译器会优化你的内部while
循环以使用stosd
。
答案 5 :(得分:0)
您可以尝试展开内循环,但实际上它只对接近水平的线条很重要。
对于不接近水平的线条,可能需要花费更多时间来设置扫描指针表。
坦率地说,对于更现实的情况,你不仅有颜色,宽度,线条样式和结束样式,更不用说XOR和锯齿等绘图模式,我看到它的方式是
每个“line”实际上都是一个多边形填充,其中有很快的算法(实际上是你的算法)和/或
特殊用途的机器语言例程是即时生成的(存储在堆栈中),因为有太多选项可以使用特定于选项的特殊例程,并且您不希望算法持续存在逐个像素地询问选项是什么。