1 पॉइंट द्वारा GN⁺ 2024-08-28 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Box64 का RV64 DynaRec एक साल पहले केवल साधारण native Linux गेम चलाने के स्तर पर था, लेकिन अब यह RISC-V PC पर The Witcher 3 चलाने तक पहुँच गया है
  • इस प्रगति का बड़ा कारण AMD ग्राफिक्स कार्ड के उपयोग की सुविधा मिलना रहा, जिससे OpenGL की सीमाएँ घटीं और अधिक x86 प्रोग्राम टेस्ट करके बग ठीक करना संभव हुआ
  • RV64 backend में ARM64 backend की तुलना में लागू किए गए x86 निर्देश कम हैं, और AVX निर्देश भी अभी RISC-V पक्ष के लिए बड़ा अधूरा काम हैं
  • RISC-V में bit range extraction·insertion और 16-byte atomic instructions की कमी है, इसलिए x86 emulation में AArch64 या LoongArch64 की तुलना में translation cost अधिक है
  • The Witcher 3 वास्तव में box64 पर चलता है, गेम के भीतर अधिकतम 15fps तक पहुँचता है, और main menu में full-speed हासिल करता है

RISC-V पर The Witcher 3 के चलने तक की यात्रा

  • एक साल पहले RV64 DynaRec केवल Stardew Valley, World of Goo जैसे अपेक्षाकृत आसानी से चलने वाले native Linux गेम ही चला पाता था
  • उस समय bottleneck मुख्य रूप से दो थे
    • RISC-V backend में x86_64 निर्देशों को तेज़ी से जोड़ने की प्रक्रिया के दौरान बहुत से DynaRec bugs बाकी थे
    • VisionFive 2 और LicheePi 4A के IMG integrated GPU केवल OpenGL ES को सपोर्ट करते थे और OpenGL को सपोर्ट नहीं करते थे
  • gl4es के जरिए कुछ OpenGL सपोर्ट मिल जाने से Stardew Valley जैसे गेम चल सके, लेकिन भारी Linux गेम और सामान्य Windows गेम के लिए यह पर्याप्त नहीं था
  • Sophgo का Milk-V Pioneer 64-core RISC-V PC है, जो ग्राफिक्स कार्ड लगाने के लिए PCIe slot देता है
  • एक अन्य contributor xctan ने VisionFive 2 में M.2 interface के जरिए AMD ग्राफिक्स कार्ड को “कनेक्ट” करने का तरीका खोजा
  • AMD ग्राफिक्स कार्ड का उपयोग संभव होने के बाद टेस्ट किए जा सकने वाले x86 प्रोग्रामों की सीमा बढ़ी, और RV64 DynaRec bugs को ठीक करने तथा x86 निर्देश जोड़ने का काम बड़े पैमाने पर हुआ
  • नतीजतन The Witcher 3 पहली बार चलाने पर ही काम कर गया

RV64 DynaRec की मौजूदा स्थिति

  • x86 instruction set बहुत बड़ा है, और backend के अनुसार implementation का पैमाना भी अलग है
    • ARM64 backend में कुल मिलाकर 1,600 से अधिक x86 निर्देश लागू हैं
    • RV64 backend में लगभग 1,000 x86 निर्देश लागू हैं
    • इनमें 300 से अधिक नए सपोर्ट किए गए AVX निर्देश हैं, जो RISC-V में अभी बिल्कुल लागू नहीं हुए हैं
  • SSE निर्देशों के implementation में भी RISC-V प्रदर्शन के लिहाज़ से कमजोर है
    • RV64 backend SSE निर्देशों को scalar instructions के रूप में लागू करता है
    • AArch64 Neon extension का उपयोग करता है, और LoongArch64 LSX extension का
    • इस अंतर के कारण प्रदर्शन अन्य दो backends की तुलना में काफी कम है
  • RISC-V में vector extension RVV मौजूद है
    • Milk-V Pioneer, RVV 0.7.1 के एक variant xtheadvector extension को सपोर्ट करता है
    • SpacemiT K1/M1 SoC ratified RVV 1.0 को सपोर्ट करता है
    • इस SoC वाले Banana Pi F3 और Milk-V Jupiter खरीदे जा सकते हैं
  • box64 में हाल ही में बुनियादी RVV सपोर्ट और कुछ सामान्य SSE निर्देशों का implementation जोड़ा गया है
  • RVV पर काम अभी बहुत शुरुआती चरण में है, इसलिए फिलहाल इससे performance improvement में मदद नहीं मिलती

x86 emulation के लिए खास तौर पर कमी वाले RISC-V निर्देश

  • x86 emulation के नज़रिए से RISC-V, सपोर्ट की जाने वाली तीन architectures में सबसे कम expressive है
  • AArch64 और LoongArch64 की तुलना में इसमें सुविधाजनक निर्देश कम हैं, इसलिए वही काम emulate करने के लिए अधिक निर्देशों की ज़रूरत पड़ती है
  • खास तौर पर दो महत्वपूर्ण सुविधाएँ नहीं हैं
    • एक register से किसी खास bit range को चुनकर दूसरे register में लाने की सुविधा
    • एक register के कुछ bits को दूसरे register की किसी खास range में insert करने की सुविधा
  • LoongArch64 और AArch64 में इसके लिए संबंधित निर्देश मौजूद हैं
    • LoongArch64 BSTRPICK.D और BSTRINS.D का उपयोग करता है
    • ARM64 UBFX और BFI opcode का उपयोग करता है
  • RISC-V में official extensions या vendor extensions, किसी में भी इसके अनुरूप निर्देश नहीं हैं

ADD AH, BL उदाहरण से दिखने वाली translation cost

  • x86 ISA बदले बिना छोड़े गए bits को सुरक्षित रखने की प्रवृत्ति रखता है, इसलिए partial register manipulation महत्वपूर्ण है
  • ADD AH, BL के मामले में box64 को ये काम करने पड़ते हैं
    • RBX का सबसे निचला byte निकालना
    • उसे RAX के दूसरे सबसे निचले byte में जोड़ना
    • परिणाम को फिर RAX के दूसरे सबसे निचले byte में insert करना
    • RAX के बाकी bytes को जस का तस बनाए रखना
  • LoongArch64 में BSTRPICK.D, ADD, BSTRINS.D की मदद से इसे सरल और सीधा लागू किया जा सकता है
  • RISC-V में वही काम shifts, masks, AND, OR आदि के संयोजन से करना पड़ता है, इसलिए 10 निर्देशों की ज़रूरत होती है
  • ऐसे मामले अलग-थलग नहीं हैं; x86 में इस तरह के कई निर्देश हैं, इसलिए RISC-V implementation अधिक झंझटभरा है

16-byte atomic instructions की सीमा

  • x86 में lock-free atomic operations के लिए LOCK prefix instructions होते हैं
  • box64 मुख्य रूप से LR/SC sequence से इनका emulation करता है
    • LR/SC का मतलब Load-Reserved / Store-Conditionally है
    • उदाहरण के लिए LOCK ADD [RAX], RCX को LR.D, ADD, SC.D, conditional branch के रूप में बनाया जाता है
  • अगर RAX address aligned न हो तो मामला और जटिल हो जाता है, लेकिन सामान्यतः यह तरीका अच्छी तरह काम करता है
  • समस्या LOCK CMPXCHG16B में है
    • यह निर्देश RDX:RAX की तुलना memory के 16 bytes से करता है
    • शर्त के अनुसार RCX:RBX को उस memory address पर swap करता है
  • AArch64 और LoongArch64 में implementation के लिए कुछ 16-byte atomic instructions उपलब्ध हैं
  • RISC-V में इसके अनुरूप निर्देश नहीं हैं, इसलिए इसे अन्य architectures जितना पूर्ण रूप से लागू नहीं किया जा सकता
  • Unity गेम्स सहित कई प्रोग्राम LOCK CMPXCHG16B का उपयोग करते हैं

वास्तविक रनिंग परिणाम

  • सीमाएँ बाकी होने के बावजूद The Witcher 3, box64 के जरिए RISC-V पर चलता है
  • प्रदर्शन गेम के भीतर अधिकतम 15fps तक पहुँचता है
  • main menu में यह full-speed पर चलता है
  • ऐसी मशीन के लिए, जिसे AAA गेम चलाने के उद्देश्य से डिज़ाइन नहीं किया गया था, यह परिणाम बुरा नहीं है

1 टिप्पणियां

 
GN⁺ 2024-08-28
Hacker News की राय
  • चिप वाली तरफ काम न करने वाले व्यक्ति के तौर पर जिज्ञासा है कि RISC-V के लिए software बनाते समय software engineer को अलग क्या करना पड़ता है
    लगता है executable file का size बढ़ जाता होगा, इसलिए cache locality को aggressively optimize करना पड़ता होगा; और यह भी जानना है कि games या web servers जैसी software categories में कुछ CISC/RISC में से किसी एक के लिए ज्यादा फिट होती हैं या नहीं

    • compressed instruction extension वाला RISC-V औसतन x86-64 या ARM से छोटा code size देता है
      software approach में मूल रूप से बदलने लायक बहुत कुछ नहीं है, और x86-64 की तुलना में सबसे बड़ा फर्क यह है कि registers 32 हैं, इसलिए stack में spill होने से पहले ज्यादा intermediate values रखी जा सकती हैं; ARM में भी 32 हैं, इसलिए वह भी मिलता-जुलता है। आम तौर पर जब तक micro-optimization नहीं कर रहे हों, इस पर ज्यादा ध्यान देने की जरूरत नहीं होती
      और detail में जाएँ तो vector extension (V/RVV) default rv64gc ISA में नहीं है, इसलिए target के हिसाब से SIMD optimization नहीं मिल सकता; और popcount तथा leading/trailing zero count भी default rv64gc में नहीं हैं, इनके लिए Zbb चाहिए। साथ ही a ? b : c जैसी branchless selection भी default rv64gc में 4–5 instructions, Zicond के साथ 3 instructions मांगती है, जबकि x86-64 और aarch64 में यह 1 instruction में हो जाता है
      RISC-V profiles पहले दो issues को कुछ हद तक solve करते हैं। जैसे Android RVV, Zbb, Zicond आदि की मांग करने वाला rva23 require करता है। लेकिन अगर Linux distribution rva20/rv64gc को target करे, तो dynamically dispatch न करने वाले precompiled code में ऐसे extensions को practical तौर पर लंबे समय तक इस्तेमाल नहीं किया जा सकेगा। x86-64 में भी ऐसा ही issue है, लेकिन ARM में extensions काफी कम हैं, इसलिए समस्या कम है; SVE सबसे बड़ा exception है, पर अभी widely supported नहीं है
    • ज्यादातर मामलों में कुछ भी अलग करने की जरूरत नहीं। C जैसी high-level language में सही तरह लिखा code वैसे ही काम करना चाहिए
      सबसे बड़ा फर्क weak memory model है, लेकिन यह ARM जैसी ज्यादातर non-x86 architectures में भी होता है, और code को शुरू से ही strong memory model पर depend नहीं करना चाहिए
      executable code density में historical कारणों से x86 बहुत अच्छा नहीं है, इसलिए executable file size उतना नहीं बढ़ता जितना लगता है। compressed instruction extension वाला RISC-V और Thumb extension वाला 32-bit ARM काफी dense हैं
      अहम बात CISC बनाम RISC नहीं, बल्कि vector instructions और cryptography extensions की मौजूदगी और quality है। video encoding/decoding अच्छी performance के लिए vector instructions पर बहुत depend करता है, और full disk encryption या hashing को AES, SHA256 जैसे specific algorithms accelerate करने वाले dedicated instructions से मदद मिल सकती है
    • कोई भी instruction set लगभग हर तरह के workload के लिए करीब-करीब उतना ही अच्छा fit होना चाहिए। अगर assembly programming कर रहे हैं तो फर्क पड़ेगा, लेकिन Python या Unity में बना रहे हैं तो यह लगभग issue नहीं होगा
      असल बात ARM patents से मुक्त होना और सीखे गए lessons के आधार पर नई शुरुआत करना ज्यादा है
  • याद आता है कि एक मशहूर रूसी व्यक्ति ने Elbrus 8S पर Atomic Heart चलाया था
    Elbrus में native translator है और मेरी जानकारी में वह काफी ठीक है। Atomic Heart करीब 15–25fps पर कुछ हद तक playable था

  • लेख में “basic” explanation थोड़ी कम है। मुझे लगा था कि इसे Wine port जैसी किसी चीज से चलाया गया होगा, लेकिन असल में ऐसा लगता है कि RISC-V chip के ऊपर किसी तरह से x86_64 ISA implement किया गया है
    अच्छा होगा अगर कोई समझा सके कि वह हिस्सा कैसे काम करता है

    • basic explanation यहाँ है: https://box86.org/
      यह emulator तो है, लेकिन libc, libm, SDL, OpenGL जैसी कुछ “system” libraries के native versions इस्तेमाल करता है, इसलिए ज्यादातर applications के साथ integrate करना आसान है, और कुछ मामलों में performance भी हैरान करने लायक high हो सकती है। Wine को भी native compile करके चलाया जा सकता है
  • कमाल का result है। बहुत बड़ा काम है, और कुछ मामलों में लगता है कि यह RISC-V की limits को छू रहा है
    bit gather/scatter instructions को extension में जाना चाहिए लगता है

    • CPU की तुलना में graphics core पर ज्यादा depend करने वाले game से test results भी देखना चाहूँगा। Divinity 2 जैसी कोई चीज ठीक हो सकती है
  • x86 emulation के संदर्भ में जिन 3 architectures को support किया जाता है, उनमें RISC-V का सबसे कम expressive होना दिलचस्प है
    Computer science history की क्लास में हमने RISC को reduced instruction set computer के रूप में पढ़ा था, लेकिन आजकल RISC-V profiles के प्रस्तावों या लेखों को देखें तो अक्सर बात ऐसी होती है कि “feature parity के लिए बस कुछ और instructions चाहिए।” मैं समझता हूं कि RISC-V कई लोगों के लिए दूसरे platforms का सुविधाजनक विकल्प है, लेकिन यह भी सोचता हूं कि क्या इसका मतलब है कि RISC का सपना मर गया है

    • मेरी समझ में असली RISC “बिल्कुल न्यूनतम instruction set” से ज़्यादा, “assembly programmer की सुविधा के लिए clever features न डालें और जहां तक हो front-end silicon के बजाय compiler पर छोड़ें” के करीब है
      RISC-V specification पढ़ने की मेरी याद के मुताबिक, वह “combo” instructions जोड़ने को लेकर काफ़ी strict था, क्योंकि आम instruction sequences को front-end में fuse किया जा सकता है
      x86/ARM की तुलना में RISC-V की कमी शायद RISC fundamentalism की वजह से नहीं, बल्कि इसलिए है कि specification ने बहुत basic embedded chips से शुरुआत की और समय के साथ application CPUs के लिए extensions जोड़े। basic RV32I में integer multiplication तक नहीं है। दुर्भाग्य से bit manipulation और SIMD/vector extensions की बहस खत्म करने में बहुत ज़्यादा समय लगा, और नतीजतन आज जिन feature gaps की बात हो रही है वे पैदा हुए
    • अगर ऐसा instruction set बनाना हो जिसे कोई छात्र एक semester की class में implement कर सके, तो सभी instructions में 2 inputs और 1 output रखने जैसी simplification चाहिए। processor design पर प्रयोग करने वाले researchers के लिए भी यह बहुत आसान हो जाता है
      हालांकि इसी वजह से high performance के लिए सुविधाजनक कुछ instructions बाहर रह जाते हैं
      simple pipeline का एक फायदा यह भी है कि high-performance design करने वाली team के engineering resources कम लगते हैं, जिससे optimization पर ज़्यादा समय लगाया जा सकता है
      RISC मोटे तौर पर simplification philosophy है, लेकिन उसका स्तर अलग-अलग होता है। MIPS, RISC-V जितना simplified है, लेकिन ARM और POWER ज़्यादा pragmatic compromise करते हैं, और high-performance क्षेत्र में x86 से मुकाबला करने में उन्हें कोई बड़ी दिक्कत नहीं दिखती
      processor के market में application execution के अलावा embedded, accelerators जैसी कई niches भी हैं। application core नाम की खास niche में मैं RISC-V को लेकर थोड़ा pessimistic हूं, लेकिन व्यापक रूप से देखें तो इसकी potential बड़ी है, कुछ commercial niches पर dominate करने की संभावना भी है, और education व research tools के रूप में यह शानदार है
    • RISC का सपना यह था कि ज़्यादातर software सीधे assembly में नहीं बल्कि compiler से लिखा जाता है, इसलिए CPU design को simplify किया जाए
      classical RISC की खासियत यह है कि ज़्यादातर data manipulation instructions सिर्फ registers पर काम करते हैं, memory instructions आम तौर पर registers में load/store तक सीमित होते हैं, और इसलिए बहुत सारे registers चाहिए होते हैं। parameters pass करने के लिए stack को सीधे manipulate करना पड़ता है, इसलिए stack भी खुद बनता है, और CALL/JSR instructions के बिना instruction pointer register पर सीधे load/store करने वाली basic instructions से इसे implement किया जाता है। instruction encoding predictable होती है और सभी instructions का size समान होता है। कई RISC architectures में ऐसा register भी था जिसे हमेशा 0 पढ़ा जाता था और लिखा नहीं जा सकता था, और values को 0 पर set करने में इस्तेमाल होता था
      यह तरीका काम आया, लेकिन बाद में out-of-order execution और SIMD ने इसकी अहमियत घटा दी। raw instruction stream desired result तक पहुंचने के रास्ते की declaration जैसा है; इसका मतलब यह नहीं कि CPU सचमुच उसे वैसा ही execute करता है। उसके पीछे speculative execution, branch prediction और register renaming होते हैं। SIMD wide register space और उसके भीतर सभी values पर काम करने वाली instructions के करीब है। आखिरकार out-of-order execution और SIMD ने lead ले ली
    • मुझे लगता है, क्या सच में RISC का कोई सपना है? efficiency का सपना, performance का सपना, cost का सपना है, और cost·performance·efficiency के मुकाबले low complexity का सपना भी है, लेकिन क्या कोई RISC itself को cost, performance, efficiency और simplicity से ज़्यादा महत्वपूर्ण मानता है?
    • इस context में x86_64 के लिए पहले से compiled code को RISC-V पर चलाने की कोशिश हो रही है। “feature parity के लिए बस कुछ और instructions चाहिए” वाली मांग इसलिए आती है क्योंकि code को ऐसे architecture के लिए compiled मानकर चलाया जा रहा है जिसमें वे extra instructions पहले से हैं
      theory में original source code को RISC के लिए compile करें तो पूरी तरह अलग binary बनेगी, और उन specific instructions की जरूरत नहीं पड़ सकती
      practical तौर पर, शायद कोई इन games को सचमुच RISC-V के लिए compile नहीं करेगा
  • screenshot में RAM 31GB दिख रही है, जो बताए गए development board की maximum spec से साफ़ तौर पर ज़्यादा है। क्या यहां कुछ और इस्तेमाल हो रहा है?

    • यह ज़्यादा पुराना board Pioneer है
      आज के समय में RVA22 और RVV 1.0 implement करने वाले कई तेज cores वाले नए options में से कोई एक इस्तेमाल करना बेहतर होगा
    • https://milkv.io/pioneer
    • milk-v pioneer में 128GB RAM लगी है
  • क्या यह 86Box है? Amstrad PC1512 खरीदने वाले दिनों को याद करना मज़ेदार था
    500MB hard card के 2 units और 128KB memory expansion जोड़कर 640KB कर दिया था, तो यह कहीं ज़्यादा मज़ेदार हो गया। शुरुआत में सिर्फ दो 360KB floppies थीं, और कुछ साल बाद 32MB hard card जोड़ा था। Borland TurboPascal और Zortech C भी थे। अच्छे दिन थे

    • नहीं, यह Box64 है और बिल्कुल अलग project है
      फिर भी Amstrad PC1512 इस्तेमाल करने वाले दिन याद हैं
  • सोचता हूं कि क्या कभी ऐसा system आएगा जिसमें कुछ बड़े RISC-V CPUs के साथ, छोटे RISC-V CPUs के झुंड से implement किया गया “GPU” भी होगा
    शायद यह उचित vector features के साथ होगा, लेकिन side question के तौर पर यह भी जानना चाहता हूं कि packed SIMD के बजाय classical vector approach GPU में उपयोगी हो सकती है या नहीं

  • technically impressive Witcher 3 achievements में Switch port भी था, और वह सचमुच अच्छी तरह चलता था
    यह दिखाता है कि optimization से कितना कुछ किया जा सकता है, और PC पर bad optimization की वजह से कितने resources waste होते हैं

    • बहुत कम quality वाले textures और 3D models इस्तेमाल करके assets के लिए RAM बहुत कम लगना भी बड़ा factor है
      यह apples-to-apples comparison नहीं है, और screen पर दिखने वाली range काफ़ी अलग है, इसलिए PC की bad optimization को तय मानना मुश्किल है
    • rendering resolution को 720p, handheld mode में 540p तक घटाकर, settings को minimum से भी नीचे रखकर, और करीब 30fps को acceptable कह सकें तो minimum-spec PC पर भी Witcher 3 को वैसा ही चलाया जा सकता है
  • अच्छा होगा अगर इस तरह का ISA-स्तर का feedback RVI के लोगों तक पहुँचे

    • scalar efficiency SIG में पहले से ही bitfield insert/extract instructions पर चर्चा हो रही है
      कल चेक किया तो [1], लेख का example पहले ही 4 RISC-V instructions से किया जा सकता है। हालांकि इसे सोच पाना थोड़ा मुश्किल है
      # a0 = rax, a1 = rbx
      slli t0, a1, 64-8
      rori a0, a0, 16
      add a0, a0, t0
      rori a0, a0, 64-16
      [1] https://www.reddit.com/r/RISCV/comments/1f1mnxf/box64_and_ri...
    • इनमें से कुछ भी नया नहीं है
      सच में, bitfield extract का छूट जाना इतनी साफ़ गलती है कि RISC-V ISA कितना बेतुका है, यह दिखाने वाला मेरा पसंदीदा example यही है। दूसरा है ढंग के addressing modes का न होना
      कुछ बेहतर RISC-V designs ने इसके लिए सचमुच custom instructions implement किए हैं। उदाहरण के लिए Hazard3 का BEXTM है: https://github.com/Wren6991/Hazard3/blob/stable/doc/hazard3....