2013-01-06 3 views
5

Burada yürütme zamanında ++ c benim macbook air sonucu. Mikrosaniye içinde "for" öncesi ve sonrasında zaman alır.
fark 732 microsseconds 0,000732 saniye Neden benim arduino'm MacBook Air'ımdan 0 ila 1 milyar daha hızlı hesaplıyor? 2,692 saniye <img src="https://i.stack.imgur.com/rkYNr.jpg" alt=""></p> <p>İşte benim arduino kod :

+1

Peki, çalıştırdığınız C++ kodunuz çalışan tek işlem değil. – enginefree

+0

'time = micros()' nasıl çalışır? İlkini saklamak ve sonra ikincisini ilkinden çıkarmak zorunda değil misin? Aksi halde, sadece orada okuduğunuz rastgele bir sayı. Arduino'da koşmak ne kadar sürdü? Bin bir, iki bin iki ... –

+0

Arduino açıldığından beri geçen mikrosaniyelik değerleri okur, bu nedenle 792-60 kodu –

cevap

11

olduğunu Öncelikle, yazdığı kod çok basit wich olduğunu. Bu kod için derleme sonucu derleyici ve derleyici ayarlarına bağlı olarak değişecektir. Düzgün olarak yapılandırılmış bir optimizasyon derleyici, genellikle herhangi bir döngü olmaksızın n son değerinin düz bir atamasını derler. Ya da tamamen n'u tamamen ortadan kaldırabilir. Bu durumda gerçekten ölçtüğünüz şey sadece “boşluk” dır: bir programın [neredeyse] hiçbir şeyi yapmayan bir başlangıç ​​ve bitiş zamanı.

İkinci olarak, kullandığınız ölçüm yöntemleri, kodun iki sürümü arasında tamamen farklı görünüyor. İlk durumda sistem seviyesinde bir şey kullanıyor gibi görünüyorsunuz, bu muhtemelen büyük olasılıkla çeşitli başlangıç ​​ve son taksit içine sarma sürelerini içerdiği anlamına gelir. İkinci durumda, ölçümleri asıl kod içine gömdünüz, sadece çevrimin ölçüldüğünden emin olursunuz (bu, yine derleyici tarafından muhtemelen ortadan kaldırılır). Başka bir deyişle, muhtemelen bulunmayan bir şeyi zamanlamak için tutarsız yöntemler kullanıyorsunuzdur. Elde ettiğin sonuçlar, kodun performansıyla çok az alakalı ya da büyük olasılıkla, hiçbir anlam ifade etmiyor.

+0

Haklısınız, iki kodda aynı ölçüm yöntemiyle çalışacağım, ama bak: Sayıyı 4.000.000.000 olarak değiştirdim ve 11.521 saniye sürdü. Diyelim ki 2 saniye sadece kütüphaneleri başlatmak içindir. O kadar çok fark olur, sence de öyle değil mi? Teşekkürler! :) –

+0

@Lucas Zanella: Bazı platformdaki kod yineleme sayısına doğrusal olarak duyarlıysa, bu çevrimin ortadan kaldırılmadığı anlamına gelir. Derleyici yeterince akıllı değildi ya da derleme ayarları optimizasyonları önledi. Diğer platformdaki derleyicinin aynı şekilde davrandığından emin misin? Diğer platform aynı zamanda iterasyonların sayısına da doğrusal mı duyarlı? – AnT

+0

Bunu deneyeceğim. Teşekkürler! –

3

ilgili teknik açıklama AndreyT tarafından verilen, ama burada doğru yönde seyir yardımcı hızlı ve kirli tahmindir edilmiştir:

aslında 1 milyar (1E9) yönetilen Arduino varsayalım kabaca bir milisaniye (artırır 730 mikrosaniye) ve ek artışı dikkate almayın ve döngü sayacı yanı sıra atlama talimatı için kontrol, bu Arduino en az 1e12 Hz, 1000 GHz olan bir artışlarla artışları işlemek anlamına gelir (bu bir "CPU frekansına" eşdeğer olmayan, ancak başka herhangi bir bilginin yokluğunda oldukça iyi bir tahmin edicidir, işlenmiş artış talimatlarının sıklığı için tahmin. Olası olmayan. Bu nedenle, arduino derleyicinizin tüm döngüyü basitçe ortadan kaldırdığını varsaymak güvenlidir.

(MacBook'unuz için aynı tahmin, en az (1e9/2.7) Hz frekansı verir, kabaca 370Mhz'lik artışlar - OS overhead'inin çarpanlarına eklenmesi, loop'un ekstra artış, atlama ve karşılaştırmaya ihtiyaç duyması gerçeği Bu, işlemci freq'una oldukça yakın bir şekilde çalışır, bu yüzden Mac programınız için derleyicinizin aslında döngüleri koruduğunu tahmin ediyorum.)

13

Derleme gibi görünen MSVC kodunuzu hata ayıklama modunda nasıl derlediğimize bakalım o ...

unsigned int max = 1000000000L; 
    011643BE mov   dword ptr [max],3B9ACA00h 
for (unsigned int i=0; i<max; i++) 
    011643C5 mov   dword ptr [ebp-14h],0 
    011643CC jmp   main+37h (011643D7h) 
    011643CE mov   eax,dword ptr [ebp-14h] 
    011643D1 add   eax,1 
    011643D4 mov   dword ptr [ebp-14h],eax 
    011643D7 mov   eax,dword ptr [ebp-14h] 
    011643DA cmp   eax,dword ptr [max] 
for (unsigned int i=0; i<max; i++) 
    011643DD jae   main+4Eh (011643EEh) 
{ 
    n++; 
    011643DF mov   eax,dword ptr ds:[0116F218h] 
    011643E4 add   eax,1 
    011643E7 mov   dword ptr ds:[0116F218h],eax 
} 
011643EC jmp   main+2Eh (011643CEh) 

Tamam, şimdi ... sürüm modunda görebilirler

unsigned int max = 1000000000L; 
for (unsigned int i=0; i<max; i++) 
    00FC1270 mov   eax,dword ptr ds:[00FC4430h] 
{ 
    n++; 
} 
std::cout << n; 
    00FC1275 mov   ecx,dword ptr ds:[0FC3030h] 
    00FC127B add   eax,3B9ACA00h 
    00FC1280 push  eax 
    00FC1281 mov   dword ptr ds:[00FC4430h],eax 
    00FC1286 call  dword ptr ds:[0FC3038h] 

Fark dikkat edin? Serbest bırakma modu döngüsünü optimize ederek tamamen 'a sahiptir.

Şimdi, vites değiştirmeye ve Arduino'nun bunu nasıl yaptıklarına bakalım. Bazı AVR asm için hazır olun ...

for(i=0; i<1000000000; i++) 
{ 
n++; 
} 
Serial.println(n); 
    d8: c8 01   movw r24, r16 
    da: 40 e0   ldi r20, 0x00 ; 0 
    dc: 5a ec   ldi r21, 0xCA ; 202 
    de: 6a e9   ldi r22, 0x9A ; 154 
    e0: 7b e3   ldi r23, 0x3B ; 59 
    e2: 2a e0   ldi r18, 0x0A ; 10 
    e4: 30 e0   ldi r19, 0x00 ; 0 
    e6: 0e 94 c4 04  call 0x988 ; 0x988 <_ZN5Print7printlnEli> 

Whoa! Döngüyü de optimize etti! Derleyici, akıllı küçük bir tutam, doğuştan?!?!

... Ve bunun hakkında düşündüğünüzde, bir döngü uzunluğunu gerçekleştirmek için .0007 saniye biraz hızlı değil mi? Bu sadece 43 saat döngü için yeterli zaman - Serial.println()'u aramak için yeterli.

İlgili konular