जब फ़्लोट्स को इसके बजाय ज्यादातर अनुशंसित किया जाता है, तो फ़्लोट्स जावा भाषा का हिस्सा क्यों होते हैं?


84

मैंने जो हर जगह देखा है, वह कहता है कि यह लगभग हर तरह doubleसे बेहतर है float। जावा में floatअप्रचलित कर दिया गया है double, तो इसका उपयोग अभी भी क्यों किया जाता है?

मैं Libgdx के साथ बहुत प्रोग्राम करता हूं, और वे आपको उपयोग करने के लिए मजबूर करते हैं float(डेल्टा टाइम आदि), लेकिन यह मुझे लगता है कि doubleभंडारण और मेमोरी के मामले में काम करना आसान है।

मैं यह भी पढ़ता हूं कि आप फ्लोट का उपयोग कब करते हैं और आप डबल का उपयोग कब करते हैं , लेकिन अगर floatदशमलव बिंदु के बाद बहुत सारे अंकों के साथ केवल संख्याओं के लिए वास्तव में अच्छा है, तो हम सिर्फ एक के कई रूपों का उपयोग क्यों नहीं कर सकते हैं double?

क्या कोई कारण है कि लोग फ़्लोट्स का उपयोग करने पर ज़ोर देते हैं, भले ही इसका वास्तव में कोई फ़ायदा न हो? क्या यह सब बदलना बहुत काम है?



58
कैसे दुनिया में आप अनुमान लगाते हैं "फ्लोट वास्तव में केवल दशमलव संख्या के बाद बहुत सारे अंकों के साथ संख्या के लिए अच्छा है" उस प्रश्न के उत्तरों से! वे सीधे विपरीत कहते हैं !
16

20
@ नाम ध्यान दें कि यह "अंक" कैसे कहता है, "अंक" नहीं। जब आप सटीक या रेंज की आवश्यकता होती है, तो फ़्लोट्स बदतर होते हैं, वे तब बेहतर होते हैं जब आपको बहुत सारे और बहुत सारे सटीक डेटा की आवश्यकता होती है। ऐसा उन जवाबों का कहना है।
आयुध

29
हम क्यों हैं byteऔर shortऔर intजब वहाँ long?
इबिबिस

15
एक और अधिक उपयुक्त प्रश्न यह है कि "आप किसी भाषा और कोड के दशकों के साथ एक भाषा और प्राथमिक डेटाटाइप को क्यों हटाएंगे जो बिना किसी कारण के बस टूट जाएगा"?
सारा

जवाबों:


169

LibGDX एक फ्रेमवर्क है जिसका उपयोग ज्यादातर खेल विकास के लिए किया जाता है।

खेल के विकास में आपको आमतौर पर वास्तविक समय में कई संख्या में क्रंचिंग करनी होती है और किसी भी प्रदर्शन से आपको मामले मिल सकते हैं। यही कारण है कि खेल डेवलपर्स आमतौर पर फ्लोट का उपयोग करते हैं जब भी फ्लोट सटीक पर्याप्त होता है।

सीपीयू में एफपीयू रजिस्टर का आकार केवल एक चीज नहीं है जिसे आपको इस मामले में विचार करने की आवश्यकता है। वास्तव में गेम के विकास में अधिकांश भारी संख्या में क्रंचिंग GPU द्वारा की जाती है, और GPU आमतौर पर फ़्लोट के लिए अनुकूलित होते हैं, डबल्स के लिए नहीं

और फिर वहाँ भी है:

  • मेमोरी बस बैंडविड्थ (आप कितनी तेजी से रैम, सीपीयू और जीपीयू के बीच डेटा को हिला सकते हैं)
  • CPU कैश (जो पिछले कम आवश्यक बनाता है)
  • राम
  • VRAM

जो सभी कीमती संसाधन हैं जिनमें से आप 64 बिट डबल के बजाय 32 बिट फ्लोट का उपयोग करते हैं।


2
धन्यवाद! यह वास्तव में मदद करता था क्योंकि आप गहराई में चले गए थे कि स्मृति का उपयोग क्या बदल गया था और क्यों
इम्स

7
इसके अलावा, SIMD संचालन के लिए, 32-बिट मान दो बार थ्रूपुट हो सकते हैं। जैसा कि 8bittree के उत्तर बताते हैं, GPU में दोहरे परिशुद्धता के साथ एक भी बड़ा प्रदर्शन जुर्माना है।
पॉल ए। क्लेटन

5
कई ग्राफिक पाइपलाइन भी प्रदर्शन को बढ़ाने के लिए 16-बिट आधा-फ्लोट का समर्थन करते हैं, जहां सटीक पर्याप्त है।
आदि श्वेत

22
@phresnel सभी हैं। आपको पदों को स्थानांतरित करना होगा, डेटा अपडेट करना होगा और क्या नहीं। और यह सरल हिस्सा है। फिर आपको टेक्सचर, डिस्टेंस को रेंडर करना (= पढ़ना, घुमाना, स्केल करना और ट्रांसलेट करना) है, इसे स्क्रीन फॉर्मेट में लाएं ... बहुत कुछ करना है।
13

8
एक खेल विकास उद्यम के पूर्व वीपी संचालन के रूप में @phresnel, मैं आपको विश्वास दिलाता हूं कि लगभग हर खेल में एक नंबर की संख्या होती है। ध्यान दें कि यह आमतौर पर पुस्तकालयों में निहित होता है और इंजीनियर से 100% दूर होता है, मुझे उम्मीद है कि वे समझेंगे और सम्मान करेंगे कि यह सब खत्म हो रहा है। जादू उलटा वर्गमूल, कोई भी?
corsiKa

57

फ्लोट्स डबल मेमोरी के रूप में आधी का उपयोग करते हैं।

उनके पास युगल की तुलना में कम सटीकता हो सकती है, लेकिन कई अनुप्रयोगों में परिशुद्धता की आवश्यकता नहीं होती है। उनके पास किसी भी समान आकार के निश्चित बिंदु प्रारूप की तुलना में बड़ी रेंज है। इसलिए, वे एक ऐसा स्थान भरते हैं, जिसमें विस्तृत श्रृंखलाओं की आवश्यकता होती है, लेकिन उच्च परिशुद्धता की आवश्यकता नहीं होती है, और जहां मेमोरी का उपयोग महत्वपूर्ण है। मैंने उन्हें अतीत में बड़े तंत्रिका नेटवर्क प्रणालियों के लिए उपयोग किया है, उदाहरण के लिए।

जावा के बाहर घूमते हुए, वे 3 डी ग्राफिक्स में भी व्यापक रूप से उपयोग किए जाते हैं, क्योंकि कई जीपीयू उन्हें अपने प्राथमिक प्रारूप के रूप में उपयोग करते हैं - बहुत महंगा NVIDIA टेस्ला / एएमडी फायरप्रो उपकरणों के बाहर, GPU पर डबल-सटीक फ़्लोटिंग पॉइंट बहुत धीमा है।


8
तंत्रिका नेटवर्क की बात करें तो, CUDA के पास वर्तमान में मशीन सीखने के काम के लिए एक्सेलेरेटर के बढ़ते उपयोग के कारण आधे सटीक (16-बिट) फ्लोटिंग पॉइंट वैरिएबल, यहां तक ​​कि कम सटीक लेकिन कम मेमोरी के पैरों के निशान के लिए समर्थन है।
JAB

और जब आप FPGAs प्रोग्राम करते हैं तो आप हर बार मैन्युअल और एक्सपोनेंट दोनों के लिए बिट्स की मात्रा का चयन करते हैं: v
सेबी

48

पिछेड़ी संगतता

यह पहले से मौजूद भाषा / पुस्तकालय / ISA / आदि में व्यवहार रखने के लिए नंबर एक कारण है ।

विचार करें कि क्या होगा यदि वे जावा से बाहर तैरते हैं। Libgdx (और हजारों अन्य पुस्तकालय और कार्यक्रम) काम नहीं करेंगे। यह सब कुछ अपडेट करने के लिए बहुत प्रयास करने जा रहा है, संभवतः कई परियोजनाओं के लिए वर्ष (बस पीछे की संगतता-तोड़ने वाले पायथन 2 से पायथन 3 संक्रमण को देखें)। और सब कुछ अपडेट नहीं किया जाएगा, कुछ चीजें हमेशा के लिए टूट जाएंगी क्योंकि रखवाले ने उन्हें छोड़ दिया, शायद जितनी जल्दी उनके पास होगा क्योंकि इससे अधिक प्रयास करना होगा जितना वे अपडेट करना चाहते हैं, या क्योंकि यह अब संभव नहीं है कि उनके सॉफ्टवेयर को पूरा करना संभव नहीं है। करने के लिए।

प्रदर्शन

64 बिट डबल्स मेमोरी को दोगुना कर देते हैं और लगभग हमेशा 32 बिट फ्लोट्स की प्रक्रिया के लिए धीमी होती हैं (बहुत कम अपवाद जहां 32 बिट फ्लोट की क्षमता का उपयोग करने की उम्मीद की जाती है, शायद ही कभी ऐसा हो या नहीं, कि उनके लिए अनुकूलन करने के लिए कोई प्रयास नहीं किया गया था। जब तक आप विशेष हार्डवेयर के लिए विकसित नहीं कर रहे हैं, आप निकट भविष्य में इसका अनुभव नहीं करेंगे।)

विशेष रूप से आपके लिए प्रासंगिक है, लिबगडक्स एक खेल पुस्तकालय है। खेलों में अधिकांश सॉफ्टवेयर की तुलना में अधिक प्रदर्शन संवेदनशील होने की प्रवृत्ति होती है। और गेमिंग ग्राफिक्स कार्ड (यानी AMD Radeon और NVIDIA Geforce, FirePro या Quadro नहीं) में बहुत कमजोर 64 बिट फ्लोटिंग पॉइंट परफॉर्मेंस है। आनंदटेक के सौजन्य से, यहां बताया गया है कि एएमडी और एनवीआईडीआईए के शीर्ष गेमिंग कार्ड में से कुछ पर सटीक परिशुद्धता प्रदर्शन की तुलना में डबल सटीक प्रदर्शन कैसे उपलब्ध है (2016 की शुरुआत में)

AMD
Card    R9 Fury X      R9 Fury       R9 290X    R9 290
FP64    1/16           1/16          1/8        1/8

NVIDIA
Card    GTX Titan X    GTX 980 Ti    GTX 980    GTX 780 Ti
FP64    1/32           1/32          1/32       1/24

ध्यान दें कि R9 रोष और GTX 900 श्रृंखला R9 200 और GTX 700 श्रृंखला की तुलना में नए हैं, इसलिए 64 बिट फ्लोटिंग पॉइंट के लिए सापेक्ष प्रदर्शन कम हो रहा है। काफी दूर तक जाएं और आपको GTX 580 मिलेगा, जिसका R9 200 श्रृंखला की तरह 1/8 अनुपात था।

यदि आप एक तंग समय बाधा है और बड़ा डबल का उपयोग करके ज्यादा हासिल नहीं करते हैं तो भुगतान का 1/32 एक बहुत बड़ा जुर्माना है।


1
ध्यान दें कि 64-बिट फ्लोटिंग पॉइंट के लिए प्रदर्शन 32-बिट प्रदर्शन के सापेक्ष तेजी से घटते-बढ़ते 32-बिट निर्देशों के सापेक्ष कम हो रहा है, इसलिए नहीं कि वास्तविक 64-बिट प्रदर्शन कम हो रहा है। यह भी इस्तेमाल किया वास्तविक बेंचमार्क पर निर्भर करता है; मुझे आश्चर्य है कि अगर 32-बिट प्रदर्शन घाटे को इन बेंचमार्क में हाइलाइट किया जाता है, तो मेमोरी बैंडविड्थ मुद्दों के साथ-साथ वास्तविक कम्प्यूटेशनल गति भी है
sig_seg_v

यदि आप ग्राफिक्स कार्ड में DP प्रदर्शन के बारे में बात करने जा रहे हैं तो आपको निश्चित रूप से टाइटन / टाइटन ब्लैक का उल्लेख करना चाहिए। दोनों फीचर मोड्स जो एकल परिशुद्धता प्रदर्शन की कीमत पर कार्ड को 1/3 प्रदर्शन तक पहुंचने की अनुमति देते हैं।
एसजीआर

@sig_seg_v निश्चित रूप से कम से कम कुछ मामले हैं जहां 64-बिट प्रदर्शन बिल्कुल कम हो जाते हैं, न कि केवल अपेक्षाकृत। एक डबल परिशुद्धता फोल्डिंग @ होम बेंचमार्क के लिए ये परिणाम देखें , जहां एक GTX 780 Ti दोनों GTX 1080 (एक अन्य 1/32 अनुपात कार्ड) और एक 980 Ti, और AMD की तरफ 7970 (1/4 अनुपात कार्ड) दोनों को हराता है। , साथ ही R9 290 और R9 290X सभी ने R9 फ्यूरी श्रृंखला को हराया। इसकी तुलना बेंचमार्क के एकल सटीक संस्करण से करें , जहां नए कार्ड सभी अपने पूर्ववर्तियों को बेहतर ढंग से प्रदर्शित करते हैं।
8bittree

36

परमाणु संचालन

दूसरों ने जो पहले ही कहा है, इसके अलावा, एक जावा-विशिष्ट नुकसान double(और long) यह है कि 64-बिट आदिम प्रकार के असाइनमेंट को परमाणु होने की गारंटी नहीं है । से जावा भाषा विशिष्टता, जावा SE 8 संस्करण , पेज 660 (जोर जोड़ा):

17.7 गैर-परमाणु उपचार doubleऔरlong

जावा प्रोग्रामिंग लैंग्वेज मेमोरी मॉडल के प्रयोजनों के लिए, एक गैर-वाष्पशील longया doubleमान के लिए एक एकल लेखन को दो अलग-अलग लेखन के रूप में माना जाता है: प्रत्येक 32-बिट आधे के लिए। यह एक ऐसी स्थिति में परिणाम हो सकता है जहां एक थ्रेड एक लिखने से 64-बिट मान के पहले 32 बिट्स को देखता है, और दूसरे 32 बिट्स को किसी अन्य लेखन से।

छी।

इससे बचने के लिए, आपको कीवर्ड के साथ 64-बिट चर घोषित करना होगाvolatile , या असाइनमेंट के आसपास सिंक्रनाइज़ेशन के कुछ अन्य रूप का उपयोग करना होगा।


2
क्या आपको खोए हुए अपडेट को रोकने के लिए किसी भी तरह से इन्ट्रेट्स को समवर्ती एक्सेस और फ्लोट्स को सिंक्रोनाइज़ करने की आवश्यकता नहीं है और ओवरएजर्स कोचिंग को रोकने के लिए उन्हें अस्थिर किया जाए? क्या मैं यह सोचने में गलत हूं कि केवल एक ही चीज int / float atomicity को रोकती है कि वे "मिश्रित" मूल्यों को कभी नहीं रख सकते हैं जो वे धारण करने वाले नहीं थे?
त्रुबेनफुच्स

3
@Traubenfuchs यही है, वास्तव में वहाँ क्या गारंटी है। मैंने इसके लिए इस्तेमाल किया शब्द "फाड़" है, और मुझे लगता है कि यह काफी अच्छी तरह से प्रभाव को पकड़ता है। जावा प्रोग्रामिंग भाषा मॉडल गारंटी देता है कि 32 बिट मान, जब पढ़ा जाता है, तो एक मूल्य होगा जो उन्हें किसी बिंदु पर लिखा गया था। यह आश्चर्यजनक रूप से मूल्यवान गारंटी है।
कॉर्ट अमोन

परमाणु के बारे में यह बात अति-महत्वपूर्ण है। वाह, मैं इस महत्वपूर्ण तथ्य के बारे में भूल गया था। प्रकृति के द्वारा परमाणु के रूप में हम आदिम के बारे में सोचने के लिए प्रति-सहज ज्ञान युक्त हो सकते हैं। लेकिन इस मामले में परमाणु नहीं।
बेसिल बॉर्क

3

ऐसा लगता है कि अन्य उत्तर एक महत्वपूर्ण बिंदु से चूक गए हैं: SIMD आर्किटेक्चर कम / अधिक डेटा संसाधित कर सकते हैं यदि वे doubleया floatस्ट्रक्चर्स पर काम करते हैं (उदाहरण के लिए, एक समय में आठ फ्लोट मान, या एक समय में चार डबल मान)।

प्रदर्शन विचार सारांश

  • float कुछ CPU (उदाहरण के लिए, कुछ मोबाइल डिवाइस) पर तेज़ हो सकता है।
  • float कम स्मृति का उपयोग करता है इसलिए विशाल डेटा सेट में यह कुल आवश्यक मेमोरी (हार्ड डिस्क / रैम) और खपत बैंडविड्थ को काफी कम कर सकता है।
  • float एक सीपीयू के कारण कम बिजली की खपत हो सकती है (मैं एक संदर्भ नहीं ढूँढ सकता, लेकिन यदि संभव नहीं है तो कम से कम प्रशंसनीय है) डबल-सटीक संगणना की तुलना में एकल-सटीक संगणना के लिए।
  • float कम बैंडविड्थ की खपत करता है, और कुछ अनुप्रयोगों में जो मायने रखता है।
  • SIMD आर्किटेक्चर आमतौर पर डेटा की समान मात्रा से दुगुनी प्रक्रिया कर सकता है।
  • float दोहरे की तुलना में आधे से अधिक कैश मेमोरी का उपयोग करता है।

सटीकता विचार सारांश

  • कई अनुप्रयोगों floatमें पर्याप्त है
  • double वैसे भी बहुत अधिक सटीक है

अनुकूलता के विचार

  • यदि आपका डेटा किसी GPU (उदाहरण के लिए, OpenGL या किसी अन्य रेंडरिंग API का उपयोग करते हुए वीडियो गेम के लिए ) प्रस्तुत किया जाना है, तो फ़्लोटिंग पॉइंट प्रारूप काफी तेज़ी से होता है double(ऐसा इसलिए है क्योंकि GPU निर्माता ग्राफिक्स कोर की संख्या बढ़ाने की कोशिश करते हैं, और इस प्रकार वे प्रत्येक कोर में जितना संभव हो उतना सर्किटरी को बचाने की कोशिश करते हैं, इसलिए floatअंदर के अधिक कोर के साथ GPU बनाने की अनुमति के लिए अनुकूलन )
  • पुराने GPU और कुछ मोबाइल डिवाइस केवल doubleआंतरिक प्रारूप (3D रेंडरिंग ऑपरेशंस के लिए) के रूप में स्वीकार नहीं कर सकते हैं

सामान्य टिप्स

  • आधुनिक डेस्कटॉप प्रोसेसर (और शायद मोबाइल प्रोसेसर की एक अच्छी मात्रा) पर आप मूल रूप doubleसे स्टैक पर अस्थायी चर का उपयोग कर सकते हैं ।
  • कभी भी अपनी आवश्यकता से अधिक परिशुद्धता का उपयोग न करें (आपको पता नहीं हो सकता है कि आपको वास्तव में कितनी सटीकता की आवश्यकता है)।
  • कभी-कभी आप मूल्यों की सीमा से मजबूर होते हैं (यदि आप उपयोग कर रहे हैं तो कुछ मूल्य अनंत होंगे float, लेकिन यदि आप उपयोग कर रहे हैं तो सीमित मूल्य हो सकते हैं double)
  • केवल floatया केवल का उपयोग doubleकरने से कंपाइलर को SIMD-ify निर्देशों की मदद मिलती है।

अधिक जानकारी के लिए पीटरकॉर्ड्स से नीचे टिप्पणी देखें।


1
doubleअस्थायी केवल x86 FPU के साथ x86 पर स्वतंत्र हैं, SSE2 के साथ नहीं। ऑटो vectorizing के साथ एक पाश doubletemporaries खोल का मतलब floatकरने के लिए doubleहै, जो एक अतिरिक्त शिक्षा लेता है, और आप आधा वेक्टर के अनुसार कई तत्वों पर कार्रवाई। ऑटो-वेक्टरकरण के बिना, रूपांतरण आमतौर पर लोड या स्टोर के दौरान मक्खी पर हो सकता है, लेकिन इसका मतलब है कि अतिरिक्त निर्देश जब आप फ्लोट और युगल में मिश्रण कर रहे हैं।
पीटर कॉर्डेस

1
आधुनिक x86 सीपीयू पर, div और sqrt डबल की तुलना में फ्लोट के लिए तेज़ हैं, लेकिन अन्य चीजें समान गति हैं (SIMD वेक्टर की चौड़ाई के मुद्दे की गिनती नहीं, या मेमोरी बैंडविड्थ / कैश फ़ुटप्रिंट ऑफ़ कोर्स)।
पीटर कॉर्डेस

@PeterCordes कुछ बिंदुओं के विस्तार के लिए धन्यवाद। मैं div और sqrt असमानता के बारे में नहीं जानता था
GameDeveloper

0

अन्य कारणों के अलावा जिनका उल्लेख किया गया था:

यदि आपके पास डेटा है, तो दबाव, प्रवाह, धाराओं, वोल्टेज या जो कुछ भी हो, यह अक्सर एडीसी वाले हार्डवेयर के साथ किया जाता है।

एक एडीसी में आमतौर पर 10 या 12 बिट्स होते हैं, 14 या 16 बिट्स दुर्लभ होते हैं। लेकिन चलो 16 बिट पर छड़ी करते हैं - यदि पूर्ण पैमाने पर मापते हैं, तो आपके पास 1/65535 की सटीकता है। इसका मतलब है कि 65534/65535 से 65535/65535 तक एक बदलाव सिर्फ यह कदम है - 1/65535। यह लगभग 1.5E-05 है। एक फ्लोट की सटीकता लगभग 1E-07 है, इसलिए बहुत बेहतर है। इसका मतलब है कि आप floatइन डेटा को संग्रहीत करने के लिए उपयोग करके कुछ भी नहीं खोते हैं ।

यदि आप फ्लोट्स के साथ अत्यधिक गणना करते हैं, तो आप doublesसटीकता के मामले में हल्के से खराब प्रदर्शन करते हैं, लेकिन अक्सर आपको उस सटीकता की आवश्यकता नहीं होती है, जैसा कि आप अक्सर परवाह नहीं करते हैं यदि आपने सिर्फ 2 वी या 2.00002 वी का वोल्टेज मापा है। इसी तरह , यदि आप इस वोल्टेज को एक दबाव में परिवर्तित करते हैं, तो आपको परवाह नहीं है कि आपके पास 3 बार या 3.00003 बार है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.