अगर रजिस्टर इतनी तेजी से धधक रहे हैं, तो हमारे पास उनमें से अधिक क्यों नहीं है?


88

32 बिट में, हमारे पास 8 "सामान्य उद्देश्य" रजिस्टर थे। 64 बिट के साथ, राशि दोगुनी हो जाती है, लेकिन यह 64 बिट के परिवर्तन से स्वतंत्र लगता है।
अब, यदि रजिस्टर इतना तेज़ है (मेमोरी एक्सेस नहीं है), तो स्वाभाविक रूप से उनमें से अधिक क्यों नहीं हैं? सीपीयू बिल्डरों को सीपीयू में अधिक से अधिक रजिस्टरों के रूप में काम नहीं करना चाहिए? तार्किक प्रतिबंध क्या है कि हमारे पास केवल राशि है जो हमारे पास है?


सीपीयू और जीपीयू मुख्य रूप से क्रमशः कैश और बड़े पैमाने पर मल्टीथ्रेडिंग द्वारा विलंबता को छिपाते हैं। इसलिए, सीपीयू के पास कुछ रजिस्टर होते हैं (या आवश्यकता होती है), जबकि जीपीयू में दसियों हजारों रजिस्टर होते हैं। GPU रजिस्टर फाइल पर मेरा सर्वे पेपर देखें जिसमें इन सभी ट्रेड-ऑफ और कारकों पर चर्चा की गई है।
user984260

जवाबों:


119

कई कारण हैं जो आपके पास बहुत बड़ी संख्या में रजिस्टर नहीं हैं:

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

इन दिनों हमारे पास बहुत सारे रजिस्टर हैं - वे केवल स्पष्ट रूप से क्रमादेशित नहीं हैं। हमारे पास "रजिस्टर नामकरण" है। जब आप केवल एक छोटे से सेट (8-32 रजिस्टर) का उपयोग करते हैं, तो वे वास्तव में बहुत बड़े सेट (जैसे 64-256) द्वारा समर्थित होते हैं। सीपीयू तब प्रत्येक रजिस्टर की दृश्यता को ट्रैक करता है, और उन्हें नामांकित सेट के लिए आवंटित करता है। उदाहरण के लिए, आप लोड कर सकते हैं, संशोधित कर सकते हैं, फिर एक पंक्ति में कई बार रजिस्टर में स्टोर कर सकते हैं, और इनमें से प्रत्येक ऑपरेशन वास्तव में एआरएम में कैश मिस आदि के आधार पर स्वतंत्र रूप से किया जाता है:

ldr r0, [r4]
add r0, r0, #1
str r0, [r4]
ldr r0, [r5]
add r0, r0, #1
str r0, [r5]

कॉर्टेक्स ए 9 कोर का नाम बदलकर रजिस्टर होता है, इसलिए "r0" का पहला लोड वास्तव में एक नामांकित वर्चुअल रजिस्टर पर जाता है - चलो इसे "v0" कहते हैं। लोड, इंक्रीमेंट और स्टोर "v0" पर होता है। इस बीच, हम r0 को फिर से लोड / संशोधित / स्टोर करते हैं, लेकिन इसका नाम बदलकर "v1" हो जाएगा क्योंकि यह r0 का उपयोग करके एक पूरी तरह से स्वतंत्र अनुक्रम है। मान लें कि "r4" में पॉइंटर से लोड कैश मिस के कारण रुका हुआ है। यह ठीक है - हमें तैयार होने के लिए "r0" की प्रतीक्षा करने की आवश्यकता नहीं है। क्योंकि इसका नाम बदल दिया गया है, इसलिए हम अगले अनुक्रम को "v1" (आरएपी के लिए मैप किया गया) के साथ चला सकते हैं - और शायद यह एक कैश हिट है और हमारे पास सिर्फ एक बड़ी प्रदर्शन जीत थी।

ldr v0, [v2]
add v0, v0, #1
str v0, [v2]
ldr v1, [v3]
add v1, v1, #1
str v1, [v3]

मुझे लगता है कि x86 इन दिनों नामांकित रजिस्टरों की एक विशाल संख्या तक है (बॉलपार्क 256)। इसका मतलब यह होगा कि हर निर्देश के लिए 8 बिट्स 2 है, केवल यह कहने के लिए कि स्रोत और गंतव्य क्या है। यह बड़े पैमाने पर कोर और उसके आकार के लिए आवश्यक तारों की संख्या में वृद्धि करेगा। तो लगभग 16-32 रजिस्टरों का एक मीठा स्थान है जो अधिकांश डिजाइनरों ने सीपीयू डिजाइन के लिए और आउट-ऑफ-ऑर्डर ऑर्डर के लिए तय किया है, रजिस्टर का नामकरण इसे कम करने का तरीका है।

संपादित करें : इस पर आउट-ऑफ-ऑर्डर निष्पादन और पंजीकरण का महत्व। एक बार जब आपके पास OOO होता है, तो रजिस्टरों की संख्या इतनी अधिक नहीं होती है, क्योंकि वे सिर्फ "अस्थायी टैग" होते हैं और बहुत बड़े वर्चुअल रजिस्टर सेट का नाम बदल जाते हैं। आप नहीं चाहते कि संख्या बहुत कम हो, क्योंकि छोटे कोड अनुक्रम लिखना मुश्किल हो जाता है। यह x86-32 के लिए एक समस्या है, क्योंकि सीमित 8 रजिस्टरों का अर्थ है ढेर सारी अस्थायीियां स्टैक के माध्यम से जा रही हैं, और कोर को पढ़ने के लिए अतिरिक्त तर्क की आवश्यकता होती है / मेमोरी में लिखते हैं। यदि आपके पास OOO नहीं है, तो आप आमतौर पर एक छोटे कोर के बारे में बात कर रहे हैं, जिस स्थिति में एक बड़ा रजिस्टर सेट खराब लागत / प्रदर्शन लाभ है।

तो रजिस्टर बैंक के आकार के लिए एक प्राकृतिक मीठा स्थान है जो सीपीयू के अधिकांश वर्गों के लिए लगभग 32 वास्तुकला वाले रजिस्टरों में अधिकतम होता है। x86-32 में 8 रजिस्टर हैं और यह निश्चित रूप से बहुत छोटा है। एआरएम 16 रजिस्टरों के साथ गया और यह एक अच्छा समझौता है। 32 रजिस्टरों से बहुत अधिक है अगर कुछ भी - आप अंतिम 10 या तो की जरूरत नहीं है।

इसमें से कोई भी आपको एसएसई और अन्य वेक्टर फ़्लोटिंग पॉइंट कोप्रोसेसर्स के लिए प्राप्त अतिरिक्त रजिस्टरों पर नहीं छूता है। वे अतिरिक्त सेट के रूप में समझ में आते हैं क्योंकि वे पूर्णांक कोर के स्वतंत्र रूप से चलते हैं, और सीपीयू की जटिलता को तेजी से नहीं बढ़ाते हैं।


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

7
@WillA अच्छी बात है। हालांकि, बहुत सारे रजिस्टरों वाले आर्किटेक्चर के पास इस लागत को कम करने के तरीके हैं। एबीआई में आमतौर पर अधिकांश रजिस्टरों के कैली-सेव होंगे, इसलिए आपको केवल एक कोर सेट को बचाना होगा। संदर्भ स्विचिंग आमतौर पर पर्याप्त महंगी है कि अतिरिक्त बचत / पुनर्स्थापना में अन्य सभी लाल टेप की तुलना में बहुत अधिक खर्च नहीं होता है। स्पार्क वास्तव में एक मेमोरी क्षेत्र पर रजिस्टर बैंक को एक "विंडो" बनाकर इसके चारों ओर काम करता है, इसलिए यह कुछ हद तक इस तरह से हाथ में जाता है (उस तरह का हाथ लहराता है)।
जॉन रिप्ले

4
इस तरह के उत्तर से मेरे मन को उड़ने पर विचार करें, जिसकी मुझे उम्मीद नहीं थी। इसके अलावा, इस स्पष्टीकरण के लिए धन्यवाद कि हमें वास्तव में बहुत सारे नामित रजिस्टरों की आवश्यकता क्यों नहीं है, यह बहुत दिलचस्प है! मुझे वास्तव में आपके उत्तर को पढ़ने में बहुत मज़ा आया, क्योंकि मुझे "हुड के नीचे" पर जाने में पूरी तरह से दिलचस्पी है। :) मैं एक उत्तर को स्वीकार करने से पहले थोड़ा इंतजार करने वाला हूं, क्योंकि आप कभी नहीं जानते, लेकिन मेरा +1 निश्चित है।
Xeo

1
भले ही रजिस्टरों को बचाने की जिम्मेदारी प्रशासनिक ओवरहेड पर पड़े। ठीक है इसलिए संदर्भ स्विचिंग सबसे अधिक बार होने वाला मामला नहीं हो सकता है, लेकिन व्यवधान हैं। हैंड-कोडेड रूटीन रजिस्टरों पर इकोनॉमी कर सकते हैं, लेकिन अगर ड्राइवरों को सी चांस में लिखा गया है, तो रुकावट घोषित फ़ंक्शन हर एक रजिस्टर को बचाएगा, आईएसआर को कॉल करेगा और फिर सभी सेव किए गए रजिस्टरों को पुनर्स्थापित करेगा। आईए -32 को आरआईएससी आर्किटेक्चर के 32 + कुछ रीजन्स की तुलना में अपने 15-20 रेज के साथ एक बाधा लाभ था।
ओलफ फोर्शेल

1
उत्कृष्ट उत्तर, लेकिन मैं "वास्तविक" प्रशंसनीय लोगों के साथ "पुनर्नामित" रजिस्टरों की प्रत्यक्ष तुलना से असहमत हूं। X86-32 पर, 256 आंतरिक रजिस्टरों के साथ भी आप निष्पादन के किसी एक बिंदु में रजिस्टरों में संग्रहीत 8 से अधिक अस्थायी मूल्यों का उपयोग नहीं कर सकते। मूल रूप से, नाम बदलना केवल OOE का एक उत्सुक उपोत्पाद है, इससे अधिक कुछ नहीं।
दोपहर सिप

12

वी डू हैव मोर देम ऑफ देम

क्योंकि लगभग हर निर्देश में 1, 2, या 3 आर्किटेक्चरली दिखने वाले रजिस्टरों का चयन करना चाहिए, उनकी संख्या का विस्तार करने से प्रत्येक निर्देश पर कई बिट्स द्वारा कोड आकार में वृद्धि होगी और इसलिए कोड घनत्व कम होगा। यह संदर्भ की मात्रा को भी बढ़ाता है जिसे थ्रेड स्थिति के रूप में सहेजा जाना चाहिए, और आंशिक रूप से फ़ंक्शन के सक्रियण रिकॉर्ड में सहेजा जाना चाहिए ये ऑपरेशन अक्सर होते हैं। पाइपलाइन इंटरलॉक को प्रत्येक रजिस्टर के लिए एक स्कोरबोर्ड की जांच करनी चाहिए और इसमें द्विघात समय और स्थान की जटिलता है। और शायद सबसे बड़ा कारण केवल पहले से परिभाषित निर्देश सेट के साथ संगतता है।

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

उदाहरण:

load  r1, a  # x = a
store r1, x
load  r1, b  # y = b
store r1, y

एक आर्किटेक्चर जिसमें केवल r0-r7 है, निम्न कोड को CPU द्वारा स्वचालित रूप से कुछ इस तरह से लिखा जा सकता है:

load  r1, a
store r1, x
load  r10, b
store r10, y

इस स्थिति में r10 एक छिपा हुआ रजिस्टर है जिसे अस्थायी रूप से r1 के लिए प्रतिस्थापित किया जाता है। CPU बता सकता है कि पहले स्टोर के बाद r1 के मूल्य का फिर से उपयोग नहीं किया जाता है। यह दूसरे लोड की देरी या दूसरे स्टोर की आवश्यकता के बिना पहले लोड को विलंबित करने की अनुमति देता है (यहां तक ​​कि ऑन-चिप कैश हिट आमतौर पर कई चक्र लेता है)।


2

वे सभी समय में रजिस्टरों को जोड़ते हैं, लेकिन वे अक्सर विशेष उद्देश्य निर्देशों (जैसे SIMD, SSE2, आदि) से बंधे होते हैं या एक विशिष्ट CPU आर्किटेक्चर के संकलन की आवश्यकता होती है, जो पोर्टेबिलिटी को कम करता है। मौजूदा निर्देश अक्सर विशिष्ट रजिस्टरों पर काम करते हैं और यदि वे उपलब्ध थे तो अन्य रजिस्टरों का लाभ नहीं उठा सकते हैं। विरासत निर्देश सेट और सभी।


1

यहां थोड़ी दिलचस्प जानकारी जोड़ने के लिए, आप देखेंगे कि 8 समान आकार वाले रजिस्टरों में हेक्साडेसिमल संकेतन के साथ स्थिरता बनाए रखने की अनुमति मिलती है। उदाहरण के लिए निर्देश push axx86 पर opcode 0x50 है और अंतिम रजिस्टर di के लिए 0x57 तक जाता है। फिर निर्देश pop ax0x58 से शुरू होता है और pop diपहला बेस -16 पूरा करने के लिए 0x5F तक जाता है । हेक्साडेसिमल की स्थिरता प्रति आकार 8 रजिस्टरों के साथ बनाए रखी जाती है।


2
X86 / 64 पर REX निर्देश उपसर्ग अधिक बिट्स के साथ रजिस्टर इंडेक्स का विस्तार करते हैं।
अलेक्सी फ्रुंज़े
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.