Float, double atau keduanya untuk kelas Vector 2D?

11

Saat ini saya sedang menulis mesin game 2D berbasis lintas platform kecil OpenGL untuk studio kami. Ketika saya meneliti kelas vektor 2D mana yang akan digunakan, saya menemukan tiga paradigma desain yang berbeda:

  • Float & Call-by-value, seperti dalam artikel Gamasutra ini . Tampaknya cepat tetapi menawarkan sedikit presisi (lihat juga Thread ini ). Pro: Cepat, portabel, dan kompatibel dengan sebagian besar perpustakaan.

  • Referensi ganda & Panggil-oleh-. Jika saya memahami artikel di atas dengan benar, saya juga bisa menggunakan 2 variabel presisi ganda daripada 4 angka float. Menurut utas di atas, dobel masih lebih lambat daripada mengambang.

  • Templat untuk dobel dan mengapung: Buku yang sangat populer " Arsitektur Mesin Game " menggunakan templat untuk memungkinkan untuk menggunakan float dan dobel sesuai kebutuhan. Kelemahan yang jelas adalah kode mengasapi. Juga, saya ragu bahwa kode dapat dioptimalkan tanpa pada dasarnya menulis dua kelas.

Saya akan sangat menghargai untuk mengetahui solusi apa yang Anda gunakan di mesin in-house Anda dan seberapa tepat misalnya mesin game yang populer, sehingga saya dapat memutuskan solusi apa yang akan saya terapkan di mesin kami. Saat ini saya sedang berpikir tentang hanya menggunakan presisi float dan hidup dengannya.

martinpi
sumber
Lebih lambat dimana ? Anda tidak dapat berbicara tentang kecepatan jika itu tidak terkait dengan arsitektur tertentu.
o0 '.
2
@ Lo'oris: Saya tidak tahu arsitektur mana pun yang lebih cepat daripada float.
Daripada menulis kelas vektor Anda sendiri, pertimbangkan untuk menggunakan Sony ( bulletphysics.org/Bullet/phpBB3/… ). Ini adalah "library" drop-in header-only yang mudah yang telah dioptimalkan secara mikro, dan semua pustaka vektor pada dasarnya adalah antarmuka eksternal yang sama pula.
@ Joey: 2 ganda, bukan 4 pelampung?
o0 '.
@ Lo'oris: Pertanyaannya sedikit aneh, saya tidak tahu apakah si penanya bingung atau hanya Anda - Anda menggunakan dua ganda "daripada" empat mengapung ketika berhadapan dengan SIMD, karena register lebar 128 bit. Anda masih perlu memproses jumlah angka yang sama, dan Anda melakukannya dengan kecepatan setengah.

Jawaban:

9

Saya selalu menggunakan float kecuali saya punya alasan untuk menggunakan double, sama seperti saya menggunakan int kecuali saya punya alasan untuk menggunakan int64_t.

Mengapung tidak memiliki masalah melakukan bilangan bulat aritmatika hingga 2 24 , yang merupakan hal yang ditakuti kebanyakan orang (sebagian besar secara tidak rasional). Doubles tidak memecahkan masalah nilai-nilai umum yang tidak terwakili dengan tepat - apakah Anda mendapatkan 0,10000001 atau 0,10000000000000001, Anda masih harus memastikan kode Anda menganggapnya "sama" dengan 0,09999999.

Doubles lebih lambat di setiap platform Anda akan peduli menulis game, mengambil bandwidth memori dua kali lipat, dan memiliki lebih sedikit instruksi CPU khusus yang tersedia.

Pelampung presisi tunggal tetap menjadi standar untuk antarmuka grafis perangkat keras, baik di sisi C / C ++ maupun di dalam shader.

Anda mungkin memerlukan vektor ganda di beberapa titik, tetapi harus digunakan saat dibutuhkan, bukan secara default.

Mengenai templating - Anda benar, untuk kinerja maksimum, Anda tetap ingin mengkhususkan template secara manual. Selain itu, saya menjalankan beberapa tes untuk beberapa kode templated selama akhir pekan (membuat IntRect dan FloatRect 4-ple), dan menemukan bahwa versi templated membutuhkan waktu sekitar 20x lebih lama untuk dikompilasi daripada hanya mengulang kode, yang berjumlah sekitar 15 baris . Pengulangan menyebalkan, tetapi menunggu kompilasi lebih menyebalkan - dan sepertinya saya tidak akan membutuhkan StringRect atau FooRect.


sumber
" Ganda lebih lambat di setiap platform [...] " - Kutipan diperlukan.
zenith
3

Kerangka kerja Microsoft XNA memiliki kelas Vector2 yang menggunakan pelampung. Ini akan menjadi alasan pribadi terbesar saya untuk mengapung, karena saya percaya kebijaksanaan dan pengalaman tim XNA jauh lebih besar daripada milik saya.

Saya merasa agak menarik untuk membaca jawaban dalam pertanyaan Stack Overflow ini: "Float vs Double Performance" . Ada juga utas gamedev.net dengan beberapa diskusi tentang kinerja ganda dalam GPU. Saya pikir aman untuk mengasumsikan bahwa ganda lebih lambat daripada float, setidaknya di banyak GPU, dan saya pribadi selalu menggunakan fungsi OpenGL float di atas rekan ganda mereka. Ini mungkin tidak berlaku saat ini, tetapi jika Anda menganggap bahwa tidak semua orang yang menjalankan game Anda memiliki GPU terbaru dengan dukungan ganda asli, saya pikir ini adalah alasan yang cukup untuk menggunakan pelampung dan mendapatkan sedikit kinerja ekstra.

Ricket
sumber
1
Dari pertanyaan SO: "Pada prosesor x86, setidaknya, float dan double masing-masing akan dikonversi ke 10-byte real oleh FPU untuk diproses." Meskipun ini benar, ia mengabaikan instruksi SIMD dan memori tambahan (= koherensi cache yang lebih buruk, bandwidth memori lebih banyak) persyaratan ganda, keduanya terus membuatnya lebih lambat daripada mengambang dalam tes dunia nyata.
Saya pikir ada tangkapan. Anda harus mengomentari jawaban SO itu, saya akan membatalkannya.
Ricket
Sudah ada di sana sebagai komentar.
1
Karena Anda membawa XNA, saya mungkin juga menunjukkan bahwa Direct2D juga menggunakan pelampung presisi tunggal.
Mike Strobel
Dan untuk kelengkapannya, OpenGL memiliki versi float dan double dari metodenya, jadi netral dalam hal ini.
Ricket