Kayar nokta hassasiyeti hakkında ve neden hala kullanıyoruz


38

Kayan nokta büyük dünyalarda hassasiyet için her zaman zahmetli olmuştur.

Bu makale perde arkasını açıklamakta ve açık alternatif - sabit nokta numaraları sunmaktadır. Bazı gerçekler, gerçekten etkileyici:

"Peki 64 bit hassasiyet, sizi mikroskobik bir hassasiyetle güneşten (7,4 milyar km) en uzak mesafeye Pluto'ya götürür."

Alt mikrometre hassasiyeti, fps ihtiyaçlarından daha fazladır (pozisyonlar ve hatta hızlar için) ve gerçekten büyük dünyalar inşa etmenizi sağlar.

Sorum şu ki, eğer sabit nokta bu gibi avantajlara sahipse neden hala kayan nokta kullanıyoruz? Çoğu oluşturma API'si ve fizik kütüphanesi kayan nokta kullanır (ve dezavantajları vardır, bu nedenle geliştiricilerin çevrelerinde dolaşmaları gerekir).

Çok mu yavaşlar?

Ek olarak, outerra veya infinity gibi ölçeklendirilebilir planet motorların büyük ölçeği nasıl ele aldığını düşünüyorsunuz? Pozisyonlar için sabit nokta mu kullanıyorlar ya da boşluk bölme algoritması var mı?


3
Son "ek" bit muhtemelen ayrı bir soru olmalıdır, bu yüzden asıl sorundan kaçınmaz.
Tetrad

Sabit noktaya nasıl zorlanacağımı bulmak istiyorum ... Oyunumda garip hatalar var çünkü Lua FPU kullanıyor ve DirectX de FPU'yu kullanıyor ... 2 * 9000 = 17995 veya 500 * 10 gibi şeyler gördüm. = 4897 gerçekten saçma. Ama en kötü hata büyük olasılıkla 1 + 5 = 4. Ogre3D forumlarda tartışılan biri olan
speeder

3
Bir yorumu haklı çıkarmadı; ama eğer Q-Floats sabit nokta kullanmaya karar verirseniz ( en.wikipedia.org/wiki/Q_(number_format) ) arkadaşınızdır; gülünç hızlı ve uygulaması kolaydır.
Jonathan Dickinson

Yani, özetlemek için ¿kayan noktalara bağlı mıyım (Java ya da Python'da çalışıyorsam)? - Gastón 26 dak önce
Gastón

Yanıtlar:


20

Utanmaz bir fişe izin verirseniz, size üzerinde çalıştığım gerçek bir oyundan bir örnek vereceğim (YouTube videosu bağlantısı).

Oyunun fizik motoru üzerinde sonsuz, usule uygun şekilde üretilmiş bir dünya var. Tek duyarlıklı kayan nokta kullanır. Birkaç yüz metrelik oyun alanının ardından, hassas konular ortaya çıkmaya başlar (ve gittikçe daha kötüye gittiğinizden daha da kötüleşir).

Çözümüm? Her 200 metrede bir, bütün dünyayı 200 metreye kadar kökene doğru geri götürüyorum (sitemdeki prototiplerden birini bulup denemek ve [w] sıradan hata ayıklama bindirmesini getirmek isterseniz, bunun olduğunu görebilirsiniz).

Neden sabit nokta kullanmıyorsunuz? Veya çift hassasiyetli? Tek duyarlık yerine? Çünkü her şey tek bir hassas kayan nokta kullanıyor!

Kullandığım fizik motoru onu kullanıyor, XNA kullanıyor, grafik kartına yüklenen veriler tek duyarlıklı kayan nokta olarak biçimlendiriliyor. Dilin kendisi bile kayan noktalı sayılarla çalışacak şekilde tasarlanmıştır - yazma ve (daha da önemlisi) okuma 0.5fçok daha kolaydır 0x80000000L.

Bu sadece pratikte kolay olanın meselesi. Ve kesin kazanan noktası hassas konularını yüzen ve farkında olmaktır yazma oldukça basit "Hareket-dünya-back-to-sıfır" fonksiyonları (veya boşluk bölümleme veya oyununuzu hangisi uyarsa uygulanması).

Ve nihayet başka bir örnek - Orbiter , gerçekten hassasiyetle ilgilenmesi gereken bir oyundur (simülasyon, gerçekten). Sadece uzayda değil, zamanda da zaman (zaman ivme artı yörüngeye bakan cisimler - şimdi gökten düşmelerini istemiyoruz). Ayrıca kayan nokta sayıları kullanır ve dengeyi korumak için bir hack kullanır .


Bazı uygulamaların her şeyi başka bir yere taşımasının ve "oynatıcıyı" başlangıçta tutmasının daha kolay olup olmadığını her zaman merak etmişimdir . Görmek ilginç, sadece ben değilim!
çizgi-tom-bang,

Sebeplerini beğendim. Ağa bağlanma noktası içeren oyunlar söz konusu olduğunda daha az tuhaflığa / sapmaya sahip gibi göründüğünü belirtmek isterim (müşteri tahmini daha doğrudur).
Jonathan Dickinson

Argümanı çok iyi anlamıyorum. Ve bu arada, neden diller henüz sabit bir noktaya değinmedi? Elbette bu, yüzer kullanmak için çizilmiş bir neden gibi görünüyor, ancak bu, sabit noktaların neden her yerde kullanılmadığını açıklamıyor.
jokoon

@jokoon Cevabımın oldukça açık olduğunu düşündüm. Neden sabit nokta her yerde uygulanmıyor? Sadece Wikipedia'ya bakın: "Çok az sayıda bilgisayar dili, sabit nokta değerleri için yerleşik destek içerir, çünkü çoğu uygulama için, ikili veya ondalık kayan nokta gösterimleri genellikle kullanımı daha kolaydır ve yeterince doğrudur ." İyi bir tasarımcı, neyin atlanacağını bilir - ve bir programcının kendisini ayağından vurmasını kolaylaştıracak şekilde işlevselliği çoğaltan bir şey iyi bir adaydır.
Andrew Russell,

Kabul. Günümüzün işlemciler kayan nokta komutlarını çok kolay bir şekilde uygularlar, talimatlar mükemmel verime sahiptir ve çoğu tamsayı talimatlarından yalnızca birkaç kez daha uzun gecikme süresidir.
doug65536

11

İlk önce - evet, çok daha hızlılar. Sabit bir noktayı "normal" bir FPU kadar hızlı çalışabilseniz bile, gerçek kayan nokta dallanmayı durdurmak için fsel veya bir seferde birçok yüzer üzerinde çalışmak için SIMD gibi avantajlı talimatlara sahiptir. GPU'lar ayrıca en azından kullanıcı arayüzlerinde de kayan nokta kullanırlar.

İkincisi, 64 bit sizi kayan noktaya oldukça götürür - çoğu insan hala 32 kullanır, ancak birincil avantajı ölçeklendirmesidir. Bu sabit nokta ölçeğinin sabit bir doğruluğu vardır. Güneşi Pluto'ya veya caddenin karşısına ölçtüğünüzde aynı hassasiyeti alırsınız. Kayan nokta, ilgili tüm değerler daha küçük olduğunda size daha doğru sonuçlar verecektir. Genel fizik kütüphanelerinin en azından pasif bir şekilde farklı ölçeklerdeki oyunlarla çalışması - ve bazı oyunların kendilerinin çok farklı ölçeklere sahip olmaları - birçok ölçekte çalışan bir sayı kullanmaları gerekir.


5

Dikkat edilmesi gereken bir diğer önemli nokta, yüzerlerin buradaki insanların düşündüğü kadar yanlış olmadığıdır. 32 bitlik bir kayan nokta, 24 bit tam sayı kesinliğine sahiptir. Bu, belirli bir aralık için en az 24 bit sabit nokta değeri kadar doğru olduğu anlamına gelir. Şamandıralar daha az hassas olurken değer ne kadar büyürse, sabit bir nokta değeri taşar ve bir noktada sarılır. Doğruluğu azaltmak daha iyi bir geri dönüş olduğunu. Şamandıralar da taşabilir, fakat çok sonra. Sabit nokta taşması nedeniyle dünyanız aniden -2 ^ 31'e dolaştığında yüzlerinizi görmek isterim.

64 bit kayan nokta değerleri, 53 bit tam sayı hassasiyetine sahiptir, bu yüzden gerçekten doğrudurlar.


Kayan nokta değerleri aslında taşma yapmaz; Bir hesaplamanın sonucu temsil edilemeyecek kadar büyükse, sonuç pozitif veya negatif Infinity olur.
Ananas

3

Bir FPS bağlamında, sabit nokta değerleri aslında bir sorumluluk olabilir. Sıfıra yakın kayan nokta daha doğru. Sadece çok büyük mesafelerde sabit nokta daha çok tercih edilir hale gelir. Cevap basitçe bağlamına bağlı olmasıdır.

Galaksiye benzer bir şeyde referans çerçevelerini kullanabilirsiniz. Güneş sistemleri için büyük bir ölçek kullanın ve daha sonra sistemin içindeki herhangi bir şeyin menşe noktası olarak Güneş'in merkezini (veya benzer bir noktayı) kullanın. Bu sistemi kullanarak, pastanızı yiyebilir ve yiyebilirsiniz, tabiri caizse, ve bunun hayal edilmesi zor değildir.

IIRC, Infinity devi, röportajlarından birinde sürekli olarak ölçek meselelerini yinelediğini belirtti.


Herhangi bir oyunda kayan nokta "sıfıra yakın" hassasiyete ihtiyaç duymanız olası değildir. Bir metre biriminiz varsa, 10 bit hassasiyet size milimetre alt hassasiyet sağlar ve yine de 32 bitlik değerlerle sıkışmışsanız her yönde 4000km'den fazla modellemenizi sağlar. Bir milimetreden daha fazla hassasiyete ihtiyacınız varsa, o zaman kesin bir kaç bit daha değiştirebilirsiniz. Bir uzay oyunundaki 64 bitlik değere geçmek size tüm hacim boyunca sabit hassasiyette bir güneş sistemi (veya daha fazla?) Verir.
çizgi-tom-bang,

Aslında. İşte bu yüzden, güneş sisteminin Sun'ını galaksideki bir dünyada referans noktası olarak kullanırsınız! Mesele şu ki, seçtiğiniz işleme hassasiyeti yöntemi masaya hiçbir şekilde bir şey getirmiyor. Tartışmasız, kütüphanenizin / donanımınızın uyduğu kütüphaneyi kullanabilirsiniz.
Rushyo,

Bu arada, her yöne 4000km den fazla model oluşturmamız gereken bir oyun üzerinde çalıştım. Diğer projelerde kod ile uyumluluk için, pozisyonlar için 32 bit kullanmak zorunda kaldı. Bugün kod kullanımına ve oyun dünyasının büyüklüğüne verilen ticari talepler göz önüne alındığında bu teorik bir sorun değil.

1

Henüz yapmadıysanız, GameDev.net'teki Planet Rendering eğitimini kesinlikle kontrol etmelisiniz. Uzay bölünmesine gelince, bir çözüm iki ayrı konum değişkeni tutmaktır - bir makro ölçeği ve bir mikro ölçek. Bu oldukça iyi çalışıyor (test edildi).

Kesin çözüm, motordaki aşırı mesafeleri nasıl tutmayı planladığınıza bağlıdır - zıplama kapıları mı yoksa zaman sıkıştırması mı planlıyorsunuz?


1

Sebeplerden biri, kayan nokta aritmetiğinin "yeterince iyi" olmasıdır (veya en azından öyleydi), hızlıca oldukça doğru sonuçlar veriyor.

Kayan nokta aritmetiğinin sınırlarının farkında olduğunuz ve algoritmalarınızı bunlarla başa çıkacak şekilde değiştirdiğiniz sürece (bkz. Andrew Russell'ın cevabı) daha sonra "işe yarayan" kod üreteceksiniz.


-1

Bir oyun yazıyorum Oyunumda / programımda, oldukça sabit bir kamera kullanarak orijinden bir uzay gemisi çizerim ve gezegenim ayrı bir kamera kullanarak çizerim. Ve bu iki şey benim için konuyla ilgileniyor, ancak gezegenim henüz ayrıntılı değil. Andrew Russell'ın dünyayı hareket etmekten bahsettiği çözüme gelince (ve kamerayı ve sakinlerini kökene doğru geri aldığımı farz ediyorum), oyunu bir ağ oyunu kurmayı planlıyorsanız, gerçekten denemem. Her müşterinin hareketlerine dayanarak dünyayı sunucu uygulamasına taşıdıysanız, dünya bir pozisyon için mücadele eder. Ve her zaman büyük bir aksaklık olacak olan herkes oynayarak yerini alacaktı.

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.