2011-04-13 85 views
4

當我從循環中刪除測試以計算最小值和最大值時,執行時間實際上比測試更長。這怎麼可能?當我刪除代碼時,爲什麼我的循環速度較慢

編輯: 運行更多的測試後,似乎運行時間不是恆定的,即相同的代碼 可以運行在9秒或13秒....所以這只是一個可重複的巧合。 Repetable直到你足夠的測試,是...

一些細節:

  • 執行時間與最小最大測試:9秒
  • 執行時間沒有最小最大測試:13秒
  • CFLAGS=-Wall -O2 -fPIC -g
  • GCC 4.4.3 32位 第除去現在在碼所指示

有些猜測: 緩存交互不良?

void FillFullValues(void) 
{ 
    int i,j,k; 
    double X,Y,Z; 
    double p,q,r,p1,q1,r1; 
    double Ls,as,bs; 
    unsigned long t1, t2; 

    t1 = GET_TICK_COUNT(); 
    MinLs = Minas = Minbs = 1000000.0; 
    MaxLs = Maxas = Maxbs = 0.0; 

    for (i=0;i<256;i++) 
    { 
     for (j=0;j<256;j++) 
     { 
      for (k=0;k<256;k++) 
      { 
       X = 0.4124*CielabValues[i] + 0.3576*CielabValues[j] + 0.1805*CielabValues[k]; 
       Y = 0.2126*CielabValues[i] + 0.7152*CielabValues[j] + 0.0722*CielabValues[k]; 
       Z = 0.0193*CielabValues[i] + 0.1192*CielabValues[j] + 0.9505*CielabValues[k]; 

       p = X * InvXn; 
       q = Y; 
       r = Z * InvZn; 

       if (q>0.008856) 
       { 
        Ls = 116*pow(q,third)-16; 
       } 
       else 
       { 
        Ls = 903.3*q; 
       } 

       if (q<=0.008856) 
       { 
        q1 = 7.787*q+seiz; 
       } 
       else 
       { 
        q1 = pow(q,third); 
       } 

       if (p<=0.008856) 
       { 
        p1 = 7.787*p+seiz; 
       } 
       else 
       { 
        p1 = pow(p,third); 
       } 

       if (r<=0.008856) 
       { 
        r1 = 7.787*r+seiz; 
       } 
       else 
       { 
        r1 = pow(r,third); 
       } 

       as = 500*(p1-q1); 
       bs = 200*(q1-r1); 

       // 
       // cast on short int for reducing array size 
       // 
       FullValuesLs[i][j][k] = (char) (Ls); 
       FullValuesas[i][j][k] = (char) (as); 
       FullValuesbs[i][j][k] = (char) (bs); 

          //// Remove this and get slower code  
       if (MaxLs<Ls) 
        MaxLs = Ls; 
       if ((abs(Ls)<MinLs) && (abs(Ls)>0)) 
        MinLs = Ls; 

       if (Maxas<as) 
        Maxas = as; 
       if ((abs(as)<Minas) && (abs(as)>0)) 
        Minas = as; 

       if (Maxbs<bs) 
        Maxbs = bs; 
       if ((abs(bs)<Minbs) && (abs(bs)>0)) 
        Minbs = bs; 
          //// End of Remove 

      } 
     } 
    } 

    TRACE(_T("LMax = %f LMin = %f\n"),(MaxLs),(MinLs)); 
    TRACE(_T("aMax = %f aMin = %f\n"),(Maxas),(Minas)); 
    TRACE(_T("bMax = %f bMin = %f\n"),(Maxbs),(Minbs)); 
    t2 = GET_TICK_COUNT(); 
    TRACE(_T("WhiteBalance init : %lu ms\n"), t2 - t1); 
} 
+3

你在說什麼運行時間?你有多少個樣品?您是否嘗試在定時部分之外移動輸出語句? – Erik 2011-04-13 15:24:21

+3

'執行時間實際上比測試長':小心顯示** _什麼測試已被刪除?**'測試'不完全清楚(把它放得輕微,把它溫和地) – sehe 2011-04-13 15:31:46

+2

什麼是確切的線你刪除了? – 2011-04-13 15:31:54

回答

2

我想編譯器試圖展開內部循環,因爲你正在消除迭代之間的依賴關係。但不知何故,這對你的情況沒有幫助。也許是因爲循環太大,並使用太多的寄存器來展開。

嘗試關閉展開並再次發佈結果。

如果是這樣的話,我會建議你向gcc提交一個性能問題。

PS。我想你可以合併if (q>0.008856)if (q<=0.008856)

+0

使用--params max-unrolled-insns = 10禁用展開似乎會給出更好的結果,但看起來我的時間測量在不同的運行中不是恆定的 – shodanex 2011-04-13 16:13:28

+0

看起來您正在使用'clock'函數:'clock()函數返回程序使用的處理器時間的近似值。' – Elalfer 2011-04-13 16:16:52

1

也許它的緩存,也許解開問題,只有一種方法來回答這個問題:查看生成的代碼(例如通過使用-S選項)。也許你可以發佈它或者在比較它們時發現差異。

編輯:正如你現在澄清說,這只是我只能推薦(或更好的命令;-)你,當你想要得到運行時數字的測量:總是把它放到一個循環,並將其平均。最好在程序之外(在shell腳本中)完成,因此你的緩存還沒有被正確的數據填充。

+0

比較什麼?並且,您如何通過查看assm來檢測緩存問題。我認爲最好是通過逐層關閉性能並使用oprofile或VTune來定位問題來檢測哪種優化會打破性能。 – Elalfer 2011-04-13 16:12:47

+1

比較帶有和不帶最小/最大代碼的彙編代碼的輸出。你不會檢測到緩存問題 - 但有50%的差異,我認爲它不僅僅是緩存問題。在那裏我會期待不同的代碼。 – flolo 2011-04-13 16:43:02

+0

問題在於較大的代碼有時可能工作得更快。但是你有一點:如果你看到更快的代碼沒有被展開,那麼試着關閉展開。 – Elalfer 2011-04-13 16:45:52

相關問題