Tentang presisi floating point dan mengapa kita masih menggunakannya

38

Floating point selalu merepotkan untuk presisi di dunia besar.

Artikel ini menjelaskan di balik layar dan menawarkan alternatif yang jelas - angka titik tetap. Beberapa fakta sangat mengesankan, seperti:

"Yah, 64 bit presisi membawa Anda ke jarak terjauh Pluto dari Matahari (7,4 miliar km) dengan presisi sub-mikrometer."

Baik presisi sub-mikrometer lebih dari kebutuhan fps (untuk posisi dan bahkan kecepatan), dan itu akan memungkinkan Anda untuk membangun dunia yang sangat besar.

Pertanyaan saya adalah, mengapa kita masih menggunakan floating point jika fixed point memiliki kelebihan seperti itu? Sebagian besar rendering API dan pustaka fisika menggunakan floating point (dan menderita kerugiannya, sehingga pengembang perlu menyiasatinya).

Apakah mereka jauh lebih lambat?

Selain itu, bagaimana menurut Anda mesin planet yang scalable seperti outerra atau infinity menangani skala besar? Apakah mereka menggunakan titik tetap untuk posisi atau apakah mereka memiliki algoritma pembagian ruang?

system_is_b0rken
sumber
3
Bit "tambahan" terakhir mungkin harus menjadi pertanyaan terpisah sehingga yang utama tidak teralihkan.
Tetrad
Saya ingin mencari cara untuk memaksa titik tetap ... Game saya memiliki segala macam kesalahan aneh karena Lua menggunakan FPU, dan DirectX memain-mainkan FPU juga ... Saya telah melihat hal-hal seperti 2 * 9000 = 17995 atau 500 * 10 = 4897 itu benar-benar konyol. Tapi kesalahan terburuk mungkin adalah salah satu yang dibahas di forum Ogre3D, di mana 1 + 5 = 4.
speeder
3
Tidak membenarkan komentar; tetapi jika Anda memutuskan untuk menggunakan Q-Floats titik tetap ( en.wikipedia.org/wiki/Q_(number_format) ) adalah teman Anda; mereka sangat cepat dan mudah diimplementasikan.
Jonathan Dickinson
Jadi, ringkasnya ¿haruskah saya tetap menggunakan floating point (jika saya bekerja di Java atau Python)? - Gastón 26 mnt yang lalu
Gastón

Jawaban:

20

Jika Anda mengizinkan saya plug yang tidak tahu malu, saya akan memberikan contoh dari game nyata yang sedang saya kerjakan (tautan video YouTube).

Gim ini memiliki dunia tanpa batas, yang dihasilkan secara prosedural pada mesin fisika. Ini menggunakan floating point presisi tunggal. Setelah beberapa ratus meter ruang permainan, masalah presisi mulai muncul (dan semakin semakin jauh dari asal Anda dapatkan).

Solusi saya? Setiap 200m atau lebih saya memindahkan seluruh dunia kembali sebesar 200m ke arah asal (jika Anda ingin menemukan dan mencoba salah satu prototipe di situs saya, dan membuka overlay debug [w] orld, Anda dapat melihat ini terjadi).

Mengapa tidak menggunakan titik tetap? Atau presisi ganda? Alih-alih presisi tunggal? Karena yang lainnya menggunakan floating point presisi tunggal!

Mesin fisika yang saya gunakan menggunakannya, XNA menggunakannya, data yang dimuat ke kartu grafis diformat sebagai titik mengambang presisi tunggal. Bahkan bahasa itu sendiri dirancang untuk bekerja dengan angka floating point - menulis dan (lebih penting) membaca 0.5fjauh lebih mudah daripada 0x80000000L.

Ini hanya masalah apa yang lebih mudah dalam praktik. Dan pemenang yang jelas adalah menyadari masalah presisi floating point dan menulis fungsi "pindahkan-dunia-kembali-ke-nol" yang cukup sederhana (atau mengimplementasikan partisi ruang atau apa pun yang sesuai dengan permainan Anda).

Dan akhirnya contoh lain - Orbiter adalah game (simulasi, sungguh) yang benar-benar perlu memperhatikan ketepatan. Tidak hanya di ruang angkasa tetapi juga dalam waktu (percepatan waktu plus benda yang mengorbit - tidak ingin mereka jatuh dari langit, sekarang). Ini juga menggunakan angka floating point dan menggunakan peretasan untuk menjaga stabilitas.

Andrew Russell
sumber
Saya selalu bertanya-tanya apakah mungkin lebih mudah bagi beberapa aplikasi untuk memindahkan yang lainnya dan menjaga "pemain" di tempat asalnya. Menarik untuk melihat saya bukan satu-satunya!
dash-tom-bang
Saya suka alasan Anda. Saya hanya ingin menunjukkan bahwa ketika datang ke permainan yang melibatkan jaringan titik tetap tampaknya memiliki lebih sedikit keanehan / penyimpangan (prediksi klien lebih akurat).
Jonathan Dickinson
Saya tidak mengerti argumen Anda dengan baik. Dan omong-omong mengapa bahasa belum menerapkan titik tetap? Tentu saja itu tampaknya menjadi alasan untuk menggunakan float, tetapi itu tidak menjelaskan mengapa fixed point belum diterapkan di mana-mana.
jokoon
@jokoon Saya pikir jawaban saya cukup jelas. Mengapa titik tetap tidak diterapkan di mana-mana? Lihat saja Wikipedia: "Sangat sedikit bahasa komputer yang menyertakan dukungan bawaan untuk nilai-nilai titik tetap, karena untuk sebagian besar aplikasi, representasi titik-mengambang biner atau desimal biasanya lebih mudah digunakan dan cukup akurat ." Seorang desainer yang baik tahu apa yang harus dihilangkan - dan sesuatu yang menduplikasi fungsi dengan cara yang membuatnya sangat mudah bagi seorang programmer untuk menembak diri mereka sendiri di kaki adalah kandidat yang baik.
Andrew Russell
Sepakat. Prosesor saat ini menjalankan instruksi floating point dengan sangat mudah, instruksi tersebut memiliki throughput yang sangat baik dan kebanyakan latensi hanya beberapa siklus lebih lama daripada instruksi integer.
doug65536
11

Pertama - ya, mereka secara signifikan lebih cepat. Bahkan jika Anda bisa mendapatkan titik tetap bekerja secepat FPU "normal", floating point nyata memiliki instruksi yang menguntungkan seperti fsel untuk berhenti bercabang, atau SIMD untuk bekerja pada banyak float sekaligus. GPU juga menggunakan floating point, setidaknya di antarmuka yang menghadap pengguna.

Kedua, 64 bit membuat Anda cukup jauh di floating point juga - kebanyakan orang masih menggunakan 32, tetapi keuntungan utama adalah bahwa ia berskala. Skala titik tetap itu memiliki akurasi tetap. Apakah Anda mengukur matahari ke Pluto, atau di seberang jalan, Anda mendapatkan ketepatan yang sama. Floating point akan memberi Anda hasil yang jauh lebih akurat ketika semua nilai yang terlibat lebih kecil. Karena perpustakaan fisika generik diharapkan bekerja setidaknya dengan lumayan banyak permainan pada skala yang berbeda - dan beberapa permainan itu sendiri mungkin memiliki skala yang sangat berbeda - mereka perlu menggunakan jenis angka yang bekerja pada banyak skala.


sumber
5

Poin penting lain yang harus dikemukakan adalah bahwa mengapung tidak begitu akurat karena orang-orang di sini tampaknya berpikir. Pelampung 32-bit memiliki 24-bit presisi integer penuh. Ini berarti paling tidak seakurat nilai titik tetap 24-bit untuk rentang apa pun yang diberikan. Sementara mengapung menjadi kurang akurat semakin besar nilainya, nilai titik tetap hanya akan meluap dan membungkus di beberapa titik. Mengurangi akurasi adalah fallback yang lebih baik. Mengapung juga bisa meluap, tetapi jauh, jauh di kemudian hari. Saya ingin melihat wajah Anda ketika dunia Anda tiba-tiba membungkus ke -2 ^ 31 karena titik tetap meluap.

Nilai floating point 64-bit memiliki presisi integer 53-bit, sehingga benar-benar akurat.

rasmus
sumber
Nilai floating point tidak benar-benar meluap; jika hasil perhitungan terlalu besar untuk diwakili maka hasilnya adalah Infinity positif atau negatif.
Nanas
3

Dalam konteks FPS, nilai titik tetap mungkin sebenarnya merupakan liabilitas. Tutup ke nol floating-point lebih akurat. Hanya saja jarak yang lebih jauh dari titik tetap menjadi lebih disukai. Jawabannya sederhana bahwa itu tergantung pada konteks.

Dalam sesuatu seperti galaksi, Anda dapat menggunakan kerangka referensi. Gunakan skala besar untuk tata surya dan kemudian gunakan pusat Matahari (atau titik serupa) sebagai titik asal untuk apa pun di dalam sistem. Menggunakan sistem ini Anda dapat memiliki kue dan memakannya, sehingga untuk berbicara, dan itu tidak sulit untuk dibayangkan.

IIRC, dev Infinity mengatakan bahwa ia terus-menerus mengulangi masalah skala dalam salah satu wawancara.

Rushyo
sumber
Kecil kemungkinan bahwa dalam game apa pun Anda membutuhkan ketepatan titik apung "mendekati nol". Jika Anda memiliki unit satu meter, presisi 10 bit memberi Anda akurasi sub-milimeter dan masih memungkinkan Anda memodelkan lebih dari 4000 km di setiap arah jika Anda terjebak dengan nilai 32 bit. Jika Anda membutuhkan presisi lebih dari satu milimeter maka Anda dapat menggeser beberapa bit lagi, pasti. Pindah ke nilai 64 bit dalam game luar angkasa akan memberi Anda tata surya (atau lebih?) Dengan presisi konstan di seluruh volume.
dash-tom-bang
Memang. Dan itulah mengapa Anda akan menggunakan matahari tata surya sebagai titik referensi di dunia seukuran galaksi! Intinya, metode penanganan presisi yang Anda pilih tidak membawa apa pun ke meja. Ini bisa diperdebatkan, jadi Anda sebaiknya menggunakan yang perpustakaan / perangkat keras Anda selaraskan.
Rushyo
Kebetulan, saya mengerjakan game di mana kami harus memodelkan lebih dari 4000 km di setiap arah. Untuk kompatibilitas dengan kode dalam proyek lain, harus menggunakan 32 bit untuk posisi. Ini bukan masalah teoritis, mengingat tuntutan komersial yang ditempatkan pada penggunaan kembali kode dan ukuran dunia game saat ini.
1

Jika belum, Anda harus memeriksa tutorial Planet Rendering di GameDev.net. Adapun pembagian ruang, satu solusi adalah untuk menjaga dua variabel posisi yang terpisah - satu skala makro dan satu skala mikro. Ini bekerja dengan sangat baik (diuji).

Solusi yang tepat tergantung pada bagaimana Anda berencana untuk menangani jarak ekstrem di mesin - apakah Anda merencanakan gerbang lompatan, atau kompresi waktu?

Kornel Kisielewicz
sumber
1

Salah satu alasannya adalah bahwa aritmatika floating point adalah "cukup baik" (atau setidaknya sudah), itu menghasilkan hasil yang cukup akurat dengan cepat.

Selama Anda menyadari keterbatasan aritmatika floating point dan mengubah algoritma Anda untuk mengatasinya (lihat jawaban Andrew Russell) maka Anda akan menghasilkan kode yang "berfungsi".

ChrisF
sumber
-1

Saya sedang menulis permainan. Dalam permainan / program saya, saya menggambar pesawat ruang angkasa di tempat asalnya menggunakan kamera yang cukup tetap dan planet saya menggambar menggunakan kamera terpisah. Dan dua hal ini menangani masalah saya, tetapi planet saya belum terlalu detail. Adapun solusinya Andrew Russell menyebutkan tentang menggerakkan dunia (dan saya berasumsi kamera dan penghuninya kembali ke tempat asalnya) saya benar-benar tidak akan mencobanya jika Anda pernah berencana menjadikan game ini game yang berjaringan. Jika Anda memindahkan dunia pada aplikasi server berdasarkan pada setiap gerakan klien maka dunia akan berakhir berjuang untuk suatu posisi. Dan akan mengambil posisi sepanjang waktu dari semua orang yang bermain yang akan menjadi kesalahan besar.

pengguna1727819
sumber