2010-11-10 10 views
12

Bu, 64 bit'lik yaklaşık bir verimlilik sorusu. Bir "int" parametresinin değerini değiştirmem gerekmediği varsayıldığında, değeri veya referansa göre iletmeliyim.C++ 64 bit int: referansa göre geçiş yapın veya değer olarak aktarın

varsayarsak 32 bit makine:

1) 32 bit int: Ben cevap olarak "değeriyle geçmesi" dir tahmin "referans olarak geçmektedir" ekstra bellek arama yükünü sahip olacak.

2) 64-bit int: I, referans ile başarılı olursa, sadece yığın 32 bit adres geçer, ama ek bir bellek arama gerekir. Hangisi daha iyi (referans veya değer)?

Makine 64 bitse ne olur? Bir kayıt değeri olarak geçirilebilir çünkü

Saygılarımızla, Hatta değerine göre 64 bit makine geçişte

JP

+3

"Verimlilik" :(KISS, diğer tüm kanlı tamsayıları nasıl geçtiğini iletin –

+0

Derleyici muhtemelen her neyse bunu iyimser olacak. –

+0

@pst: +1 komik yorum için çok güldüm adamım –

cevap

10

Değere göre geçiş - kesinlikle. Sistem 64-bit ise, 64-bit kelimeyi son derece hızlı kopyalar.

8

, (bazı çok az istisna dışında) daha iyidir.

+7

64 bitlik bir makinede * özellikle * diyebilirim. – cHao

+0

Yani 64-bit int "by value" iletmek, hem 32-bit hem de 64-bit makinelerde 64-bit int "atıfta bulunarak" (64-bit makinelerde bile), daha verimli mi? –

+0

İstisnaları bilmek istemiyorum (bu, tartışmanın kapsamı dışındadır) –

4

Argüman hatırı için, farklılıkları gideren önemsiz iyimser durumlarını göz ardı edin. Ayrıca Microsoft'un Intel 64 bit çağrı kurallarını (Linux ABI'dan farklı olan) kullandığınızı varsayalım, daha sonra bu değerleri iletmek için 4 64-bit yazmaçlarınız var. Bu açıkça daha iyi.

32-bit bir uygulama için, değere ve düz bir şekilde yığının üstüne giderler. Referansa göre, bir kayıtçiye bir işaretçi konabilir (tekrar, bu tür birkaç kayıt kullanımının yığına başvurmadan önce izin verilir). Bu const referans değeri ve f2 (101) tarafından g ++ -O3 -S bir çıkış, çağrı f1 (99) 'de olabilir:

void f1(int64_t); 
void f2(const int64_t&); 

int main() 
{ 
    f1(99); 
    f2(101); 
} 

... 

    pushl 0 
    pushl $99 
    call _Z2f1x // by value - pushed two halves to stack 

    leal -8(%ebp), %eax 
    movl %eax, (%esp) 
    movl $101, -8(%ebp) 
    movl $0, -4(%ebp) 
    call _Z2f2RKx // by const& - ugly isn't it!?! 

adlandırılan fonksiyonu daha sonra (eğer varsa, ilk kullanımdan önce almak gerekir). Çağrılan işlev, yazmaçlarda okunan değerleri önbelleğe almakta serbesttir, bu yüzden sadece bir kez gerekir. Yığın yaklaşımı ile, değer istekte yeniden okunabilir, bu nedenle kayıt için bu değer için ayrılmaya gerek yoktur. İşaretçi yaklaşımıyla, işaretçinin veya 64 bitlik değerin, başka bir iş için anlık olarak geçici olarak kaldırılması gerektiğinde, daha öngörülebilir bir yerde (örneğin, itti veya daha az kullanışlı bir kayıt) kaydedilmesi gerekebilir. int parametresi daha sonra tekrar gereklidir. Her şey, hangisinin daha hızlı olduğunu tahmin etmek zordur - CPU/register-use/optimiser/etc bağımlı olabilir ve denemeye değmez.

PST tavsiyesine A düğüm ...

Eğer her kanlı tamsayı geçirme şekli "verimlilik" :(KISS geçmek -..

pst

... gerçi bazen şablonuna KISS uygulamak Parametreler ve bazı yapıları T & yapsa bile, bazı kayıtlar bile sığabilir.

7

Onları boost::call_traits<int64_t>::param_type olarak geçirin.Bu şablon desteklenen platformlarda herhangi bir tür geçirme için en iyi uygulamaları yakalar. 32 ve 64 bit platformlarda, ancak aynı kodu her yerde kullanabilirsiniz. Henüz kesin türünü bilmediğiniz diğer şablonları da kullanabilirsiniz.

+10

+1 bu tamsayıların geçişini optimize etmekten endişe duyan insanlar için en iyi cezadır, o kadar çok yazmalıdırlar. –

+0

Belki de 64 bit veri için bu fark göz ardı edilebilir. Bununla birlikte, sorunun ruhu faydalıdır. 12 baytlık bir yapım varsa ne olur? 16 bayt? Hans Passant'ın yorumu teknik olarak doğrulanmamış veya test edilemese de, en azından doğru yönde bir gösterge vermektedir. –

+0

Elbette, 64 bit için endişelenmenize gerek olmadığını bilmek yararlı :). (Bizim kodumuzda bu tür fonksiyonlar 100'lerce Milyon kere çağrılacak ve genel olarak saatlerce çalışacak olsa da. Bu durumda, "en iyi" uygulamaları takip etmek her zaman iyidir.) –

1

kullanın biraz sağduyu,

  1. nesne karmaşık kopya kurucu gerektiriyorsa

    , bu başvuruyla geçirme değer demektir (söyleyerek - Boost nesnelerin oldukça çok şekilde tasarlanmıştır geçti-by- sadece iç uygulama oldukça önemsiz olduğundan, referans yerine değer var. Gerçekten hiç çalışmadığım tek bir tane var, std::string, her zaman bunu referans olarak geçiriyorum ...

  2. Bu değeri değiştirmek istediğinizde içeri aktarıldı, bir referans kullanın

  3. Else, PASS-BY-VALUE!

İşlevlerin bağımsız değişkenleri ile belirli bir performans darboğazı var mı? Else, ... denizde ing ** pi gibidir bir int geçirilen nasıl endişesi ile ... geçmesine iyi yolu olan endişesi

Optimizasyon çok fazla zaman harcamak yok

+0

Bulmacayı çözmek istiyorum: " denizde pezevenk " – weberc2