1 पॉइंट द्वारा GN⁺ 2024-07-28 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • AMD Zen 5 ने Zen आर्किटेक्चर के पूरी तरह पुनःडिज़ाइन के तहत 2-Ahead Branch Predictor पेश किया है, जो 1990 के दशक के multi-block ahead branch prediction शोध को आधुनिक x86 फ्रंटएंड विस्तार में फिर से लेकर आता है
  • branch prediction वह तंत्र है जो CPU फ्रंटएंड को conditional branch का परिणाम आने से पहले भी instruction लाना जारी रखने देता है, और prediction विफल होने पर pipeline flush तथा restart cost चुकानी पड़ती है
  • Zen 5 में 32KB L1 instruction cache से 32 bytes/cycle fetch pipe 2 हैं, और हर एक अपने 4-wide decode cluster से जुड़ा है; Op Cache भी dual-ported 6-wide संरचना वाला है, जो Op Queue को अधिकतम 12 operand दे सकता है
  • नई संरचना एक cycle में 2 taken branch को असतत instruction block पर संभालती है, और 5-bit length field के जरिए तीसरी prediction window की शुरुआत ढूँढ़कर decode और Op Cache संसाधनों के अत्यधिक उपयोग को कम करती है
  • x86 में variable-length instruction होने की वजह से instruction boundary पहचान को parallel करना मुश्किल है, इसलिए 2-Ahead Branch Predictor और dual fetch·decode संरचना Zen श्रृंखला के फ्रंटएंड विस्तार का मुख्य बदलाव बन जाते हैं

Zen 5 फ्रंटएंड में क्या बदला

  • AMD ने Zen 5 को Zen आर्किटेक्चर का पूरी तरह पुनःडिज़ाइन कहा है, और 2-Ahead Branch Predictor इस बदलाव का सबसे ध्यान खींचने वाला हिस्सा है
  • यह संरचना 30 साल पुराने शोधपत्रों में चर्चा किए गए विचारों पर आधारित है, और single-core performance को और बढ़ाने की कोशिशों के बीच फिर से सामने आई है
  • कई taken branch को एक साथ predict करने से फ्रंटएंड पहले से अधिक दूर के instruction stream तक देख सकता है

CPU pipeline में branch prediction की ज़रूरत क्यों होती है

  • आधुनिक CPU instruction fetch, decode और execution को कई चरणों में बाँटने वाली pipeline संरचना का उपयोग करते हैं
  • जब conditional branch आती है, तो फ्रंटएंड को condition evaluation पूरी होने से पहले तय करना पड़ता है कि अगला instruction कहाँ से लाना है
  • मोटे तौर पर दो विकल्प होते हैं
    • branch result आने तक रुक जाना
    • अगला path predict करना, और गलत होने पर गलत काम को हटाकर सही बिंदु से फिर शुरू करना
  • prediction गलत होने पर उस अनुमान पर आधारित काम को pipeline से हटाने के लिए flush की ज़रूरत होती है
  • branch condition पर रुकने की लागत instruction fetch और branch condition evaluation पूरा होने के बीच pipeline stages की संख्या के अनुपात में बढ़ती है
  • अंततः CPU को प्रोग्राम के instruction flow का जितना संभव हो उतना सटीक अनुमान लगाना होता है

2-Ahead विचार किस संदर्भ में आया

  • सरल prediction तरीकों में short backward jump को हमेशा taken मानने की रणनीति थी, और यह हमेशा अगला address लाने वाले तरीके की तुलना में ऐतिहासिक रूप से बड़ा लाभ देती थी
  • हाल का branch history या address record जैसी छोटी state बनाए रखने से वास्तविक प्रोग्रामों में बेहतर परिणाम मिल सकते थे
  • केवल कुछ दर्जन KB के ढाँचे से भी 90% के ऊपरी स्तर की branch prediction accuracy संभव थी
  • 2-Ahead Branch Predictor पर 1990 के दशक की शुरुआत से चर्चा होती रही, और उस समय 8-wide या उससे अधिक आर्किटेक्चरल width बढ़ाने की समस्या भी साथ उठी थी
  • बाद में commercial CPU के multicore की ओर बढ़ने से प्रति-core area अधिक महत्वपूर्ण हो गया, और academia ने अधिक area-efficient TAGE predictor सुधारों पर ध्यान केंद्रित किया
  • process shrink के कारण समान area में अधिक transistor रख पाना संभव हुआ, और सैकड़ों out-of-order CPU तक विस्तार की प्रवृत्ति के साथ single-core performance में रुचि फिर बढ़ी

x86 फ्रंटएंड अधिक कठिन क्यों है

  • 64-bit Arm जैसे fixed-length instruction वाले ISA में instruction cache line के मनचाहे हिस्सों को parallel decode करना आसान होता है
    • input data को सुनिश्चित instruction byte boundary पर बाँटकर decoder logic की प्रतिकृति बनानी होती है
  • x86 में instruction length variable होती है, इसलिए हर instruction की अगली boundary जानने के लिए instruction byte को रैखिक रूप से parse करना पड़ता है
  • prefix को पहले आंशिक decode करने जैसी pipelining से कुछ हद तक parallelism मिल सकता है, लेकिन x86 में इसकी लागत कम नहीं है
  • performance-oriented x86 core में लंबे समय तक 4-wide decode आम रहने की एक वजह यही थी
  • Intel Golden Cove के 6-wide decode जैसे डिज़ाइन आधुनिक process में logic density बढ़ने के कारण commercial रूप से संभव हुए, लेकिन monolithic parallel x86 decoding की area और power लागत width बढ़ने के साथ super-linear रूप से बढ़ती है
  • सामान्य application integer code में लगभग हर 5~6 instruction पर 1 branch जैसी branch density होती है, इसलिए decoder width को बहुत अधिक बढ़ाने की प्रेरणा कम हो जाती है
  • x86 फ्रंटएंड को instruction boundary पहचान जैसे कठिन parallelizable चरण को पार करके सुरक्षित रूप से अगली instruction boundary तक पहुँचने का तरीका चाहिए

Zen 5 का dual fetch·decode implementation

  • “Multiple-block ahead branch predictors” by Seznec et al. 2-Ahead Branch Predictor के कारण और implementation तरीके पर एक प्रमुख शोधपत्र है
  • कई taken branch सँभालने वाला predictor अकेले काफी नहीं है; Seznec et al. का मानना था कि area requirement को विस्फोटक रूप से बढ़ाए बिना इसका उपयोग करने के लिए instruction fetch dual-porting ज़रूरी है
  • Zen 5 ने instruction fetch और Op Cache को dual-port संरचना में बदला है
    • 32KB L1 instruction cache से 32 bytes/cycle fetch pipe 2 का उपयोग किया जाता है
    • हर fetch pipe अपने 4-wide decode cluster से जुड़ा है
    • Op Cache dual-ported 6-wide डिज़ाइन है, और Op Queue को अधिकतम 12 operand दे सकता है
  • Branch Target Buffer भी dual-porting में शामिल है
    • Zen 5 के L1 BTB का 16K entries जैसा बड़ा आकार dual-ported L1 BTB की संभावना समझा सकता है
    • L2 BTB 8K entries का है, जो L1 BTB से छोटा है
    • AMD, L2 BTB को victim cache जैसी भूमिका में उपयोग करता है, जहाँ L1 BTB से evict हुई entry L2 BTB में चली जाती है

एक cycle में 2 taken branch सँभालने का तरीका

  • Zen 5 असतत instruction block के पार एक cycle में 2 taken branch सँभाल सकता है
  • यह बदलाव taken branch मिलने पर fetch bandwidth loss को घटाता है और दो taken branch के आगे तक prediction करने देता है
  • दूसरे taken branch के बाद के instruction stream को और दूर तक देखा जा सकता है, इसलिए तीन prediction window हो सकती हैं
  • इन तीनों prediction window का उपयोग decode के लिए instruction तैयार करने में किया जा सकता है
  • दूसरी prediction window में 5-bit length field जुड़ी होती है
    • यह decode या Op Cache संसाधनों के over-reservation को रोकती है
    • यह pointer से छोटी होते हुए भी तीसरी prediction window की शुरुआत बताती है
    • जब तीसरी prediction window cache line boundary पार करती है, तब अगले cycle के prediction lookup index के लिए अतिरिक्त state रखने की ज़रूरत नहीं पड़ती
    • अगर तीसरी prediction window पहली या दूसरी prediction window के साथ उसी cache line में हो, तो वह partial third window पूरी तीसरी prediction window जितनी प्रभावी नहीं होती

SMT में बची हुई सीमाएँ

  • Zen 5 में जब दो thread सक्रिय होते हैं, तो decode cluster के साथ जुड़े fetch pipe statically partition हो जाते हैं
  • इस स्थिति में dual fetch core की तरह काम करने के लिए L1 instruction cache और Op Cache दोनों से fetch करना पड़ता है
  • AMD ने Op Cache को dual-port बनाया, इसकी एक वजह dual fetch pipeline को बेहतर बनाए रखना हो सकती है

साथ में उल्लेखित संबंधित शोधपत्र

1 टिप्पणियां

 
GN⁺ 2024-07-28
Hacker News की राय
  • branch prediction को शुरुआती implementations से लेकर अच्छी तरह समझाने के लिए https://danluu.com/branch-prediction/ अच्छा है

  • जिज्ञासा है कि SMT performance कैसी निकलेगी, और उम्मीद है कि यह approach फायदा देगी और अगली generation में और refined होगी
    Zen5c 192 cores या 384 vCPU तक जाता है, और अगले साल Zen 6c में शायद 256 cores संभव हो जाएं। dual-socket 1U server में संभावित रूप से 512 cores, 1024 vCPU हो सकते हैं
    2014 में जिन web app scaling समस्याओं से जूझना पड़ता था, वे अब cooling हो जाए तो एक server में समा सकती हैं। vCPU प्रति सिर्फ 1 RPS मानें तो cache hits को छोड़कर भी 1000 RPS है, जबकि HN frontpage भी server पर प्रति सेकंड 1000 pageviews नहीं ठोकता

    • webpage serve करना सस्ता काम है, इसलिए cores saturate होने से पहले network I/O limit पर पहुंचने की संभावना ज्यादा है
      HPC performance कैसी होगी, यह जानने की उत्सुकता है। cooling खुद शायद बड़ी समस्या न हो, लेकिन किसी point के बाद यह direct liquid cooling (DLC) की जरूरत वाला गीला मामला बन सकता है
    • जैसे computing 1940s में kilobyte युग में दाखिल हुई थी, वैसे अब हम kilocore युग में दाखिल हो रहे हैं
      GPU लगे घने server rack को अगर एक machine माना जाए, तो हम पहले ही सैकड़ों kilocores तक पहुंच चुके हैं
      एक बार किसी ऐसे व्यक्ति से बहस हुई थी जो यह concept नहीं समझ पा रहा था कि Wikipedia-scale की service एक ही server से दी जा सकती है; काफी मजेदार था। यह काफी समय से आसान काम रहा है, बस availability या cost efficiency जैसे व्यावहारिक कारणों से ऐसा नहीं किया जाता
    • उल्टा भी हो सकता है। CPU pipeline का जितना बेहतर इस्तेमाल होगा, second thread फिट करने की गुंजाइश उतनी कम होगी, इसलिए SMT benefit छोटा हो सकता है
    • SMT के लिए कहीं ज्यादा benchmark validation की जरूरत है
      intuitively लगता है कि एक ही समस्या को आधी speed पर process करने वाले workloads बढ़ें तो memory usage की लागत होनी चाहिए, लेकिन जिज्ञासा है कि क्या ऐसे apps आम हैं जो SMT on करने पर speed gain के बिना सिर्फ ज्यादा memory इस्तेमाल करते हैं
      published benchmarks में से काफी में ऐसा दिखता है कि ज्यादातर apps को execution speed में कोई खास फायदा नहीं मिलता
    • web app scaling की समस्याएं आम तौर पर database latency के आसपास पैदा होती हैं
  • यह देखना हमेशा दिलचस्प होता है कि दशकों पुराने papers, जो उस समय ज्यादा ध्यान खींचे बिना publish हुए थे, hardware पर्याप्त मजबूत होने पर अचानक state-of-the-art बन जाते हैं
    उदाहरण के लिए Z-buffer है। यह 3D videogames में इस्तेमाल होता है, लेकिन जब यह पहली बार paper में आया था तो main topic नहीं था; बहुत ज्यादा memory चाहिए, इस वजह से इसे side note जैसा माना गया था
    कई दशकों बाद megabytes काफी सस्ते हो गए, और आखिरकार सभी real-time 3D renderers ने इसे इस्तेमाल करना शुरू कर दिया

    • एक और उदाहरण low-density parity-check code है। Robert Gallager ने इसे 1962 में खोजा था, लेकिन computationally अव्यावहारिक होने की वजह से यह दशकों तक छोड़ दिया गया और भुला दिया गया
      David MacKay द्वारा rediscover किए जाने से पहले literature में शायद करीब 38 साल का gap था
      पहला mainstream उपयोग 2003 में हुआ, और अब यह WiFi, Ethernet, 5G में इस्तेमाल होता है
      [1] https://en.wikipedia.org/wiki/Low-density_parity-check_code
      [2] https://scholar.google.com/scholar?q=%22low+density+parity+c...
    • कभी-कभी सोचता हूं कि engineers के लिए ऐसी कोई छिपी हुई academic career वाली राह तो नहीं है
      library जाकर computer science researchers ने जब paper में publish किया था उन चीजों को पढ़ें, तो शायद ऐसे ideas मिल जाएं जो उस समय अव्यावहारिक थे लेकिन अब implement किए जा सकते हैं
    • मुझे लगता है कि यह hardware मजबूत होने से संभव हुआ, ऐसा कम है; बल्कि ऐसी designs दशकों पहले से संभव थीं, लेकिन आज के trade-off combination में ही attractive बनी हैं
      पिछले 20 वर्षों में single-core performance को horizontal scaling, यानी ज्यादा cores को प्राथमिकता देने के कारण दबाया गया, इसलिए individual core की complexity और die area समस्या बन गए। अगर यह trend न होता और CPU designers मुख्य रूप से single-core performance को pursue करते, तो शायद हमें बहुत पहले implementation दिख गया होता
      Z-buffer एक simple concept है, इसलिए paper में side note जैसा दिखा होगा। बेहतर example शायद ray tracing हो सकता है। 3D graphics background न हो तब भी concept खुद काफी स्पष्ट है, लेकिन हाल तक real-time rendering के लिए performance के लिहाज से अव्यावहारिक था
      दिलचस्प बात यह है कि असल जैसा rendering approximate करने के लिए कोई simpler approach नहीं मिल पाया, और हमें पुराने, कुछ हद तक naive और महंगे solution पर लौटना पड़ रहा है
    • एक और उदाहरण Rust का borrow checker है, जिसकी जड़ें दशकों पुराने substructural type system papers में हैं
      कई academics मानते थे कि substructural type system को effectively garbage collection ने खत्म कर दिया है, लेकिन Rust ने उसे उस समय C++ के नए ideas के साथ जोड़कर फिर जिंदा कर दिया
    • Z-buffer को सिर्फ एक frame buffer जितनी extra memory ही नहीं चाहिए, बल्कि हर pixel के लिए काफी read/write bandwidth भी चाहिए
      इसी extra memory bandwidth requirement ने इसे ठीक से implement करना मुश्किल और महंगा बनाया। high-end implementations dedicated RAM channels इस्तेमाल करते थे, लेकिन low-cost hardware में यह shared memory interface की काफी bandwidth खा जाता था
      उदाहरण के लिए कुछ N64 games ने depth information पढ़ने और update करने की लागत से बचने के लिए Z-buffer बंद कर दिया और background/foreground drawing को software में manage करके optimize किया
  • speculative predictor निजी डेटा निकालने के लिए कई हमलों का target रहा है
    अगर आम ISA का बड़ा हिस्सा vulnerable है, तो उत्सुकता है कि क्या ऐसे हमलों के असर को कम करने के लिए कदम उठाए जा रहे हैं

    • vulnerability branch prediction नहीं, बल्कि speculative execution है। branch predictor सिर्फ वह target है जिसे trick करके victim program में processor से code को speculatively execute कराना होता है। ऊपर से speculative execution के result को पढ़ने के लिए एक valid timing source भी चाहिए
      इसे रोकने का कोई तरीका नहीं है, समुद्र उबालने जैसे approach[0] को छोड़कर। speculative execution performance के लिए इतना valuable है कि इसके बिना computer लगभग पूरी तरह बेकार हो जाएगा। अगर सच में speculative execution के बिना processor चाहिए, तो पुराना 1st-gen Pentium खरीद लें
      practical mitigations कई तरह की हैं, लेकिन कम से कम secrets रखने वाले victim process और victim execution को प्रभावित कर सकने वाले संभावित attacker के बीच process isolation सुनिश्चित करना होगा
      Intel ring boundaries के आर-पार speculative execution करते हुए पकड़ा गया था, इसलिए user space से kernel या hypervisor memory पढ़ी जा सकती थी। अगर CPU design खराब न हो, तो मुख्य चिंता का विषय HTML iframe होता है
      अलग-अलग origins मनमाने HTTP requests नहीं भेज सकते[1], लेकिन बिना अनुमति एक-दूसरे को include कर सकते हैं[2]। परंपरागत रूप से वह जानकारी attacker process में load होती थी और timing attack से leak हो सकती थी
      web का शुरुआती समाधान iframe को process-isolate करना नहीं था, बल्कि shared-memory multithreading को ही हटाना था। अगर attacker से timing reference छीन लें, तो victim चाहे जो speculatively execute करे, उसका महत्व कम हो जाता है। लेकिन इसके लिए multithreading हटानी पड़ती है। वरना एक thread known data को loop में बार-बार लिखकर clock बना सकता है
      [0] https://hackaday.com/2013/08/02/the-mill-cpu-architecture/
      [1] कम से कम तब तक असंभव है, जब तक target origin CORS से अनुमति न दे
      [2] उदाहरण: image hotlinking या iframe embed
    • speculative execution का virtual memory translation और cache के साथ interaction वाला बिंदु exploit किया जा सकता है
      यह prediction में inherent vulnerability नहीं है
  • इस क्षेत्र में beginner होने के नाते, article पढ़ने के बाद भी यह साफ नहीं है कि 2-ahead branch predictor आखिर है क्या

    • यह करीब 30 साल पुराना concept है, इसलिए लगता है कि यह 1996 के इस paper[0] की ओर इशारा कर रहा है। यह मेरी समझ से ऊपर की चीज है, लेकिन लगता है कि यह कई instruction units और high clock speeds से पैदा होने वाली branch prediction problem में मदद करता है
      90s में processors इनमें से किसी एक के करीब थे, लेकिन modern processors में शायद ज्यादातर दोनों होते हैं
      “Multiple-block ahead branch predictors” का abstract बताता है कि current instruction block की information को next instruction block address predict करने में नहीं, बल्कि उसके बाद वाले block को predict करने में इस्तेमाल किया जाता है। इससे wide-dispatch “brainiac” processors में instruction fetch bottleneck कम होता है और एक cycle में दो instruction block addresses को effectively predict किया जा सकता है
      साथ ही “speed demon” processors में branch prediction process को pipeline करके higher clocks या बड़े prediction structures के जरिए accuracy improvement मिल सकता है। मौजूदा multiple-predictor approach के उलट, multiple-block-ahead branch predictor कोई भी branch prediction method इस्तेमाल कर सकता है
      [0] https://dl.acm.org/doi/10.1145/237090.237169
      वैसे, लगता है eyegor ने पहले ही link डाल दिया है, लेकिन मतलब है कि abstract ही देख लें
    • मेरी समझ में यह next branch के target को नहीं, बल्कि उसके बाद वाली branch के target को predict करता है
      यह next branch prediction से कहीं ज्यादा मुश्किल होगा, लेकिन deeper pipeline को feed करने के लिए code बहुत पहले fetch करने देता है
    • beginner न हों तब भी उतना ही confusing है। article branch prediction की बहुत basics समझाने में काफी समय लगाता है, लेकिन जब 2-ahead पर आता है तो explanation skip कर देता है
    • लगता है यह एक cycle में 1 branch नहीं, बल्कि 2 branches predict करता है
      इसलिए सामान्य branch prediction की तरह सिर्फ n+1 को पहले से evaluate नहीं करता, बल्कि n+2 result तक पहले से evaluate कर सकता है। यह L1 cache को बिगाड़े बिना कैसे काम करता है, यह मुझे ठीक से समझ नहीं आ रहा
      अगर n+1 से आगे peek करने का तरीका है, तो cache eviction बहुत बढ़ना चाहिए, इसलिए लगता है कि मैं कुछ miss कर रहा हूँ
      कहा गया है कि Zen 5 दूसरे taken branch से आगे के instruction stream तक और दूर देख सकता है, और नतीजतन decode की जाने वाली instructions बनाने के लिए तीन useful prediction windows रख सकता है
      original paper public access में उपलब्ध है, लेकिन अभी ज्यादा पढ़ा नहीं है: https://dl.acm.org/doi/10.1145/237090.237169
    • सामान्य branch predictor branch, जैसे if-else, execute होने से पहले अनुमान लगाता है कि कौन-सा path लिया जाएगा। तब CPU instructions को पहले से fetch और decode कर सकता है
      branch की हर दिशा एक नए instruction block की शुरुआत की ओर ले जाती है, और ऐसे block की last instruction आम तौर पर एक और branch होती है
      यानी branch predictor वह device है जो next block का address सही guess करता है। 2-ahead branch predictor भी यही काम करता है, लेकिन आगे आने वाले दो blocks के लिए
      paper की भाषा में कहें तो “current instruction block की information का इस्तेमाल next instruction block के बाद आने वाले block के address को predict करने में किया जाता है”
      सामान्य branch predictor के उलट, यह next block की instructions decode होने तक इंतजार किए बिना हो सकता है। इसलिए यह multiple instruction decoders को simultaneously feed कर सकता है
      यह modern CPUs में खास तौर पर useful है, जहां instruction decoder bottleneck बन गया है। क्योंकि cycle में सिर्फ 1 instruction decode करने वाला एक decoder, cycle में 4~6 जैसी कई instructions execute कर सकने वाले wide frontend के साथ चलना मुश्किल पाता है
  • शायद और branch hints की जरूरत हो सकती है: https://github.com/ziglang/zig/issues/5177
    cold, warm, warmer रखकर hot को default मानकर omit करना संभव होगा क्या, ऐसा लगता है। कभी-कभी एक को छोड़कर सभी branches को cold के रूप में designate भी किया जा सकता है

  • शायद यह बुरा विचार होगा, लेकिन वजह जानना चाहता हूँ
    जब कोई conditional branch हो, तो दोनों संभावित branches के instructions को fetch और तैयार करके, गलत वाली side को फेंक क्यों नहीं दिया जा सकता—यह जानना चाहता हूँ
    क्या यह कहीं ज्यादा कठिन काम है, या कोई और वजह है जो इसे बेकार बना देती है?

    • वह second-best strategy है
      आधुनिक TAGE branch predictors 99% से भी ज्यादा सही होते हैं। इसलिए दूसरी side के अतिरिक्त instructions लगभग हमेशा फेंक दिए जाएंगे
      इससे भी खराब बात यह है कि frontend, backend में असली direction verify हो सकने वाली जगह से दर्जनों branches आगे तक fetch करता है। अगली branch पर क्या करेंगे? 4 संभावित branches decode करेंगे, फिर 8, 16, 32 decode करेंगे? इनमें से ज्यादातर फेंकने पड़ेंगे
      अगर आपके पास कई instruction streams को parallel में fetch करने वाला hardware है, जैसे Intel Gracemont/Goldmont/Skymont और AMD Zen 5 में, तो बेहतर strategy यह मानना है कि branch predictor 100% सही है। एक branch को follow करें, फिर उसके बाद वाली को भी
      Intel Skymont में 3 decoders हैं और हर एक 3-wide है, इसलिए वह अगली 3 branch targets को parallel में decode करता है। Intel बड़े code blocks को तोड़ने के लिए fake branches तक डालता है, ताकि तीनों decoders आने वाली instruction stream के अलग-अलग हिस्सों को हमेशा decode करते रहें। बाद में 3 micro-op streams को merge करके Skymont प्रति cycle 9 instructions की effective decode bandwidth बनाए रखता है
      दोनों branches execute करने से branch prediction गलत होने वाले दुर्लभ मामलों में latency थोड़ी घटती है। दूसरी ओर, एक ही direction में अगले दो-तीन predictions को लगातार follow करने से Intel और AMD कई decoders को parallel में काम करवा सकते हैं। Intel तीन सरल 3-wide decoders से 9-wide बना सकता है, और AMD दो सरल 4-wide decoders से 8-wide बना सकता है
    • जिन मामलों में branch का result random हो, वे दुर्लभ होते हैं
      compiler, runtime, CPU आदि अक्सर सही अंदाजा लगा सकते हैं कि कौन-सा result ज्यादा likely है, और शुरू से ही extra work न करना आम तौर पर बेहतर strategy है। यह गलत होने की स्थिति के लिए silicon और heat को गलत जवाब पर खर्च करने से बेहतर है
      लगता है बहुत लोगों को अंदाजा नहीं होता कि branch prediction कितनी accurate हो सकती है। अपने code को ही देखें तो जल्दी समझ आ जाता है कि “ज्यादातर control flow इस तरफ जाता है, और यह branch exceptional situation handle करने के लिए है”
      आजकल compilers भी इसे काफी अच्छी तरह infer कर लेते हैं, और CPU/JIT/runtime भी प्रभावशाली heuristics बना सकते हैं। फिर भी जब fail हो, तो code में explicit hints डालकर compiler वगैरह को expected direction बता सकते हैं
    • मैं इस field में काम नहीं करता, सिर्फ hobbyist हूँ, लेकिन लगता है branch predictors हमेशा इतने अच्छे रहे हैं कि दोनों sides करना value नहीं रखता था
      आधुनिक CPU का instruction reorder buffer सैकड़ों instructions deep होता है, और अगर उनमें सिर्फ 8 conditional jumps हों, तो program के संभावित paths 256 हो जाते हैं
      अगर branch predictor के उन सभी 8 को सही पकड़ने की probability 50% से ज्यादा है—और वास्तव में ऐसा ही है—तो तैयारी के लिए 256 गुना काम करना worthwhile नहीं है
    • इसे speculative execution कहा जाता है, और जहाँ तक याद है सभी आधुनिक CPU ऐसा करते हैं
      ज्यादा microarchitectural state रखने के लिए silicon चाहिए, और इस technique का पूरा फायदा उठाने के लिए ज्यादा execution units चाहिए। लेकिन superscalar CPUs के पास ये चीजें पहले से होती हैं, क्योंकि कम branches वाले code में instruction-level parallelism का लाभ उठाने के लिए ये जरूरी हैं
      बाकी aliases, interrupts जैसी जटिल चीजों को handle करने वाला सिरदर्द है, लेकिन hardware engineers जादूगर जैसे होते हैं, इसलिए यह भी कर लेते हैं
      हालांकि speculative execution cache timing side channels का फायदा उठाकर, ऐसे data से जानकारी निकालने की संभावना खोल देता है जिसे उस code ने touch किया हो जो केवल speculatively execute हुआ और जिसके architectural side effects commit नहीं हुए। यानी जो code “असल में” execute नहीं हुआ, उससे भी जानकारी leak हो सकती है
      इसमें condition checks, जैसे permission checks की वजह से explicitly execute न हुआ code भी शामिल है
      एक जाना-पहचाना attack example Spectre है: https://en.m.wikipedia.org/wiki/Spectre_(security_vulnerabil...
    • दशकों पहले ही 90% accuracy हासिल कर ली गई थी। workload के हिसाब से आधुनिक chips इससे कहीं बेहतर करते हैं
      इसलिए मूल रूप से यह बिल्कुल cost-effective नहीं है। उस chip resource को किसी दूसरे thread या core पर लगाना कहीं बेहतर है
  • यह अच्छा idea है या नहीं, तय करने के लिए पहले performance data देखना चाहूँगा। इस approach की branch prediction penalty की जानकारी भी नहीं है
    फिर भी इस approach का intuition शायद उन instructions को aggressively fetch और decode करने में है जो L1 instruction cache या micro-op cache में अभी न हों
    यह x86, और शायद RISC-V में भी महत्वपूर्ण है। दोनों में instruction length variable होती है, इसलिए केवल instruction cache block देखकर core नहीं जान सकता कि उस block के instructions को कैसे decode करना है। दोनों ISA में instruction cache block decode शुरू करने के लिए कम से कम एक instruction का PC जानना पड़ता है
    इसलिए अगर application को पता हो कि दो blocks आगे कहाँ jump किया जा सकता है, तो यह current approach से भी आगे तक fetch और decode करने में मदद करता है
    यह approach instruction prefetching जैसी है, लेकिन instruction prefetching core को starting point की जानकारी नहीं देती
    high-performance ARM cores में सभी instructions 32-bit length के होते हैं, इसलिए उनमें “starting point ढूँढने” की problem शायद नहीं होती। इसलिए starting point न पता हो तब भी decoding procedure parallel में हो सकता है
    यह तरीका frontend-heavy applications, जैसे cloud workloads जहाँ hot code blocks binary में अलग-अलग जगह फैले होते हैं, को फायदा दे सकता है। बाकी तरह की applications में performance gain होगा या loss, यह जानने की उत्सुकता है

  • मुझे अभी भी बिल्कुल समझ नहीं आया कि 2-ahead branch predictor क्या है

    • शायद article में link किए गए पुराने research paper से शुरू करना बेहतर होगा
      आम तौर पर पुराने research papers मानकर चलते हैं कि reader ऐसे topics के बारे में काफी कम जानता है। उस समय यह knowledge कहीं ज्यादा niche थी
  • अब ज़रूरत memory bandwidth की है। Consumer-grade AM5 socket के दो memory channels, इस स्तर की compute performance के मुकाबले, खासकर बेसिक Apple Silicon से तुलना करने पर भी, फीके लगते हैं
    मैं एक भारी-भरकम Zen configuration से M2 Max पर आया, और यह देखकर फिर से हैरान हुआ कि memory bandwidth में सुधार intensive data workloads को कितना तेज़ कर देता है। काफ़ी भारी multitasking में भी Zen configuration की संकरी memory pipe अक्सर अटक जाती थी

    • असल में ऐसे applications बहुत कम हैं जो memory bandwidth bottleneck में फँसते हों और फिर भी CPU, GPU से ज़्यादा उपयुक्त हो
      लोग खासकर LLM की वजह से Apple Silicon को देखते हैं, क्योंकि LLM वैसे तो GPU के लिए ज़्यादा उपयुक्त हैं, लेकिन उन्हें VRAM भी बहुत चाहिए, और NVIDIA ज़्यादा VRAM वाले GPUs की बेहिसाब कीमत लगाता है
      अगर AMD सच में NVIDIA की रफ़्तार तोड़ना चाहता है, तो उसे 64~128GB VRAM वाले consumer GPUs बेचने चाहिए
    • AM5 में असल में 4 memory channels हैं। क्योंकि DDR5 ने channels की संख्या दोगुनी कर दी है