OCaml में केवल 31 बिट्स में इंट क्यों है?


115

यह "सुविधा" कहीं और नहीं देखी गई। मुझे पता है कि 32 वें बिट का उपयोग कचरा संग्रहण के लिए किया जाता है। लेकिन ऐसा क्यों है कि केवल किलों के लिए और अन्य बुनियादी प्रकारों के लिए नहीं?


10
ध्यान दें कि 64-बिट ऑपरेटिंग सिस्टम पर, OCaml में एक इंट 63 बिट्स है, 31 नहीं। यह टैग बिट के अधिकांश व्यावहारिक समस्याओं (जैसे सरणी आकार सीमा) को हटा देता है। और निश्चित रूप से वहाँ int32 प्रकार है अगर आप कुछ मानक एल्गोरिथ्म के लिए एक वास्तविक 32-बिट पूर्णांक की जरूरत है।
पोर्कुलस

1
nekoVM ( nekovm.org ) में भी हाल तक 31 बिट्स थे।
हिप्पो

जवाबों:


244

इसे टैग किए गए पॉइंटर प्रतिनिधित्व कहा जाता है , और दशकों के लिए कई अलग-अलग दुभाषियों, वीएम और रनटाइम सिस्टम में उपयोग किया जाने वाला एक बहुत ही सामान्य अनुकूलन चाल है। बहुत ज्यादा हर लिस्प कार्यान्वयन में उनका उपयोग होता है, कई स्मॉलटॉक वीएम, कई रूबी दुभाषिया, और इसी तरह।

आमतौर पर, उन भाषाओं में, आप हमेशा पॉइंटर्स टू ऑब्जेक्ट्स से गुजरते हैं। एक ऑब्जेक्ट में ही एक ऑब्जेक्ट हेडर होता है, जिसमें ऑब्जेक्ट मेटाडेटा होता है (जैसे ऑब्जेक्ट का प्रकार, उसका वर्ग (तों), शायद नियंत्रण प्रतिबंध या सुरक्षा एनोटेशन और इतने पर पहुंच), और फिर वास्तविक ऑब्जेक्ट डेटा ही। तो, एक साधारण पूर्णांक को एक सूचक के रूप में दर्शाया जाएगा और एक वस्तु जो मेटाडेटा और वास्तविक पूर्णांक से मिलकर बनेगी। यहां तक ​​कि बहुत कॉम्पैक्ट प्रतिनिधित्व के साथ, यह एक साधारण पूर्णांक के लिए 6 बाइट की तरह कुछ है।

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

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

हालांकि, चाल यह है कि पूर्णांक जैसे तथाकथित अपरिवर्तनीय मूल्य प्रकारों के साथ, आपको आमतौर पर ऑब्जेक्ट हेडर में सभी मेटाडेटा की आवश्यकता नहीं होती है : आप बस उस सभी सामान को छोड़ सकते हैं, और बस इसे संश्लेषित कर सकते हैं (जो VM-nerd है- "नकली यह" के लिए बोलें), जब कोई भी देखने के लिए परवाह करता है। पूर्णांक में हमेशा कक्षा होगी Integer, उस जानकारी को अलग से संग्रहीत करने की कोई आवश्यकता नहीं है। यदि कोई किसी पूर्णांक के वर्ग का पता लगाने के लिए प्रतिबिंब का उपयोग करता है, तो आप बस उत्तर देते हैं Integerऔर कोई भी कभी भी नहीं जान पाएगा कि आपने वास्तव में उस जानकारी को ऑब्जेक्ट हेडर में संग्रहीत नहीं किया है और वास्तव में, ऑब्जेक्ट हेडर (या नहीं) भी नहीं है वस्तु)।

तो, चाल मान संग्रहीत है की सूचक के भीतर वस्तु के लिए , वस्तु को प्रभावी ढंग से एक में दो गिर।

सीपीयू हैं जो वास्तव में एक पॉइंटर (तथाकथित टैग बिट्स ) के भीतर अतिरिक्त स्थान रखते हैं जो आपको पॉइंटर के बारे में पॉइंटर के बारे में अतिरिक्त जानकारी संग्रहीत करने की अनुमति देते हैं। "यह वास्तव में एक सूचक नहीं है, यह पूर्णांक है" जैसी अतिरिक्त जानकारी। उदाहरणों में बरोज़ B5000, विभिन्न लिस्प मशीनें या AS / 400 शामिल हैं। दुर्भाग्य से, वर्तमान मुख्यधारा के अधिकांश सीपीयू में वह सुविधा नहीं है।

हालाँकि, वहाँ एक रास्ता है: ज्यादातर मौजूदा मुख्यधारा सीपीयू जब शब्द सीमाओं पर संरेखित नहीं होते हैं, तो काफी धीमी गति से काम करते हैं। कुछ भी अनकही पहुँच का समर्थन नहीं करते हैं।

इसका मतलब यह है कि व्यवहार में, सभी बिंदु 4 से विभाज्य होंगे, जिसका अर्थ है कि वे हमेशा दो 0बिट्स के साथ समाप्त होंगे । यह हमें वास्तविक बिंदुओं (कि अंत में 00) और संकेत के बीच अंतर करने की अनुमति देता है जो वास्तव में भेस में पूर्णांक हैं (जो अंत में समाप्त होते हैं 1)। और यह अभी भी हमें सभी बिंदुओं के साथ छोड़ देता है जो 10अन्य सामान करने के लिए स्वतंत्र रूप से समाप्त होते हैं। इसके अलावा, अधिकांश आधुनिक ऑपरेटिंग सिस्टम खुद के लिए बहुत कम पते आरक्षित करते हैं, जो हमें एक और क्षेत्र के साथ खिलवाड़ करने के लिए देता है (संकेत जो कहते हैं, 24 0एस और अंत के साथ शुरू होते हैं 00)।

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

हम उन अन्य पता स्थानों के साथ क्या करते हैं? ठीक है, विशिष्ट उदाहरण एन्कोडिंग शामिल floatअन्य बड़ी पता स्थान और की तरह विशेष वस्तुओं की संख्या में रों true, false, nil, 127 ASCII वर्ण, कुछ आमतौर पर इस्तेमाल किया संक्षिप्त स्ट्रिंग, खाली सूची, खाली वस्तु, खाली सरणी और इतने पर के पास 0पता।

उदाहरण के लिए, MRI, YARV और रूबिनस रूबी दुभाषियों में, पूर्णांकों को मेरे द्वारा वर्णित तरीके falseसे एन्कोड किया जाता है, पते के रूप में एन्कोडेड किया जाता है 0(जो कि ऐसा ही होता है, C में इसका प्रतिनिधित्व भी होता falseहै), trueपते के रूप में 2(जो कि बस होता है) सी true) एक बिट द्वारा स्थानांतरित कर दिया) और के nilरूप में 4


5
ऐसे लोग हैं जो कहते हैं कि यह जवाब अभेद्य है । मुझे नहीं पता कि क्या यह मामला है या यदि वे नाइटपार्टिंग कर रहे हैं। मैंने सोचा था कि मैं इसे सच होने की स्थिति में इंगित करूंगा।
सर्फ करें

5
@threeFourOneSixOneThree यह उत्तर OCaml के लिए पूरी तरह से सटीक नहीं है क्योंकि, OCaml में, इस उत्तर का "इसे संश्लेषित करें" भाग कभी नहीं होता है। OCaml कोई ऑब्जेक्ट-ओरिएंटेड भाषा नहीं है जैसे स्मॉलटाक या जावा हैं। OCaml के तरीके तालिका को पुनः प्राप्त करने का कोई कारण नहीं है int
पास्कल क्यूक

Chrome का V8 इंजन एक टैग किए गए पॉइंटर का भी उपयोग करता है और एक 31-बिट पूर्णांक को संग्रहीत करता है जिसे अनुकूलन के रूप में smi (स्मॉल
इंटेगर

@ एफ्युल्व: यह आश्चर्यजनक नहीं है, निश्चित रूप से। हॉटस्पॉट जेवीएम की तरह, वी 8 एनिमोर्फिक स्मॉलटाक वीएम पर आधारित है, जो बदले में सेल्फ वीएम पर आधारित है। और V8 का विकास (कुछ) उन्हीं लोगों द्वारा किया गया था जिन्होंने हॉटस्पॉट JVM, एनिमोर्फिक स्मॉलटॉक वीएम और सेल्फ वीएम विकसित किए थे। लार्स बक, विशेष रूप से, उन सभी पर काम किया, साथ ही अपने खुद के स्मॉलटॉक वीएम को ओओवीएम कहा। इसलिए, यह बिल्कुल भी आश्चर्य की बात नहीं है कि वी 8 स्मॉलटाकल की दुनिया की जानी-मानी ट्रिक्स का इस्तेमाल करता है, क्योंकि इसे स्मॉलटॉक टेक्नोलॉजी पर आधारित स्मॉलटालकर्स ने बनाया था।
जॉर्ग डब्ल्यू मित्तग

28

एक अच्छे वर्णन के लिए https://ocaml.org/learn/tutorials/performance_and_profiling.html के अनुभाग में "पूर्णांक, टैग बिट्स, हीप-आबंटित मानों का प्रतिनिधित्व" देखें ।

संक्षिप्त उत्तर यह है कि यह प्रदर्शन के लिए है। किसी फ़ंक्शन के तर्क को पास करते समय इसे या तो पूर्णांक या पॉइंटर के रूप में पास किया जाता है। मशीन स्तर की भाषा के स्तर पर यह बताने का कोई तरीका नहीं है कि क्या एक रजिस्टर में एक पूर्णांक या एक सूचक है, यह सिर्फ एक 32 या 64% मूल्य है। तो OCaml चलाने का समय यह निर्धारित करने के लिए टैग बिट की जाँच करता है कि उसे क्या प्राप्त हुआ था एक पूर्णांक या एक सूचक। यदि टैग बिट सेट है, तो मान एक पूर्णांक है और इसे सही अधिभार के लिए पारित किया गया है। अन्यथा यह एक पॉइंटर है और इसके प्रकार को देखा जाता है।

केवल पूर्णांकों के पास यह टैग क्यों है? क्योंकि बाकी सब कुछ एक पॉइंटर के रूप में पास किया जाता है। जो पास किया गया है वह या तो एक पूर्णांक या कुछ अन्य डेटा प्रकार के लिए एक संकेतक है। केवल एक टैग बिट के साथ, केवल दो मामले हो सकते हैं।


1
"संक्षिप्त उत्तर यह है कि यह प्रदर्शन के लिए है"। विशेष रूप से Coq का प्रदर्शन। लगभग सभी चीजों का प्रदर्शन इस डिजाइन निर्णय से ग्रस्त है।
जद

17

यह वास्तव में "कचरा संग्रहण के लिए उपयोग नहीं किया जाता है।" इसका उपयोग आंतरिक रूप से एक सूचक और एक अनबॉक्स किए गए पूर्णांक के बीच अंतर करने के लिए किया जाता है।


2
और वह करने के लिए परिणाम यह है कि है कम से कम एक अन्य प्रकार, अर्थात् संकेत के लिए उस तरह। यदि फ्लोट्स भी 31 बिट्स नहीं हैं, तो मुझे लगता है क्योंकि वे ढेर पर वस्तुओं के रूप में संग्रहीत होते हैं, और संकेत के साथ संदर्भित होते हैं। मुझे लगता है कि उनमें से सरणियों के लिए एक कॉम्पैक्ट रूप है, यद्यपि।
टॉम एंडरसन

2
यह जानकारी ठीक है कि जीसी को पॉइंटर ग्राफ को नेविगेट करने की आवश्यकता है।
तोबू

"इसका उपयोग आंतरिक रूप से एक सूचक और एक अनबॉक्स किए गए पूर्णांक के बीच अंतर करने के लिए किया जाता है"। क्या जीसी के अलावा कोई और इसका उपयोग करता है?
JD

13

मुझे 64-बिट OCaml के लिए 63-बिट फ़्लोटिंग-पॉइंट प्रकार को समझने के लिए ओपी की मदद करने के लिए इस लिंक को जोड़ना होगा

यद्यपि लेख का शीर्षक floatइसके बारे में लगता है , यह वास्तव में बात कर रहा हैextra 1 bit

OCaml रनटाइम प्रकार के समान प्रतिनिधित्व के माध्यम से बहुरूपता की अनुमति देता है। प्रत्येक OCaml मान को एक एकल शब्द के रूप में दर्शाया जाता है, ताकि "चीजों की सूची", जैसे कि (जैसे List.length) को एक्सेस करने और इन सूचियों को बनाने (जैसे List.map) का निर्माण करने के लिए एक ही कार्यान्वयन के लिए संभव हो, यह वही काम करता है, चाहे वे किलों की सूची, फ़्लोट्स की, या पूर्णांकों के सेटों की सूचियाँ हों।

जो कुछ भी एक शब्द में फिट नहीं होता है वह ढेर में एक ब्लॉक में आवंटित किया जाता है। इस डेटा का प्रतिनिधित्व करने वाला शब्द तब ब्लॉक का एक संकेतक है। चूंकि ढेर में केवल शब्दों के ब्लॉक होते हैं, इन सभी बिंदुओं को संरेखित किया जाता है: उनके कम से कम महत्वपूर्ण बिट्स हमेशा परेशान होते हैं।

तर्कहीन निर्माणकर्ता (इस तरह: प्रकार फल = सेब | नारंगी | केला) और पूर्णांक इतनी जानकारी का प्रतिनिधित्व नहीं करते हैं कि उन्हें ढेर में आवंटित करने की आवश्यकता है। उनका प्रतिनिधित्व अनबॉक्स है। डेटा सीधे शब्द के अंदर होता है जो अन्यथा एक संकेतक होता। इसलिए जबकि सूचियों की एक सूची वास्तव में संकेतकर्ताओं की सूची है, सूची की सूची में एक कम अप्रत्यक्षता के साथ ints शामिल हैं। सूचियों तक पहुँचने और निर्माण करने वाले कार्यों पर ध्यान नहीं जाता है क्योंकि इन्ट्स और पॉइंटर्स का आकार समान होता है।

फिर भी, गारबेज कलेक्टर को पूर्णांक से संकेत पहचानने में सक्षम होना चाहिए। एक सूचक ढेर में एक अच्छी तरह से गठित ब्लॉक को इंगित करता है जो कि परिभाषा के अनुसार है (क्योंकि यह जीसी द्वारा दौरा किया जा रहा है) और इसे चिह्नित किया जाना चाहिए। एक पूर्णांक का कोई भी मूल्य हो सकता है और अगर सावधानी नहीं बरती गई, तो गलती से एक पॉइंटर की तरह दिख सकता है। यह जिंदा दिखने के लिए मृत ब्लॉक का कारण बन सकता है, लेकिन इससे भी बदतर, यह जीसी को बिट्स को बदलने का कारण होगा, जो इसे लगता है कि लाइव ब्लॉक का हेडर है, जब यह वास्तव में एक पूर्णांक का अनुसरण कर रहा है जो एक संकेतक की तरह दिखता है और उपयोगकर्ता को गड़बड़ कर रहा है। डेटा।

यही कारण है कि अनबॉक्सेड पूर्णांक OCaml प्रोग्रामर को 31 बिट्स (32-बिट OCaml के लिए) या 63 बिट्स (64-बिट OCaml के लिए) प्रदान करते हैं। प्रतिनिधित्व में, पर्दे के पीछे, पूर्णांक वाले किसी शब्द का कम से कम महत्वपूर्ण बिट हमेशा एक सूचक से अलग करने के लिए निर्धारित होता है। 31- या 63-बिट पूर्णांक बल्कि असामान्य हैं, इसलिए जो कोई भी OCaml का उपयोग करता है वह यह सब जानता है। OCaml के उपयोगकर्ताओं को आमतौर पर पता नहीं होता है कि 64-बिट OCaml के लिए 63-बिट अनबॉक्स फ्लोट प्रकार क्यों नहीं है।


3

OCaml में केवल 31 बिट्स में इंट क्यों है?

मूल रूप से, कोक प्रमेय प्रोवर पर सर्वश्रेष्ठ संभव प्रदर्शन प्राप्त करने के लिए जहां प्रमुख ऑपरेशन पैटर्न मिलान है और प्रमुख डेटा प्रकार भिन्न प्रकार हैं। सर्वश्रेष्ठ डेटा प्रतिनिधित्व को एक समान प्रतिनिधित्व के रूप में पाया गया था जो अनबॉक्स किए गए डेटा से पॉइंटर्स को अलग करने के लिए टैग का उपयोग करता है।

लेकिन ऐसा क्यों है कि केवल किलों के लिए और अन्य बुनियादी प्रकारों के लिए नहीं?

ही नहीं int। अन्य प्रकार जैसे कि charऔर enums समान टैग किए गए प्रतिनिधित्व का उपयोग करते हैं।

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