2010-05-26 17 views
5

Bu döngüyü, C++ ile yazdım, MSVC2010 ile derlenen çok uzun bir süreye sahip. (300 ms)C++ (VC 2010) 'da garip performans

for (int i=0; i<h; i++) { 
    for (int j=0; j<w; j++) { 
     if (buf[i*w+j] > 0) { 
      const int sy = max(0, i - hr); 
      const int ey = min(h, i + hr + 1); 
      const int sx = max(0, j - hr); 
      const int ex = min(w, j + hr + 1); 
      float val = 0; 
      for (int k=sy; k < ey; k++) { 
       for (int m=sx; m < ex; m++) { 
        val += original[k*w + m] * ds[k - i + hr][m - j + hr]; 
       } 
      } 
      heat_map[i*w + j] = val; 
     } 
    } 
} 

Bana biraz garip görünüyordu, bu yüzden bazı testler sonra montaj satır içi birkaç bit değişti mi: (özellikle, "val" özetliyor kodu)

for (int i=0; i<h; i++) { 
    for (int j=0; j<w; j++) { 
     if (buf[i*w+j] > 0) { 
      const int sy = max(0, i - hr); 
      const int ey = min(h, i + hr + 1); 
      const int sx = max(0, j - hr); 
      const int ex = min(w, j + hr + 1); 
      __asm { 
       fldz 
      } 
      for (int k=sy; k < ey; k++) { 
       for (int m=sx; m < ex; m++) { 
        float val = original[k*w + m] * ds[k - i + hr][m - j + hr]; 
        __asm { 
         fld val 
         fadd 
        } 
       } 
      } 
      float val1; 
      __asm { 
       fstp val1 
      } 
      heat_map[i*w + j] = val1; 
     } 
    } 
} 

Şimdi bu zamanın yarısı, 150ms. Tam olarak aynı şeyi yapıyor, ama neden iki katı kadar hızlı? Her iki durumda da optimizasyon açık olarak Yayın modunda çalıştırıldı. Orijinal C++ kodumda yanlış bir şey yapıyorum? kontrol etmek

+3

Oluşturulan derleme kodunu her iki durumda da karşılaştırmayı denediniz mi? –

cevap

5

Ben derleyici tarafindan desteklenen farklı kayan nokta hesaplama modellerini denemenizi öneririz - herhangi bir sonuca yapmadan önce orijinal kodu ile - precise, strict veya fast (/fp seçeneği bakınız). Orijinal kodunuzun aşırı derecede kısıtlayıcı kayan noktalı bir modelle derlendiğinden şüpheleniyorum (kodun ikinci sürümünde meclisiniz tarafından takip edilmez), bu yüzden orijinali çok daha yavaştır. Başka bir deyişle, orijinal model gerçekten çok kısıtlayıcı ise, o zaman elmaları portakallarla karşılaştırıyordunuz. İlk bakışta görünse bile, iki versiyon da aynı şeyi yapmadı.

Örneğin, kodun ilk sürümünde, ara toplamın float değerinde toplandığını unutmayın. precise modeliyle derlenmişse, val değişkeni en iyi duruma getirilmiş ve bunun yerine dahili FPU kaydı kullanılmış olsa bile, ara sonuçların float türünün hassasiyetine yuvarlanması gerekecektir. Montaj kodunuzda, daha iyi performansa katkıda bulunabilecek olan, birikmiş sonucu yuvarlama zahmetine girmezsiniz.

Kodun iki sürümünü /fp:fast modunda derlemenizi ve bu durumda performanslarının nasıl karşılaştırıldığını görmenizi öneririz.

+0

Teşekkürler!Orijinal kodumu Hızlı modda çalıştırıyorum ve şimdi 80ms hızında çalışıyor, 2. sürüm hala Hızlı modda 150 ms'de çalışıyor, bu yüzden derleyici hala daha iyi biliyor sanırım :) Bu # pragma'nın MSVC için buldum işlev başına yüzer hassas geçiş yapmak için (iç fonksiyonları çalışmıyor): #pragma float_control (hassas, kapalı, itme) ... burada kodu ... #pragma float_control (pop) Ama daha spesifik: http://msdn.microsoft.com/en-us/library/45ec64h6(VS.80).aspx – raicuandi

3

birkaç nokta:

  • Bunu aynı kodudur aslında kontrol etmeniz gerekir. Inline derleme ifadeleriniz derleyici tarafından oluşturulanlarla tam olarak aynı mı? Üç potansiyelinin farkını (potansiyel olarak optimize edilebildiğinden) görebiliyorum. Birincisi, val'un ilk ayarı sıfırdır, ikincisi val1 değişkenidir (büyük olasılıkla yığın işaretçisinin sabit çıkarma işlemini değiştirmesi olası değildir), üçüncüsü, satır içi montaj sürümünüzün ara sonuçları vermemesidir val'a dönüş.

  • Örnek alanınızın büyük olduğundan emin olmanız gerekir. İstatistiklerinizde "gürültünün" etkisini ortadan kaldırmak için, her bir sürümden veya bir yüz koşudan sadece bir koşuyu yapıp yapmadığınızı, daha fazla koşmanın, daha iyi bir şey yapıp yapmadığınızı söylemediniz.

  • Daha da iyi bir ölçüm, geçen süreden ziyade CPU zamanı olabilir. Geçen süre, çevresel değişikliklere tabidir (virüs denetleyiciniz veya test ettiğiniz sırada bir şey yapmaya karar verdiğiniz hizmetlerinizden biri gibi). Büyük örnek uzayı hafifletecek, ancak bunu mutlaka çözmeyecek.

İlgili konular