代码之家  ›  专栏  ›  技术社区  ›  tommyk

线条绘制程序

  •  1
  • tommyk  · 技术社区  · 17 年前

    如何优化此线条绘制例程?记忆会更快地工作吗?

    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 回复  |  直到 17 年前
        1
  •  4
  •   George Phillips    17 年前

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

    memset(Put, Color, iLen);
    

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

    当然,只有当COLORVAL为字符大小时,此memset()用法才有效。

        2
  •  1
  •   Skizz    17 年前

    不,不是真的。memcpy复制内存,即读和写,你不需要读。memset只写,只写字节,所以这也不起作用,除非COLORVAL也是一个字节。不,保持原样,编译器应该生成相当好的代码。别忘了,你可能会受到内存带宽的限制。

        3
  •  1
  •   Andy J Buchanan    17 年前

    在做其他事情之前,你最好的选择是使用你现有的任何低级分析工具。至少要为一个庞大的测试用例或3获得一个总体时间。没有基线测量,你是在黑暗中拍摄的。(我应该知道,我和其他人一样有罪!)

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

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

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

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

    4. 当然,最快的选择通常是诉诸于组装。

        4
  •  0
  •   DeusAduro    17 年前

        5
  •  0
  •   Nick Dandoulakis    17 年前

    在汇编中绘制水平线(即用值填充数组)的最快方法之一是使用 stosb, stosw, stosd stosb

    __asm {
            cld
            mov eax, color
            mov ecx, screen_width
            mov edi, video_buffer
            rep stosd
    }
    

    但我很确定你的内心 while 编译器将优化循环以使用 stosd

        6
  •  0
  •   Mike Dunlavey    17 年前

    坦率地说,对于更现实的情况,你不仅有颜色,还有宽度、线条样式和端点样式,更不用说XOR和混叠等绘图模式了,我看到的方法是

    1. 每条“线”实际上都是一个多边形填充,有相当快的算法(这实际上就是你的算法),和/或

    2. 一个特殊用途的机器语言例程是动态生成的(存储在堆栈上),因为选项太多,无法有特定于选项的特殊例程,而且你不希望算法不断地逐像素质疑选项是什么。