SORU
19 EKİM 2013, CUMARTESİ


Neden gcc eğer hız yerine BOYUTU için optimize eğer 15-20% daha hızlı kod oluşturur mu?

Ben ilk gcc (benim makinede en azından benim projeler üzerinde ve eğer ben optimize ederseniz daha hızlı kod üretmek için bir eğilim var, 2009 yılında bu farkboyutu(-Os) yerine hızı (-O2 -O3) ve şimdiye kadar neden beri merak edilmiştir.

Bu şaşırtıcı davranış gösterir (çok) saçma bir kod oluşturmak için başarmış ve yeterince küçük buraya asılacak.

const int LOOP_BOUND = 200000000;

__attribute__((noinline))
static int add(const int& x, const int& y) {
    return x   y;
}

__attribute__((noinline))
static int work(int xval, int yval) {
    int sum(0);
    for (int i=0; i<LOOP_BOUND;   i) {
        int x(xval sum);
        int y(yval sum);
        int z = add(x, y);
        sum  = z;
    }
    return sum;
}

int main(int , char* argv[]) {
    int result = work(*argv[1], *argv[2]);
    return result;
}

I -Os, ile derleme 0.38 s Bu programı çalıştırmak için gereken, ve 0.44 -O2 -O3 ile derlenen. Bu kez neredeyse hiç gürültü (4.7.2, gcc x86_64 GNU/Linux, Intel Core ı5-3320M) ile sürekli ve elde edilir.

(Güncelleme: tüm montaj kodları github taşındı: post şişkinlik yaptı fno-align-* bayraklar aynı etkiye sahip olarak. bu soru için çok az değer ekleyin) anlaşılan

-Os -O2 ile oluşturulan derleme. Ne yazık ki, benim anlayışıma göre montajı çok sınırlı, bu yüzden hiçbir fikrim yok olsun bakalım sonra ne yaptım oldu Doğru: aldım montaj için -O2 ve birleştirilmiş tüm farklılıkları içine montaj için -Oshariç.p2align satır here sonuç. Bu kod hala 0.38 s olarak geçertek fark bu.p2alignşeyler.

Eğer doğru tahmin edersem, bu hizalama yığını için doldurma. Why does GCC pad functions with NOPs? göre kodu daha hızlı çalışır umuduyla yapılır ama görünüşe göre bu iyileştirme benim durumumda geri tepti.

Bu durumda suçlu doldurma mı? Neden ve nasıl?

Çıkardığı sesi oldukça fazla mikro-optimizasyon zamanlama imkansız kılıyor.

Nasıl böyle bir kaza sonucu şanslı / şanssız doğrultma işlemi yaptığımda engel olmadığından emin olun C üzerinde mikro-iyileştirme (hizalama yığın ilgisiz) veya C kaynak kodlarını alabilir miyim?


GÜNCELLEME:

Pascal Cuoq's answer aşağıdaki dizilimi ile biraz tinkered. -O2 -fno-align-functions -fno-align-loops gcc geçerek, .p2align tüm montaj gitti ve oluşturulan yürütülebilir 0.38 s çalışır. gcc doc göre:

-Os-O2 tüm iyileştirmeleri [ama] -Os, aşağıdaki optimizasyon bayrakları devre dışı bırakır sağlar:

  -falign-functions  -falign-jumps  -falign-loops 
  -falign-labels  -freorder-blocks  -freorder-blocks-and-partition 
  -fprefetch-loop-arrays

Yani, oldukça fazla (yanlış)uyum sorunu gibi görünüyor.

Hala Marat Dukhan's answer önerilen -march=native hakkında kuşkuluyum. Sadece (yanlış)bu uyum sorunu mani olmuyor ben ikna olmuş değilim; kesinlikle benim makine üzerinde hiçbir etkisi yoktur. (Yine de, onun cevabını ben upvoted.)


GÜNCELLEME 2:

Resmin dışında -Os alabiliriz.Aşağıdaki zamanları ile derleme ile elde edilir

  • *24 0.37* ler

  • *25 0.37* ler

  • -S -O2 work() 0.37 s sonra manuel olarak add() Meclisi hareketli

  • *29 0.44* ler

Arama sitesinden add() mesafe çok önemli gibi görünüyor. perf denedim ama perf stat perf report çıkış bana pek mantıklı gelmiyor. Ancak, tek bir tutarlı sonuç alabilirim:

-O2:

 602,312,864 stalled-cycles-frontend   #    0.00% frontend cycles idle   
       3,318 cache-misses                                                
 0.432703993 seconds time elapsed
 [...]
 81.23%  a.out  a.out              [.] work(int, int)
 18.50%  a.out  a.out              [.] add(int const&, int const&) [clone .isra.0]
 [...]
       │   __attribute__((noinline))
       │   static int add(const int& x, const int& y) {
       │       return x   y;
100.00 │     lea    (%rdi,%rsi,1),x
       │   }
       │   ← retq
[...]
       │            int z = add(x, y);                                                                                                                                 
  1.93 │    → callq  add(int const&, int const&) [clone .isra.0]                                                                                                       
       │            sum  = z;                                                                                                                                          
 79.79 │      add    x,x   

fno-align-* için:

 604,072,552 stalled-cycles-frontend   #    0.00% frontend cycles idle   
       9,508 cache-misses                                                
 0.375681928 seconds time elapsed
 [...]
 82.58%  a.out  a.out              [.] work(int, int)
 16.83%  a.out  a.out              [.] add(int const&, int const&) [clone .isra.0]
 [...]
       │   __attribute__((noinline))
       │   static int add(const int& x, const int& y) {
       │       return x   y;
 51.59 │     lea    (%rdi,%rsi,1),x
       │   }
[...]
       │    __attribute__((noinline))                                                                                                                                  
       │    static int work(int xval, int yval) {                                                                                                                      
       │        int sum(0);                                                                                                                                            
       │        for (int i=0; i<LOOP_BOUND;   i) {                                                                                                                     
       │            int x(xval sum);                                                                                                                                   
  8.20 │      lea    0x0(%r13,%rbx,1),i                                                                                                                             
       │            int y(yval sum);                                                                                                                                   
       │            int z = add(x, y);                                                                                                                                 
 35.34 │    → callq  add(int const&, int const&) [clone .isra.0]                                                                                                       
       │            sum  = z;                                                                                                                                          
 39.48 │      add    x,x                                                                                                                                         
       │    }   

-fno-omit-frame-pointer için:

 404,625,639 stalled-cycles-frontend   #    0.00% frontend cycles idle   
      10,514 cache-misses                                                
 0.375445137 seconds time elapsed
 [...]
 75.35%  a.out  a.out              [.] add(int const&, int const&) [clone .isra.0]                                                                                     ▒
 24.46%  a.out  a.out              [.] work(int, int)  
 [...]
       │   __attribute__((noinline))
       │   static int add(const int& x, const int& y) {
 18.67 │     push   %rbp
       │       return x   y;
 18.49 │     lea    (%rdi,%rsi,1),x
       │   const int LOOP_BOUND = 200000000;
       │
       │   __attribute__((noinline))
       │   static int add(const int& x, const int& y) {
       │     mov    %rsp,%rbp
       │       return x   y;
       │   }
 12.71 │     pop    %rbp
       │   ← retq
 [...]
       │            int z = add(x, y);                                                                                                                                 
       │    → callq  add(int const&, int const&) [clone .isra.0]                                                                                                       
       │            sum  = z;                                                                                                                                          
 29.83 │      add    x,x    

Yavaş durumda add() çağrı oyalamak gibi görünüyor.

İnceledimher şeyiperf -e benim makinede tükürmek olabilir; sadece yukarıda belirtilen istatistikte.

Aynı yürütülebilir için, stalled-cycles-frontend yürütme süresi ile doğrusal korelasyon gösterir; çok net bir şekilde bağ başka bir şey fark etmedi. (Farklı yürütülebilir dosyalar için stalled-cycles-frontend karşılaştırılması bana pek mantıklı gelmiyor.)

İlk Yorum gibi geldi önbellek özlüyor ben dahil. Önbellek performans, yalnızca olanları yukarıda verilen benim makinede ölçülebilen özlüyor hepsini inceledim. Önbellek çok çok gürültülü ve yürütme kez bir ilişki için küçük Haritayı özlüyor.

CEVAP
19 EKİM 2013, CUMARTESİ


Varsayılan Derleyiciler "" işlemci. ortalama için optimize ederek Farklı işlemciler farklı talimat dizileri iyilik beri, derleyici en iyi duruma getirme -O2 etkin ortalama işlemci yarar, ama özellikle işlemci performansı (ve aynı 50 ** için geçerlidir) düşebilir. Eğer farklı işlemciler üzerinde aynı örnek çalışırsanız, bazıları o diğer -Os iyileştirmeler için daha uygun iken -O2 fayda bulacaksınız.

Burada çeşitli işlemciler üzerinde time ./test 0 0 sonuçları (kullanıcı zaman rapor):

Processor (System-on-Chip)             Compiler   Time (-O2)  Time (-Os)  Fastest
AMD Opteron 8350                       gcc-4.8.1    0.704s      0.896s      -O2
AMD FX-6300                            gcc-4.8.1    0.392s      0.340s      -Os
AMD E2-1800                            gcc-4.7.2    0.740s      0.832s      -O2
Intel Xeon E5405                       gcc-4.8.1    0.603s      0.804s      -O2
Intel Xeon E5-2603                     gcc-4.4.7    1.121s      1.122s       -
Intel Core i3-3217U                    gcc-4.6.4    0.709s      0.709s       -
Intel Core i3-3217U                    gcc-4.7.3    0.708s      0.822s      -O2
Intel Core i3-3217U                    gcc-4.8.1    0.708s      0.944s      -O2
Intel Core i7-4770K                    gcc-4.8.1    0.296s      0.288s      -Os
Intel Atom 330                         gcc-4.8.1    2.003s      2.007s      -O2
ARM 1176JZF-S (Broadcom BCM2835)       gcc-4.6.3    3.470s      3.480s      -O2
ARM Cortex-A8 (TI OMAP DM3730)         gcc-4.6.3    2.727s      2.727s       -
ARM Cortex-A9 (TI OMAP 4460)           gcc-4.6.3    1.648s      1.648s       -
ARM Cortex-A9 (Samsung Exynos 4412)    gcc-4.6.3    1.250s      1.250s       -
ARM Cortex-A15 (Samsung Exynos 5250)   gcc-4.7.2    0.700s      0.700s       -
Qualcomm Snapdragon APQ8060A           gcc-4.8       1.53s       1.52s      -Os

Bazı durumlarda gcc belirli bir işlemci (seçenek -mtune=native ya -march=native kullanarak) için optimize sorarak dezavantajlı optimizasyon etkisini azaltabilir:

Processor            Compiler   Time (-O2 -mtune=native) Time (-Os -mtune=native)
AMD FX-6300          gcc-4.8.1         0.340s                   0.340s
AMD E2-1800          gcc-4.7.2         0.740s                   0.832s
Intel Xeon E5405     gcc-4.8.1         0.603s                   0.803s
Intel Core i7-4770K  gcc-4.8.1         0.296s                   0.288s

Güncelleme: Ivy Bridge tabanlı Core i3 üç sürümleri gcc (4.6.4, 4.7.3, ve 4.8.1) üretmek ikili ile önemli ölçüde farklı performans, ama derleme kod var sadece ince farklılıklar. Şimdiye kadar, bu gerçek, hiçbir açıklaması var.

gcc-4.6.4 -Os (0.709 saniye içinde çalıştırır) montaj:

00000000004004d2 <_ZL3addRKiS0_.isra.0>:
  4004d2:       8d 04 37                lea    eax,[rdi rsi*1]
  4004d5:       c3                      ret

00000000004004d6 <_ZL4workii>:
  4004d6:       41 55                   push   r13
  4004d8:       41 89 fd                mov    r13d,edi
  4004db:       41 54                   push   r12
  4004dd:       41 89 f4                mov    r12d,esi
  4004e0:       55                      push   rbp
  4004e1:       bd 00 c2 eb 0b          mov    ebp,0xbebc200
  4004e6:       53                      push   rbx
  4004e7:       31 db                   xor    ebx,ebx
  4004e9:       41 8d 34 1c             lea    esi,[r12 rbx*1]
  4004ed:       41 8d 7c 1d 00          lea    edi,[r13 rbx*1 0x0]
  4004f2:       e8 db ff ff ff          call   4004d2 <_ZL3addRKiS0_.isra.0>
  4004f7:       01 c3                   add    ebx,eax
  4004f9:       ff cd                   dec    ebp
  4004fb:       75 ec                   jne    4004e9 <_ZL4workii 0x13>
  4004fd:       89 d8                   mov    eax,ebx
  4004ff:       5b                      pop    rbx
  400500:       5d                      pop    rbp
  400501:       41 5c                   pop    r12
  400503:       41 5d                   pop    r13
  400505:       c3                      ret

gcc-4.7.3 -Os Meclisi (0.822 saniye içinde yürütür):

00000000004004fa <_ZL3addRKiS0_.isra.0>:
  4004fa:       8d 04 37                lea    eax,[rdi rsi*1]
  4004fd:       c3                      ret

00000000004004fe <_ZL4workii>:
  4004fe:       41 55                   push   r13
  400500:       41 89 f5                mov    r13d,esi
  400503:       41 54                   push   r12
  400505:       41 89 fc                mov    r12d,edi
  400508:       55                      push   rbp
  400509:       bd 00 c2 eb 0b          mov    ebp,0xbebc200
  40050e:       53                      push   rbx
  40050f:       31 db                   xor    ebx,ebx
  400511:       41 8d 74 1d 00          lea    esi,[r13 rbx*1 0x0]
  400516:       41 8d 3c 1c             lea    edi,[r12 rbx*1]
  40051a:       e8 db ff ff ff          call   4004fa <_ZL3addRKiS0_.isra.0>
  40051f:       01 c3                   add    ebx,eax
  400521:       ff cd                   dec    ebp
  400523:       75 ec                   jne    400511 <_ZL4workii 0x13>
  400525:       89 d8                   mov    eax,ebx
  400527:       5b                      pop    rbx
  400528:       5d                      pop    rbp
  400529:       41 5c                   pop    r12
  40052b:       41 5d                   pop    r13
  40052d:       c3                      ret

gcc-4.8.1 -Os (0.994 saniye içinde çalıştırır) montaj:

00000000004004fd <_ZL3addRKiS0_.isra.0>:
  4004fd:       8d 04 37                lea    eax,[rdi rsi*1]
  400500:       c3                      ret

0000000000400501 <_ZL4workii>:
  400501:       41 55                   push   r13
  400503:       41 89 f5                mov    r13d,esi
  400506:       41 54                   push   r12
  400508:       41 89 fc                mov    r12d,edi
  40050b:       55                      push   rbp
  40050c:       bd 00 c2 eb 0b          mov    ebp,0xbebc200
  400511:       53                      push   rbx
  400512:       31 db                   xor    ebx,ebx
  400514:       41 8d 74 1d 00          lea    esi,[r13 rbx*1 0x0]
  400519:       41 8d 3c 1c             lea    edi,[r12 rbx*1]
  40051d:       e8 db ff ff ff          call   4004fd <_ZL3addRKiS0_.isra.0>
  400522:       01 c3                   add    ebx,eax
  400524:       ff cd                   dec    ebp
  400526:       75 ec                   jne    400514 <_ZL4workii 0x13>
  400528:       89 d8                   mov    eax,ebx
  40052a:       5b                      pop    rbx
  40052b:       5d                      pop    rbp
  40052c:       41 5c                   pop    r12
  40052e:       41 5d                   pop    r13
  400530:       c3                      ret

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Google Россия

    Google Ро

    9 Temmuz 2007
  • Nightmare2005

    Nightmare200

    14 Ocak 2007
  • The Bad Tutorials

    The Bad Tuto

    6 EKİM 2009