2012-05-08 21 views
1

我有一些專有的圖像處理代碼。它遍歷圖像並計算圖像上的一些統計數據。下面可以看到我所談論的那種代碼的一個例子,雖然這是而不是需要優化的算法。如何描述/識別緊密處理循環中的緩慢步驟?

我的問題是,有哪些工具可用於分析這些緊密環路,以確定事情發展緩慢的地方?昏昏欲睡,Windows性能分析器更側重於識別哪些方法/功能較慢。我已經知道什麼功能很慢,我只需要弄清楚如何優化它。

void BGR2YUV(IplImage* bgrImg, IplImage* yuvImg) 
{ 
    const int height = bgrImg->height; 
    const int width  = bgrImg->width; 
    const int step  = bgrImg->widthStep; 
    const int channels = bgrImg->nChannels; 

    assert(channels == 3); 
    assert(bgrImg->height == yuvImg->height); 
    assert(bgrImg->width == yuvImg->width); 
    // for reasons that are not clear to me, these are not the same. 
    // Code below has been modified to reflect this fact, but if they 
    // could be the same, the code below gets sped up a bit. 
// assert(bgrImg->widthStep == yuvImg->widthStep); 
    assert(bgrImg->nChannels == yuvImg->nChannels); 

    const uchar* bgr = (uchar*) bgrImg->imageData; 
      uchar* yuv = (uchar*) yuvImg->imageData; 

    for (int i = 0; i < height; i++) 
    { 
     for (int j = 0; j < width; j++) 
     { 
      const int ixBGR = i*step+j*channels; 
      const int b = (int) bgr[ixBGR+0]; 
      const int g = (int) bgr[ixBGR+1]; 
      const int r = (int) bgr[ixBGR+2]; 

      const int y = (int) (0.299 * r + 0.587 * g + 0.114 * b); 
      const double di = 0.596 * r - 0.274 * g - 0.322 * b; 
      const double dq = 0.211 * r - 0.523 * g + 0.312 * b; 
      // Do some shifting and trimming to get i & q to fit into uchars. 
      const int iv = (int) (128 + max(-128.0, min(127.0, di))); 
      const int q = (int) (128 + max(-128.0, min(127.0, dq))); 

      const int ixYUV = i*yuvImg->widthStep + j*channels; 
      yuv[ixYUV+0] = (uchar)y; 
      yuv[ixYUV+1] = (uchar)iv; 
      yuv[ixYUV+2] = (uchar)q; 
     } 
    } 
} 
+2

使用體面的採樣分析器。如果你堅持使用Windows,那麼最好的辦法就是英特爾的VTune。 –

+0

如果您知道哪些功能需要大量時間,請將其拆開並仔細查看內部循環中生成的說明。 – TJD

+1

Visual Studio沒有最好的分析器,但它的確不錯。 Google for'visual studio profiler'。或google your_favourite_os profiler – Sam

回答

1

既然你不能分享代碼,我有一些一般性的建議。首先記住分析器告訴你什麼部分代碼需要更多時間,更高級的代碼可以建議進行一些修改以提高速度。但總的來說,算法優化比調整代碼要快得多。對於你分享的示例代碼,如果你谷歌高效或快速的RGB到YUV轉換,你會發現大量的方法(從使用查找表到SSE2和GPU利用率),大大提高了速度,我敢肯定,沒有一個分析器可以建議其中的任何一個。

所以一旦你知道什麼是方法的一部分是緩慢的,你可以按照以下兩個步驟:

  1. 算法優化:明白什麼算法,並試着拿出更優化算法。谷歌是你的朋友,很可能有人已經想過優化這個算法,並且已經與世界分享了想法/代碼。通過,通常你應該考慮你的限制。例如,加速代碼的最簡單但最有效的圖像處理方法是儘可能減小圖像的大小。一個好的經驗法則是對代碼/算法中的每一個假設提出質疑。例如,處理800x600的圖像是否必要?或者可以將尺寸減小到320x240而不影響準確性?處理三通道圖像是必要的嗎?或者使用灰度圖像可以實現相同效果?我想你應該已經明白了。

  2. 實施優化:一些先進的分析工具可以建議如何調整代碼,你可以嘗試找到一個負擔得起的代碼。有些人可能不同意,但我不認爲有必要使用這些工具。通常圖像處理精確值不是必需的,例如,可能使用整數對濾波器響應進行粗略近似,而不是使用雙浮點數進行精確計算。 SIMD指令和最近的GPU已被證明非常適合優化圖像處理方法。如果可以這樣做,你應該考慮這一點。你總是可以谷歌如何優化循環或某些特定的操作。畢竟你所能做的只是將你的代碼分解成更小的邏輯塊並改變它,這樣算法或者方法就不會通過共享這些塊而暴露出來。然後你可以分享每一個SO,並詢問其他人如何優化它的意見。

+0

這些都是好的。我發現優化上述算法,只是從浮點更改爲整數算術加速了一個數量級,SSE2和類似的選項我們將會研究,你用過SSE2嗎?你見過什麼樣的速度改進?我發現很難得到任何「感覺」 – John

+1

通過使用SSE2加速非常接近它的承諾如果你設法重寫代碼以高效的方式使用SSE2並且用一條指令處理四個操作數,那麼你的部分代碼將會是快四倍。 – fireant