Saya saat ini pada tahap desain arsitektur berbasis komponen di C ++.
Desain saya saat ini mencakup penggunaan fitur-fitur seperti:
std::vector
sstd::shared_ptr
s untuk memegang komponenstd::dynamic_pointer_cast
std::unordered_map<std::string,[yada]>
Komponen akan mewakili data dan logika berbagai item yang diperlukan dalam perangkat lunak seperti game, seperti Grafik, Fisika, AI, Audio, dll.
Saya telah membaca di semua tempat bahwa kesalahan cache sulit pada kinerja, jadi saya menjalankan beberapa tes, yang membuat saya percaya bahwa, memang, itu dapat memperlambat aplikasi.
Saya belum dapat menguji fitur bahasa yang disebutkan di atas, tetapi dikatakan di banyak tempat bahwa ini cenderung menghabiskan banyak biaya dan harus dihindari jika mungkin.
Karena saya pada tahap desain arsitektur, dan ini akan dimasukkan dalam inti desain, haruskah saya mencoba mencari cara untuk menghindarinya sekarang, karena akan sangat sulit untuk mengubahnya nanti jika ada kinerja masalah?
Atau saya hanya terjebak melakukan optimasi prematur?
sumber
the answer to this question is almost always a resounding "YES !!"
. Saya masih merasa bahwa itu lebih baik untuk membuatnya bekerja pertama & mengoptimalkan nanti, tetapi YMMV, semua orang memiliki pendapatnya, yang semuanya valid, dan hanya OP yang benar-benar dapat menjawab pertanyaannya sendiri - subyektif.Jawaban:
Tanpa membaca apa pun kecuali judulnya: Ya.
Setelah membaca teks: Ya. Meskipun adalah benar bahwa peta dan berbagi pointer dll tidak melakukan cache-bijaksana dengan baik, Anda pasti akan menemukan bahwa apa yang ingin Anda menggunakannya untuk - sejauh yang saya mengerti - tidak hambatan dan tidak akan diadakan di atau menggunakan cache secara efisien terlepas dari struktur data.
Tulis perangkat lunak untuk menghindari kesalahan paling bodoh, lalu uji, lalu temukan kemacetan, lalu optimalkan!
Fwiw: https://xkcd.com/1691/
sumber
Saya tidak terbiasa dengan C ++, tetapi secara umum tergantung.
Anda tidak perlu mengoptimalkan secara prematur algoritme terisolasi di mana Anda dapat dengan mudah mengoptimalkannya ketika sampai pada hal itu.
Namun Anda perlu mendapatkan desain keseluruhan aplikasi untuk mencapai indikator kinerja utama yang diinginkan.
Misalnya jika Anda perlu mendesain aplikasi untuk melayani jutaan permintaan per detik, Anda perlu memikirkan skalabilitas aplikasi saat mendesainnya, daripada membuat aplikasi berfungsi.
sumber
Jika Anda harus bertanya, maka ya. Optimalisasi prematur berarti optimisasi sebelum Anda yakin ada masalah kinerja yang signifikan.
sumber
ECS? Saya benar-benar akan menyarankan bahwa mungkin tidak prematur jika demikian untuk menaruh banyak pemikiran ke sisi berorientasi data dari desain dan benchmark repetisi yang berbeda karena dapat berdampak pada desain antarmuka Anda , dan yang terakhir sangat mahal untuk berubah di akhir permainan. ECS juga hanya menuntut banyak pekerjaan dan pemikiran di muka dan saya pikir layak menggunakan sebagian dari waktu itu untuk memastikan itu tidak akan memberi Anda kesedihan kinerja tingkat desain lebih jauh di bawah garis mengingat bagaimana itu akan menjadi jantung dari hati Anda seluruh mesin freaking. Bagian ini memelototi saya:
Bahkan dengan optimasi string kecil, Anda memiliki wadah berukuran variabel (string) di dalam wadah berukuran variabel lain (unordered_maps). Bahkan, optimasi string kecil sebenarnya bisa sama berbahayanya dengan membantu dalam kasus ini jika tabel Anda sangat jarang, karena optimasi string kecil akan menyiratkan bahwa setiap indeks tabel hash yang tidak digunakan masih akan menggunakan lebih banyak memori untuk optimasi SS (
sizeof(string)
akan menjadi jauh lebih besar) ke titik di mana total memori overhead tabel hash Anda mungkin lebih mahal daripada apa pun yang Anda simpan di dalamnya, terutama jika itu adalah komponen sederhana seperti komponen posisi, di samping menimbulkan lebih banyak cache yang hilang dengan langkah besar untuk mendapatkan dari satu entri di tabel hash ke yang berikutnya.Saya mengasumsikan string adalah semacam kunci, seperti ID komponen. Jika demikian, ini sudah membuat segalanya lebih murah secara dramatis:
... jika Anda menginginkan manfaat memiliki nama yang mudah digunakan yang dapat digunakan skrip, misalnya, string yang diinternir dapat memberi Anda yang terbaik dari kedua dunia di sini.
Yang mengatakan, jika Anda bisa memetakan string ke kisaran yang cukup rendah dari indeks yang digunakan secara padat, maka Anda mungkin bisa melakukan ini:
Alasan saya tidak menganggap ini terlalu dini adalah karena, sekali lagi, ini dapat berdampak pada desain antarmuka Anda. Maksud dari DOD seharusnya bukan untuk mencoba untuk datang dengan representasi data yang paling efisien yang dapat dibayangkan dalam sekali jalan IMO (yang umumnya harus dicapai secara iteratif sesuai kebutuhan), tetapi untuk memikirkannya cukup untuk merancang antarmuka di atas untuk bekerja dengan itu data yang membuat Anda cukup ruang bernapas untuk profil dan mengoptimalkan tanpa perubahan desain cascading.
Sebagai contoh naif, perangkat lunak pemrosesan video yang memasangkan semua kodenya dengan ini:
Tidak akan jauh tanpa berpotensi menulis ulang epik, karena gagasan mengabstraksi pada tingkat piksel tunggal sudah sangat tidak efisien (
vptr
itu sendiri akan sering menghabiskan lebih banyak memori daripada seluruh piksel) dibandingkan dengan mengabstraksi pada tingkat gambar (yang akan sering mewakili jutaan piksel). Jadi taruh pemikiran yang cukup dalam representasi data Anda terlebih dahulu sehingga Anda tidak harus menghadapi skenario mimpi buruk seperti itu, dan idealnya tidak lebih, tapi di sini saya pikir ada baiknya memikirkan hal-hal ini di muka karena Anda tidak ingin membangun sebuah mesin rumit di sekitar ECS Anda dan temukan bahwa ECS itu sendiri adalah penghambat dalam cara yang mengharuskan Anda mengubah hal-hal pada tingkat desain.Mengenai kesalahan cache ECS, menurut saya pengembang sering berusaha terlalu keras untuk membuat cache ECS mereka ramah. Itu mulai menghasilkan sedikit bang untuk uang untuk mencoba mengakses semua komponen Anda dengan cara yang berdekatan, dan sering akan menyiratkan menyalin dan mengacak data di semua tempat. Biasanya cukup baik untuk, katakanlah, hanya indeks komponen sortir radix sebelum mengaksesnya sehingga Anda mengaksesnya dengan cara di mana Anda setidaknya tidak memuat wilayah memori ke dalam garis cache, hanya untuk mengusirnya, dan kemudian memuatnya, lalu memuat semuanya lagi dalam loop yang sama hanya untuk mengakses bagian yang berbeda dari garis cache yang sama. Dan ECS tidak harus memberikan efisiensi luar biasa di seluruh papan. Ini tidak seperti manfaat sistem input dari itu sebanyak fisika atau sistem rendering, jadi saya sarankan bertujuan untuk "baik" efisiensi secara menyeluruh dan "luar biasa" hanya di tempat-tempat di mana Anda benar-benar membutuhkannya. Yang mengatakan, penggunaan
unordered_map
dan distring
sini cukup mudah untuk dihindari.sumber