画线程序

时间:2009-07-20 16:42:11

标签: c++ optimization graphics

如何优化此线描例程? 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++;
    }
}

6 个答案:

答案 0 :(得分:4)

我认为你的意思是说“memset”而不是“memcpy”。替换这段代码:

while (iLen--)
{
    *Put++ = Color;
}

memset(Put, Color, iLen);

可能更快,但这取决于您的目标CPU,内存架构和遇到的iLen的典型值。这不太可能是一场大胜利,但是如果你有时间我会鼓励你去测量替代方案,因为这种练习是真正理解优化的唯一方法。

当然,只有COLORVAL的字符大小才能使用这个memset()。

答案 1 :(得分:1)

不,不是真的。 memcpy复制内存,这是一个读取和写入,您不需要读取。 memset只写入,只写字节,因此也不会起作用,除非COLORVAL也是一个字节。不,保持原样,编译器应该生成相当多的代码。不要忘记您可能受内存带宽的限制。

答案 2 :(得分:1)

在做任何其他事情之前,最好的选择是使用您可用的任何低级分析工具。至少得到一个大型测试案例的整体时间或3.没有基线测量你在黑暗中拍摄。 (我应该知道,我和其他人一样对此感到内疚!)

那就是说我注意到你的代码看起来每个像素都有相当多的开销,

  1. memset()调用可能是胜利(如果COLORVAL是sizeof(char))。

  2. 或者,展开循环可能会有所帮助 - 这在很大程度上取决于您的输入数据,机器架构等。

  3. 如果您的iLen值合理有限,您可以考虑为每个完全展开的iLen值编写一个自定义函数(内联开关中的前几个小的情况),并通过一组函数指针调用更大的情况。

  4. 当然,最快的选择通常是采用装配。

答案 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和锯齿等绘图模式,我看到它的方式是

  1. 每个“line”实际上都是一个多边形填充,其中有很快的算法(实际上是你的算法)和/或

  2. 特殊用途的机器语言例程是即时生成的(存储在堆栈中),因为有太多选项可以使用特定于选项的特殊例程,并且您不希望算法持续存在逐个像素地询问选项是什么。