2009-07-20 56 views
1

如何优化这个线条画例程? 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

一些额外的信息: - COLORVAL - > uint16_t - 平台 - > IMX31 ARM – tommyk 2009-07-21 07:19:09

回答

4

我想你的意思是说“memset”而不是“memcpy”。更换代码的此位:

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

memset(Put, Color, iLen); 

可能会更快,但是这在很大程度上取决于你的目标CPU,内存架构和遇到艾朗的典型值。这不可能是一个巨大的胜利,但如果你有时间,我鼓励你衡量替代品,因为这种锻炼是真正理解优化的唯一途径。

当然,这个memset()的使用只有在COLORVAL是字符大小的情况下才会起作用。

1

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

0

我已经通过个人经验发现memcpy比直接指针访问稍微快一点,但只是略微,通常不是一个突破性的优化。

0

在汇编中绘制水平线,又名用数值填充数组的一种最快方法是使用stosb, stosw, stosd指令。 memset优化为使用stosb。要使用的DWORD值,我们可以编写代码类似下面画一条线,

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

但我敢肯定的是你的内心while循环将被编译器使用stosd反正进行优化。

1

在做任何事情之前,最好的办法就是使用你可用的低级分析工具。至少得到一个大型测试案例的总体时间,或者3.在没有基线测量的情况下,您在黑暗中拍摄。 (我应该知道,我是有罪的这是其他任何人!)

不过我注意到,你的代码看起来像它具有每像素开销公平一点,

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

  2. 或者,展开循环可能会帮助 - 这在很大程度上取决于你的输入数据,计算机体系结构等

  3. 如果您艾朗值合理界定你可能会考虑写一个自定义功能为每个艾朗值完全展开(内联开关中的前几个小案例),并通过一组函数指针调用较大的案例。

  4. 当然最快的选择通常是诉诸大会。

0

您可以尝试展开内部循环,但实际上它只对接近水平的线条起作用。

对于不接近水平的线条,可能需要花更多时间来设置扫描指针表。坦白地说,对于更逼真的情况,不仅有颜色,而且还有宽度,线条样式和结束样式,更不用说绘制模式如异或和别名,我已经看到它完成的方式是

  1. 每个“行”是一个真正的多边形填充,对于其中有相当快的算法(实际上是你的算法是什么),和/或

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