2013-07-16 29 views
14

dikkate alındığında aşağıdaki test programları: O0 onları hazırlayarakNeden dereferencing programımı daha hızlı hale getiriyor?

Loop value on the stack

int main(void) { 
    int iterations = 1000000000; 

    while (iterations > 0) 
     -- iterations; 
} 

Loop value on the stack (dereferenced)

int main(void) { 
    int iterations = 1000000000; 
    int * p = & iterations; 

    while (* p > 0) 
     -- * p; 
} 

Loop value on the heap

#include <stdlib.h> 

int main(void) { 
    int * p = malloc(sizeof(int)); 
    * p = 1000000000; 

    while (*p > 0) 
     -- * p; 
} 

, Ben olsun o Aşağıdaki yürütme süreleri:

case1.c 
real 0m2.698s 
user 0m2.690s 
sys  0m0.003s 

case2.c 
real 0m2.574s 
user 0m2.567s 
sys  0m0.000s 

case3.c 
real 0m2.566s 
user 0m2.560s 
sys  0m0.000s 

[değiştir] 10 yürütmeler ortalama aşağıdadır:

case1.c 
2.70364 

case2.c 
2.57091 

case3.c 
2.57000 

Neden en basit gibi görünüyor ilk test durumunda, birlikte yürütme zamanı büyük?

Şu anki mimarim x86 sanal makinesidir (Archlinux). Bu sonuçları hem gcc (4.8.0) hem de clang (3.3) ile elde ediyorum.

[değiştir 1] Oluşturulan derleyici kodları hemen hemen aynıdır, ancak ikinci ve üçüncü olanlar ilkinden daha fazla yönergeye sahip olmaları dışında.

[değiştir 2] Bu performanslar tekrarlanabilir (sistemimde). Her uygulama aynı büyüklük derecesine sahip olacaktır.

[edit 3] Optimize edilmemiş bir programın performanslarını umursamıyorum, ancak neden daha yavaş olacağını anlamıyorum ve merak ediyorum.

+9

Oluşturulan koda bakmayı denediniz mi? Niçin düzenlenmemiş kodun performansını önemsiyorsunuz? –

+8

Hae onları farklı bir düzende çalıştırmayı denediniz mi? Bu tek çekim süreleri mi, yoksa ortalama sayısı önemli sayıda mı? – EJP

+0

@CarlNorum Neredeyse aynı üretilen kod, son iki örnekte daha fazla talimat (hareket ve yükleme) olması dışında. Performansları umursamıyorum, ama hala merak ediyorum :) –

cevap

6

Bunun bir nedeni olduğunu tahmin etmemizin sebebi buysa ve bazı özellikleri vermediyseniz (ki hangi amaçla kullandığınız gibi) söylemek zor.

Vaka 1:

L3: 
    sub DWORD PTR [esp+12], 1 
L2: 
    cmp DWORD PTR [esp+12], 0 
    jg L3 

Örneği 2:

L3: 
    mov eax, DWORD PTR [esp+12] 
    mov eax, DWORD PTR [eax] 
    lea edx, [eax-1] 
    mov eax, DWORD PTR [esp+12] 
    mov DWORD PTR [eax], edx 
L2: 
    mov eax, DWORD PTR [esp+12] 
    mov eax, DWORD PTR [eax] 
    test eax, eax 
    jg L3 

Bir büyük fark Fakat benim x86 hedefle optimziations olmadan derleme yaparken görüyorum iterations değişken decrementign için aşağıdaki dizileri Durum 1'de gördüğünüzde, L3 adresindeki yönerge, bellek konumunu okur ve yazar. Hemen yazılan aynı hafıza yerini okuyan bir talimatla takip edilir. Bu tip bir komut dizisi (bir sonraki talimatta hemen yazılan aynı hafıza konumu) çoğu zaman modern CPU'larda bir çeşit boru hattının durmasına neden olur. Sen yazma aynı yerde bir okuma ve hemen ardından dikkat edeceğiz

Yine

durumda 2. bulunmaz - Bu yanıt bilinçli spekülasyon biraz.

+0

Sizinkini test ettiniz, çünkü asm kodunuz OP'nin – aaronman

+0

OP'lerinden farklıdır, Clang'ınki gibi görünüyor. Aynı şeyi gcc 4.8 ile aldım. – snf

+2

Şüphesiz bu sorunun cevabı bu soruya cevap verecek kadar ilginçtir. – aaronman

İlgili konular