Zamanından önce optimizasyon yapıyor muyum?


9

Şu anda C ++ 'da bileşen tabanlı bir mimarinin tasarım aşamasındayım.

Mevcut tasarımım aşağıdaki gibi özelliklerin kullanımını içerir:

  • std::vectorve s std::shared_ptrbileşenlerini tutmak için s
  • std::dynamic_pointer_cast
  • std::unordered_map<std::string,[yada]>

Bileşenler, Grafik, Fizik, AI, Ses vb. Gibi oyun benzeri bir yazılımda gerekli olan çeşitli öğelerin verilerini ve mantığını temsil eder.

Önbellek özlemlerinin performansının zor olduğu her yeri okudum, bu yüzden bazı testleri yaptım, bu da beni gerçekten bir uygulamayı yavaşlatabileceğine inandırdı.

Yukarıda belirtilen dil özelliklerini test edemedim, ancak birçok yerde bunların çok pahalıya mal olduğu ve mümkünse kaçınılması gerektiği söyleniyor.

Mimarinin tasarım aşamasında olduğum için ve bunlar tasarımın çekirdeğinde yer alacağından, şimdi bunlardan kaçınmanın yollarını bulmaya çalışmalıyım, çünkü performans varsa daha sonra değiştirmek çok zor olacak sorunlar?

Yoksa erken optimizasyona mı yakalandım?


3
Performans sorunlarına bakılmaksızın daha sonra değiştirmeyi zorlaştıran bir tasarıma yerleşmekte çok isteksiz olurum. Mümkünse bundan kaçının. Hem esnek hem de hızlı birçok tasarım var.
candied_orange

1
Ayrıntıları bile bilmeden, bu sorunun cevabı neredeyse her zaman yankılanan bir "EVET !!" dir.
Mawg, Monica'yı

2
@Mawg "... Yine de bu kritik% 3'teki fırsatlarımızı kaçırmamalıyız." Bu tasarımın çekirdeği olduğundan, bu% 3 üzerinde çalışıp çalışmadığımı nasıl bilebilirim?
Vaillancourt

1
Bir excelelnt puan, Alexandre (+1) ve evet, biliyorum ki neredeyse hiç bahsedilmeyecek olan teklifin son yarısında :-) Ama ondan önce yorumuma geri dönmek için (acecpted cevaba yansır) , the answer to this question is almost always a resounding "YES !!". İlk önce çalışıp daha sonra optimize etmenin daha iyi olduğunu düşünüyorum, ancak YMMV, herkesin kendi fikri var, hepsi geçerli ve sadece OP kendi - öznel - sorusunu gerçekten cevaplayabilir.
Mawg, Monica

1
@AlexandreVaillancourt Knuth gazetesini okumaya devam edin (PDF, alıntı, PDF okuyucuda 268, sayfa 8 etiketli sayfanın sağ tarafından gelir). “... eleştirel koda dikkatlice bakmak akıllıca olacaktır; ancak bu kod tanımlandıktan sonra . Bir programın hangi bölümlerinin gerçekten kritik olduğu konusunda a priori yargılarda bulunmak genellikle bir hatadır. ölçüm araçlarını kullanan programcılar sezgisel tahminlerinin başarısız olmasıydı. " (Vurgu onun)
8bittree

Yanıtlar:


26

Başlık dışında hiçbir şey okumadan: Evet.

Metni okuduktan sonra: Evet. Her ne kadar haritaların ve paylaşılan işaretçilerin vb. Önbellek açısından iyi performans göstermedikleri doğru olsa da , kesinlikle onları kullanmak istediğiniz şeyin - anladığım kadarıyla - darboğaz olmadığını ve tutulmayacağını veya veri yapısından bağımsız olarak önbelleği verimli kullanın.

En aptal hatalardan kaçınarak yazılımı yazın, sonra test edin, ardından darboğazları bulun, sonra optimize edin!

Fwiw: https://xkcd.com/1691/


3
Kabul. Önce doğru çalışmasını sağlayın, çünkü çalışmanın ne kadar hızlı başarısız olduğu önemli değildir. Ve her zaman en etkili optimizasyonların kodu değiştirmeyi, farklı ve daha verimli bir algoritma bulmayı içerdiğini unutmayın.
Todd Knarr

10
İlk satırın doğru olmadığını belirtmek isterim çünkü optimizasyon her zaman prematürdür, ancak optimizasyon sadece ihtiyacınız olduğunu biliyorsanız erken değildir, bu durumda bunu sormazsınız. Dolayısıyla, ilk satır sadece doğrudur, çünkü optimizasyonun erken olup olmadığı hakkında bir soru sormanız, optimizasyona ihtiyacınız olduğundan emin olmadığınız anlamına gelir, ki bu tanımı gereği erken yapar. Uf.
Jörg W Mittag

@ JörgWMittag: kabul etti.
steffen

3

Ben C ++ aşina değilim, ama genel olarak bağlıdır.

Bu söz konusu olduğunda kolayca optimize edebileceğiniz yalıtılmış algoritmaları zamanından önce optimize etmeniz gerekmez.

Ancak, istenen temel performans göstergelerini elde etmek için uygulamanın genel tasarımını almanız gerekir.

Örneğin, saniyede milyonlarca istek sunmak için bir uygulama tasarlamanız gerekiyorsa, uygulamayı tasarlarken uygulamanın çalışmasını sağlamak yerine uygulamanın ölçeklenebilirliğini düşünmeniz gerekir.


3

Sormak zorundaysan, evet. Erken optimizasyon , önemli bir performans sorunu olduğundan emin olmadan önce optimizasyon anlamına gelir .


1

ECS? Aslında, tasarımın veri odaklı tarafına çok fazla düşünmenin ve farklı temsilcileri karşılaştırmanın erken olacağını düşünmeyeceğim çünkü arayüz tasarımlarınızı etkileyebilir ve ikincisi geç saatlerde değişmek çok maliyetli oyun. Ayrıca ECS sadece çok fazla çalışma gerektiriyor ve açık bir şekilde düşünüyor ve sanırım, kalbinizin altında nasıl olacağı göz önüne alındığında, size tasarım düzeyinde performans kederini daha fazla vermeyeceğinden emin olmak için o zamanın bir kısmını kullanmaya değer. tüm ucube motoru. Bu bölüm bana dik dik bakıyor:

unordered_map<string,[yada]>

Küçük dize optimizasyonlarında bile, başka bir değişken boyutlu kabın (unordered_maps) içinde değişken boyutlu bir kabınız (dizeler) vardır. Masanız çok seyrek ise küçük dize optimizasyon karma tablonun her kullanılmayan endeks hala (SS optimizasyonu için daha fazla bellek kullanacağını ima olacağından Aslında, küçük dize optimizasyonlar aslında bu durumda yardımcı gibi zararlı olarak olabilir sizeof(string)olurdu karma tablonuzun toplam bellek yükünün, içine depoladığınız her şeyden daha pahalı olabileceği noktaya, özellikle de bir konum bileşeni gibi basit bir bileşense, büyük adımda daha fazla önbellek özlemi oluşmasına ek olarak karma tablosundaki bir girişten diğerine geçmek için.

Dize bir bileşen kimliği gibi bir tür anahtar varsayalım. Öyleyse, bu zaten işleri önemli ölçüde daha ucuz hale getiriyor:

unordered_map<int,[yada]>

... komut dosyalarının kullanabileceği kullanıcı dostu adlara sahip olmanın avantajlarını istiyorsanız, örneğin, o zaman stajyer dizeler size her iki dünyanın en iyisini verebilir.

Bununla birlikte, dizeyi oldukça düşük yoğunlukta kullanılan endekslerle eşleyebiliyorsanız, bunu yapabilirsiniz:

vector<[yada]> // the index and key become one and the same

Bu prematüre düşünmememin nedeni, yine, arayüz tasarımlarınızı etkileyebileceğidir. DOD'un amacı, bir seferde IMO'da (genellikle gerektiği gibi yinelemeli olarak başarılması gerekir) akla gelebilecek en verimli veri temsillerini bulmaya çalışmak değil, bununla çalışmak için üstte arayüzler tasarlayacak kadar düşünmek olmalıdır. basamaklı tasarım değişiklikleri yapmadan profil oluşturmak ve optimize etmek için yeterli nefes alanınızı bırakan veriler.

Naif bir örnek olarak, tüm kodlarını buna karşı birleştiren bir video işleme yazılımı:

// Abstract pixel that could be concretely represented by
// RGB, BGR, RGBA, BGRA, 1-bit channels, 8-bit channels, 
// 16-bit channels, 32-bit channels, grayscale, monochrome, 
// etc. pixels.
class IPixel
{
public:
    virtual ~IPixel() {}
    ...
};

Potansiyel olarak destansı bir yeniden yazma olmadan çok uzağa gitmeyecek, çünkü tek piksel seviyesinde soyutlama fikri vptr, görüntü düzeyinde soyutlamaya kıyasla zaten oldukça verimsiz ( kendisi genellikle tüm pikselden daha fazla belleğe mal olacak). genellikle milyonlarca pikseli temsil eder). Bu nedenle, böyle bir kabus senaryosuyla yüzleşmek zorunda kalmamanız ve ideal olarak artık veri temsillerinize yeterince düşünün, ancak burada bir şey oluşturmak istemediğiniz için bu şeyleri düşünmeye değer olduğunu düşünüyorum. ECS'nizin etrafındaki karmaşık motoru ve ECS'nin kendisinin tasarım düzeyinde bir şeyleri değiştirmenizi gerektiren şekillerde darboğaz olduğunu bulun.

ECS önbellek hatalarına gelince, bence geliştiriciler genellikle ECS'yi önbellek dostu yapmak için çok uğraşıyorlar. Paranın tüm bileşenlerinize mükemmel bir şekilde bitişik bir şekilde erişmeye çalışması için çok az patlama vermeye başlar ve çoğu zaman verilerin her yerde kopyalanması ve karıştırılması anlamına gelir. Genellikle, bileşen dizinlerini erişmeden önce sıralamak için sadece yeterince iyidir, böylece en azından bir bellek bölgesini önbellek hattına yüklemeyeceğiniz bir şekilde erişirsiniz, yalnızca onu çıkarmak ve sonra yüklemek için aynı önbellek satırının farklı bir bölümüne erişmek için aynı döngü içinde tekrar tekrar. Ve bir ECS'nin tüm dünyada inanılmaz bir verimlilik sağlaması gerekmez. Bir giriş sisteminin bir fizik veya render sistemi kadar fayda sağladığı gibi değil, bu yüzden "iyi" verimlilik yönetim kurulu ve sadece gerçekten ihtiyacınız olan yerlerde "mükemmel". Yani, kullanımıunordered_mapve stringburada kaçınmak için yeterince kolay.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.