HN से: Go Plan9 मेमो
(pehringer.info)Go की concurrency और parallelism का उपयोग
- संख्यात्मक गणना क्षमता को बेहतर बनाने के लिए Go की concurrency और parallelism का उपयोग करने वाले एक प्रोजेक्ट का परिचय।
- SIMD(Same Instruction Multiple Data) निर्देशों का उपयोग करके हार्डवेयर स्तर पर parallel गणना की जा सकती है।
- Go का compiler SIMD का उपयोग नहीं करता, और उपयुक्त general-purpose SIMD package न मिलने पर स्वयं package विकसित करने का निर्णय लिया गया।
Plan9 assembly भाषा
- Go अपनी खुद की Plan9 assembly भाषा का उपयोग करता है, जो किसी विशेष platform के instructions और registers को थोड़ा संशोधित करके इस्तेमाल करती है।
- x86 Plan9 और ARM Plan9 एक-दूसरे से अलग हैं।
- Plan9 के सरल उदाहरणों के माध्यम से इसकी बुनियादी उपयोग-विधि समझाई गई है।
Plan9 उदाहरण
AddInts_amd64.sफ़ाइल औरmain.goफ़ाइल के माध्यम से Plan9 में बुनियादी function declaration और उपयोग का तरीका समझाया गया है।- Go की calling convention के अनुसार function arguments और return values को stack में store करने का तरीका बताया गया है।
package design योजना
- arithmetic और bit operation SIMD कार्यों के लिए एक पतली abstraction layer प्रदान करने वाला package डिज़ाइन किया गया है।
- architecture-विशिष्ट Plan9 implementation शामिल करने वाला internal package बनाया जाता है, और initialization function के माध्यम से इसे सेट किया जाता है।
SIMD उदाहरण
- x86 SIMD Plan9 function के उदाहरण के माध्यम से SIMD के उपयोग का तरीका समझाया गया है।
Supported_amd64.sऔरAddFloat32_amd64.sफ़ाइलों के जरिए SSE support की जाँच औरfloat32addition operation करने का तरीका दिखाया गया है।
performance और भविष्य
- Go software implementation और Plan9 SIMD implementation के बीच performance अंतर दिखाने वाले chart से लगभग 200-450% speed improvement की पुष्टि होती है।
- आशा है कि यह मेमो Plan9 और SIMD का उपयोग करने वाले प्रोजेक्ट्स के लिए प्रेरणा देगा।
# GN⁺ का सार
- यह लेख Go की concurrency और parallelism का उपयोग करके performance को अधिकतम करने के तरीकों का परिचय देता है।
- Plan9 assembly भाषा और SIMD निर्देशों का उपयोग करके हार्डवेयर स्तर पर parallel गणना करने के तरीके समझाए गए हैं।
- यह लेख Go developers के लिए Plan9 और SIMD के उपयोग की संभावनाएँ दिखाता है और performance सुधार के लिए नए approaches तलाशने में उपयोगी हो सकता है।
- समान कार्यक्षमता वाले प्रोजेक्ट्स के रूप में Rust की SIMD support libraries या C++ की SIMD-संबंधित libraries की सिफारिश की गई है।
1 टिप्पणियां
Hacker News की राय
Go assembly के बारे में कुछ बातें साफ़ कर दूँ: amd64 पर वे
intअसल में 64-bit हैंint32इस्तेमाल करने पर parameter list में word alignment हो जाता है, लेकिन इसमें एक फंदा है। 64-bit सिस्टम पर return value हमेशा doubleword-aligned offset से शुरू होती हैNOSPLITtextflag.hमें define है, जिसे Go compiler अपने-आप उपलब्ध कराता है। हालांकि जितना मैंने पढ़ा है,NOSPLITशायद सिर्फ़runtime.XXfunctions में ही माना जाता है, इसलिए यहाँ यह कुछ नहीं करता, और ज़रूरी भी नहीं हैNOSPLITका मतलब है कि compiler वह code insert न करे जो जाँचता है कि stack overflow हो सकता है या नहीं और splitting की ज़रूरत है या नहीं। जिस function को stack space की ज़रूरत नहीं है, उसके लिए यह technically अनावश्यक है, और मूल रूप से यह इसलिए है कि stack splitting की जाँच करने वाले function के अंदर ही वह checking code inject न हो जाएजिन्हें यह जानना हो कि
4“NOSPLIT” को दर्शाता है और क्यों इसे ज़रूरी बताया गया है, उनके लिए: आम तौर पर frame size (NOSPLITके बाद वाला parameter) के बाद argument size आता है, और दोनों को minus sign से अलग किया जाता हैयह subtraction नहीं, बस एक अजीब syntax है। frame size
$24-8का मतलब है कि function के पास 24-byte frame है, और उसे caller frame में मौजूद 8-byte arguments के साथ call किया जाता हैअगर
TEXTमेंNOSPLITspecify नहीं करते, तो argument size देना अनिवार्य है। Go prototype वाले assembly function के मामले मेंgo vetजाँचता है कि argument size सही है या नहींस्रोत: https://go.dev/doc/asm
“Go अपनी internal assembly language, Plan9, इस्तेमाल करता है” कहा गया है—क्या वह language सच में इसी नाम से जानी जाती है?
Syntax Plan 9 से निकला है, लेकिन हम इसे Go assembly कहते हैं
https://go.dev/doc/asm देखें
लेकिन जितना और खोजा, उतना लगा कि यह LLM hallucination जैसा है
Assembly format का document इसे कोई ठीक-ठाक नाम नहीं देता, बस
go assemblerकहता हैइस hallucination का स्रोत शायद पहला paragraph है: “assembler Plan 9 assembler की input style पर आधारित है और… यह document उस syntax का सार, differences, और Go के साथ interact करने वाला assembly code लिखते समय की peculiarities समझाता है”
यह कहने जैसा है कि “GNU Compiler Collection अपनी internal assembly language Unix इस्तेमाल करता है”
अगर आप सोच रहे हैं कि Go team ने ऐसा dedicated assembly format क्यों चुना, तो Rob Pike ने 2016 की एक presentation में Go assembler design पर बात की थी [1][2]
मुख्य बात शायद यह observation थी कि ज़्यादातर assembly languages काफ़ी मिलती-जुलती हैं, इसलिए एक common assembly language बनाई जाए जो “machine के सबसे निचले level से बात करते हुए भी नया syntax सीखने की ज़रूरत न रहने दे”
इससे नए architecture के instruction manual PDF को input के रूप में लेकर काम करने वाला assembler auto-generate करना भी संभव हो जाता है
[1]: https://www.youtube.com/watch?v=KINIAgRpkDA
[2]: https://go.dev/talks/2016/asm.slide#1
“slice पर SIMD operations करने वाले functions की ज़रूरत थी” कहा गया था, लेकिन मैं सोच रहा था कि असल में इसका उपयोग कैसे होता है
पूरे लेख में खोजने पर भी slice पर किए जाने वाले operations कहीं नहीं मिले
सुधार: linked document में मिला: https://pkg.go.dev/github.com/pehringer/simd#pkg-index
मूल रूप से अगर आपके पास 2 slices हैं जिन्हें add करना है, तो
forloop की जगह SIMD से parallel process करकेsimd.AddInt32(slice1, slice2, result)जैसा इस्तेमाल कर सकते हैंhttps://github.com/pehringer/simd/blob/main/simd_test.go
Go द्वारा support किए जाने वाले processors के संबंध में यह section relevant है (1). Basic x64 support में SSE और SSE2 शामिल हैं
हालांकि मुझे नहीं पता कि Go compiler वास्तव में उन्हें generate करता है या नहीं। gcc जैसे बहुत complex compiler, जो performance को सर्वोपरि मानते हैं, उनसे अलग Go compiler Wirth-style (2) में simple और fast compiler को प्राथमिकता देता है
(1) https://go.dev/wiki/MinimumRequirements#amd64
(2) https://irreal.org/blog/?p=7075
https://smartgo.blog/2024/01/06/niklaus-wirth/
लगता है लेखक ने इस हिस्से में confusion किया है, इसलिए reference link छोड़ रहा हूँ: https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs
मैं भी यही कहने वाला था कि यह कोड को LLM द्वारा गलत समझने का नतीजा लगता है
Plan 9 शब्द के बारे में जानना और assembly तक गहराई में जाना, लेकिन फिर भी यह न समझना कि वह किस दुनिया में कदम रख रहा है—इसे किसी और तरह से कल्पना करना मुश्किल है। दूसरों को भी ऐसा ही लगा, यह देखकर समझ आया
अगर यह सही है, तो लेखक को शर्मिंदा या “पकड़ा गया” महसूस करने के बजाय ईमानदार होना चाहिए। तभी हम भी सीख सकते हैं। मैं इस तरह के “LLM exposure” टाइप के मामलों पर भरोसा बनाना चाहता हूं, लेकिन चाहे वे कितने भी स्पष्ट दिखें, लोग शायद ही कभी मानते हैं
बेशक यहां यह स्पष्ट नहीं है, बस बहुत जल्दबाजी में की गई और judgmental अटकल है
ऐसी चीजें सच में गुस्सा दिलाती हैं
यह मेरे स्तर से थोड़ा ऊपर था, लेकिन लेख जिस तरह पाठक को साथ लेकर चलता है, वह अच्छा लगा
ऐसा प्रयास पहली बार तो नहीं हो सकता, है ना? SIMD के लिए तरसते literally दर्जनों Gopher होंगे। क्या ज्यादा आम pattern CGO इस्तेमाल करना है?
Go में assembly function call करना कहीं ज्यादा सस्ता है
https://pkg.go.dev/github.com/grailbio/base/simd पर मैंने इसी दिशा में जो काम किया है, वह मौजूद है
अगर मेरी याद सही है, उस समय कई AVX instructions Go के Plan 9 assembler में encode तक नहीं होते थे, इसलिए उन्हें bytes के रूप में सीधे encode करना पड़ता था [0]
मैंने जो सबसे complete library देखी है, हालांकि इस्तेमाल नहीं की, वह CGO को आंशिक रूप से इस्तेमाल करते हुए उस overhead से बचने के लिए एक साफ hack इस्तेमाल करती है [1]
[0]: https://github.com/slimsag/rand/blob/f1e8d464c0021a391d5cd64...
[1]: https://github.com/alivanz/go-simd/
Go assembly program लिखना है तो Avo(https://github.com/mmcloughlin/avo) देखने की सलाह दूंगा
यह type safety देता है और valid assembly output हो रही है या नहीं, इसके लिए कुछ checks करता है। यह registers को dynamically allocate कर सकता है, और stack व frame size जैसी चीजें खुद calculate करने की जरूरत भी खत्म कर देता है
यह calling convention details भी handle कर सकता है, ताकि arguments को मनचाहे register या location में आसानी से load किया जा सके
हाल ही में मैंने Go की crypto library में मौजूद पूरी amd64 assembly को Avo पर port किया है, और ऐसे कामों के लिए यह बहुत उपयोगी library है