2009-07-20 57 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. 專用機器語言程序是即時生成的(存儲在堆棧中),因爲有太多的選項需要特定於特定選項的特殊例程,並且您不希望算法不斷逐個像素地詢問選項是什麼。