दर काही महिन्यांनी ओपन-सोर्स समुदाय आणखी एक नवीन AI फ्रेमवर्क तयार करतो. त्यापैकी बहुतेक फ्रेमवर्क्स जड C++ कर्नल्सभोवती Python बाइंडिंग्स गुंडाळतात, किंवा ते ॲबस्ट्रॅक्शन लेयर्स इतके जास्त रचतात की केवळ रनटाइमचे वजन त्यांनी सेवा देणाऱ्या मॉडेल्सपेक्षाही जास्त होते. CatAI याच्या अगदी उलट दिशेने काम करते. हे पूर्णपणे C++ मध्ये लिहिलेले एक नेटिव्ह AI इंजिन आहे, जे टेन्सर मॅथपासून (tensor math) तयार केले आहे. याचा उद्देश PyTorch वर आणखी एक सोपे स्वरूप (skin) तयार करणे हा नाही. तर हार्डवेअर बाउंड्रीपासून सुरुवात करून मेमरीचा प्रत्येक बाइट आणि कम्प्युटचा प्रत्येक सायकल स्वतःच्या नियंत्रणाखाली आणणे हा आहे.

आणखी एक इंजिन का?

जर तुम्ही काहीही प्रोडक्शनमध्ये पाठवले असेल, तर तुम्हाला त्यातील त्रास आधीच माहित आहे. एखादा स्टँडर्ड डीप-लर्निंग स्टॅक कंटेनरमध्ये घ्या आणि त्याचे इमेज मल्टिपल गिगाबाइट्सपर्यंत कशी वाढते ते पहा. डिपेंडन्सीज एकमेकांशी संघर्ष करतात. Python इंटरप्रिटरमुळे लॅटन्सी वाढते. CUDA किंवा CPU कडे ऑप्स (ops) पाठवणारा डिस्पॅचर असा सूक्ष्म ओव्हरहेड निर्माण करतो जो डझनभर नेस्टेड फ्रेमवर्क्समध्ये हरवल्यावर प्रोफाईल करणे अशक्य होते. एज डिव्हाइसेस, एम्बेडेड रोबोटिक्स किंवा लॅटन्सी-सेन्सिटिव्ह बॅकएंड्ससाठी, हा भार वास्तविक आहे. एक प्युअर C++ इंजिन मध्यस्थाला काढून टाकते. ते ऑपरेटिंग सिस्टम आणि सिलिकॉनशी थेट संवाद साधते, ज्यामध्ये कोणतीही गारबेज कलेक्शन, ग्लोबल इंटरप्रिटर लॉक किंवा भाषांमधील सिरियलायझेशनची प्रक्रिया नसते.

CatAI याला तडजोड म्हणून नाही, तर एक फीचर म्हणून पाहते. हा प्रकल्प C++ मध्ये शून्यापासून (from scratch) लिहिला जात आहे कारण लेखकाला टेन्सर RAM मध्ये कसे राहतील, ते कॅश हायरार्कीजमधून कसे हलतील आणि थ्रेड्समध्ये कर्नल्स कसे शेड्यूल केले जातील हे नेमके ठरवायचे आहे. हे वेडेपणाचे काम नाही. मर्यादित हार्डवेअरमधून परफॉर्मन्स काढताना वर्तन (behavior) निश्चित राहण्याची खात्री करण्याचा हा एकमेव मार्ग आहे.

"From Scratch" चा नेमका अर्थ काय?

बहुतेक आधुनिक फ्रेमवर्क्समध्ये, टेन्सर मॅथ cuDNN, oneMKL किंवा MPS सारख्या व्हेंडर लायब्ररीजच्या अस्पष्ट कॉल्सद्वारे हाताळले जाते. वेगाने काम पूर्ण करण्यासाठी हे योग्य आहे, परंतु ते ऑपरेशनची कार्यपद्धती लपवून ठेवते. CatAI स्वतःचे कोअर टेन्सर मॅथ आणि मेमरी लेआउट्स लिहित आहे. याचा अर्थ मल्टी-डायमेंशनल ॲरेज साठवणारे मूलभूत डेटा स्ट्रक्चर्स डिझाइन करणे, स्ट्राइड्स आणि ऑफसेट्स कसे मोजले जातील हे निवडणे आणि ॲक्सेस पॅटर्ननुसार डेटा row-major, column-major किंवा कस्टम टायल्ड फॉरमॅट्समध्ये साठवायचा की नाही हे ठरवणे.

हे सखोल सिस्टम्स वर्क आहे. जेव्हा तुम्ही हाताने मॅट्रिक्स-मल्टिप्लाय कर्नल लिहिता, तेव्हा तुम्ही torch.matmul च्या संदर्भात विचार करणे थांबवता आणि L1 कॅश लाईन्स, रजिस्टर प्रेशर आणि लूप टायलिंगबद्दल विचार करू लागता. तुम्ही टार्गेट CPU च्या SIMD विड्थवर आधारित 32x32 टायल्ससाठी की 64x64 साठी ब्लॉक करायचे हे ठरवता. तुम्ही अलोकेशन्स 64-बाइट बाउंड्रीजवर अलाइन करता जेणेकरून AVX-512 लोड्स कॅश लाईन्स ओलांडणार नाहीत. टेन्सर स्टोरेजसाठी std::vector योग्य कंटेनर आहे की कस्टम एरिना अलोकेटर तुम्हाला संपूर्ण इन्फरन्स ग्राफमध्ये चांगली लोकॅलिटी आणि शून्य फ्रॅगमेंटेशन देईल, यावर तुम्ही प्रश्न विचारता.

मेमरी लेआउट देखील तितकेच महत्त्वाचे आहे. जर channels-last इमेज डेटा channels-first पॅटर्नमध्ये ॲक्सेस केला गेला, तर एक साधी n-डायमेंशनल ॲरे परफॉर्मन्स खराब करू शकते. CatAI मध्ये, हे लेआउट्स प्रथम श्रेणीचे घटक (first-class citizens) आहेत, केवळ एक्सपोर्ट वेळी चालणाऱ्या ग्राफ ऑप्टिमायझरद्वारे हाताळले जाणारे विचार नसून.

ऑप्टिमायझेशनची मानसिकता

जोपर्यंत तुम्ही नॅनोसेकंद मोजायला सुरुवात करत नाही, तोपर्यंत बेअर-मेटल ऑप्टिमायझेशन हे केवळ एक बझवर्ड वाटते. याचा अर्थ ऑपरेशन्स असे फ्यूज करणे की ज्यामुळे मध्यवर्ती निकाल कधीही CPU रजिस्टर्स किंवा L1 कॅशच्या बाहेर जाणार नाहीत. याचा अर्थ layer-norm आणि त्यानंतर GELU हे एक सिंगल कर्नल म्हणून लागू करणे, ज्यामुळे DRAM कडे जाणारा संपूर्ण राऊंड-ट्रिप वाचतो. याचा अर्थ OpenMP डिफॉल्ट्सवर अवलंबून राहण्याऐवजी स्वतःचा थ्रेड पूल लिहिणे, कारण तुम्हाला माहित आहे की तुमचे वर्कलोड 'बर्स्टी' आहे आणि तुम्हाला प्रत्येक फॉरवर्ड पासमध्ये थ्रेड्स तयार करणे आणि जोडणे (spawning and joining) नको आहे.

याचा अर्थ असेंब्ली कधी लिहू नये हे समजून घेणे देखील आहे. कधीकधी कंपायलर हाताने लिहिलेल्या इंट्रिन्सिकपेक्षा लूप अधिक चांगल्या प्रकारे वेक्टराइज करतो. शिस्त म्हणजे मोजमाप: प्रोफाईल करा, गृहितक (hypothesize) मांडा, एक व्हेरिएबल बदला आणि पुन्हा प्रोफाईल करा. हे इंजिन अशा लोकांद्वारे बनवले जात आहे ज्यांना या कष्टाचा आनंद घेता येतो. जर तुम्ही कधी एखाद्या बॅचमधून दोन मिलीसेकंद वाचवण्यासाठी कन्व्होल्यूशन लूप पुन्हा लिहिण्यात दुपार घालवली असेल, तर तुम्हाला ही संस्कृती आधीच समजली आहे.

आम्हाला कोणाची गरज आहे

हा केवळ एका व्यक्तीचा प्रकल्प नाही. शून्यापासून बॅकएंड तयार करण्यासाठी अशा विशिष्ट कौशल्यांची आवश्यकता असते जी एकाच मेंदूत क्वचितच एकत्र येतात. जर तुम्ही हे वाचत असाल आणि यात सामील होण्याचा विचार करत असाल, तर तुम्ही खालीलपैकी कुठे बसू शकता:

  • C++ डेव्हलपर्स ज्यांना आधुनिक मानके (modern standards) माहित आहेत, पण टेम्पलेट्समुळे (templates) कंपायलेशन ब्लोट (compilation bloat) कधी होतो हे देखील माहित आहे. तुम्हाला आवश्यकतेनुसार रॉ पॉइंटर्स (raw pointers) आणि योग्य वेळी स्मार्ट पॉइंटर्स (smart pointers) वापरण्यात सहजता असावी आणि तुम्हाला सिंटॅक्स शुगर (syntax sugar) इतक्याच बायनरी साईजची (binary size) काळजी असावी.

  • गणित तज्ज्ञ (Math experts) जे नॉन-स्टँडर्ड ॲक्टिव्हेशन्ससाठी (non-standard activations) बॅकवर्ड-पास ग्रेडियंट्स (backward-pass gradients) काढू शकतात, मिक्सड-प्रिसिजन ट्रेनिंगमधील (mixed-precision training) न्यूमेरिकल स्टॅबिलिटीबद्दल (numerical stability) विचार करू शकतात आणि अल्गोरिदम कोडमध्ये रूपांतरित होण्यापूर्वीच ते ऑप्टिमाइझ करू शकतात. जर तुम्ही 'log-sum-exp trick' का महत्त्वाचे आहे हे स्पष्ट करू शकत असाल, तर तुम्ही योग्य मानसिकतेत आहात.

  • लो-लेव्हल मेमरी स्पेशालिस्ट्स (Low-level memory specialists) जे अलोकेटर्स (allocators), पेज फॉल्ट्स (page faults) आणि NUMA टोपोलॉजीबद्दल विचार करतात. इंजिनला ग्राफ एक्झिक्यूशनसाठी मेमरी पूल्स (memory pools), कर्नल्ससाठी स्क्रॅच बफर्स (scratch buffers) आणि मेमरी लीक किंवा फ्रॅगमेंटेशन टाळून ट्रेनिंग स्टेप्समध्ये टेन्सर स्टोरेज (tensor storage) पुन्हा वापरण्याच्या धोरणांची गरज आहे.

  • सिस्टम इंजिनिअर्स (Systems engineers) ज्यांना समजते की एक चुकीचा syscall संपूर्ण ट्रेनिंग लूप थांबवू शकतो. शेड्युलिंग (Scheduling), I/O आणि सिंक्रोनाइझेशन प्रिमिटिव्ह्स (synchronization primitives) हे गणिताला एकत्र बांधून ठेवणारे घटक आहेत.

तुम्हाला या चारही क्षेत्रांत जागतिक दर्जाचे तज्ज्ञ असण्याची गरज नाही. बहुतेक योगदानकर्ते एका कर्नल किंवा एका अलोकेटरपासून सुरुवात करतील आणि आर्किटेक्चर स्थिर होत असताना उर्वरित गोष्टी शिकतील.

आर्किटेक्चर आणि कस्टम मॅथ (Architecture and Custom Math)

बॅकएंड लॉजिक सहकार्याने तयार केले जात आहे आणि त्याची सुरुवात आर्किटेक्चरवरील चर्चेने होते. इंजिन स्टॅटिक कम्प्युटेशन ग्राफ (static computation graph) वापरेल का, जिथे रनटाइमपूर्वी संपूर्ण मॉडेल परिभाषित आणि ऑप्टिमाइझ केले जाते? किंवा ते ऑटोमॅटिक डिफरेंशिएशनसाठी (automatic differentiation) टेपसह इगर एक्झिक्यूशनला (eager execution) सपोर्ट करेल? ऑटोडिफ (autodiff) कशा प्रकारे दर्शवले जाईल—ऑपरेटर ओव्हरलोडिंग (operator overloading), सोर्स ट्रान्सफॉर्मेशन (source transformation) किंवा ग्राफ IR? हे निर्णय इतर सर्व गोष्टींना आकार देतात.

कस्टम न्यूरल नेट मॅथ म्हणजे केवळ स्टँडर्ड लेयर्सची पुनरावृत्ती करणे नव्हे. याचा अर्थ नवीन लेयर्स शोधण्याचे स्वातंत्र्य आहे. जर तुम्हाला नॉन-स्टँडर्ड स्पार्स कर्नलसह (non-standard sparse kernel) कन्व्होल्यूशन व्हेरिएंट किंवा असा ॲक्टिव्हेशन फंक्शन हवा असेल ज्याचे साहित्यात (literature) नाव नाही, तर तुम्ही C++ फॉरवर्ड आणि बॅकवर्ड पासेस लिहिता आणि ते थेट इंजिनमध्ये प्लग करता. तिथे लढण्यासाठी कोणतेही Python API नाही आणि 'monkey-patching' ची गरज नाही. गणित हाच कोड आहे आणि कोड हाच इंटरफेस आहे.

सहभागी कसे व्हावे

जर तुम्हाला हे पटले असेल, तर प्रकल्पाचा संपूर्ण तपशील आणि सध्याचा रोडमॅप लेखकाच्या Dev.to पोस्टमध्ये सविस्तरपणे दस्तऐवजीकृत केला आहे. तुम्ही तपशील वाचू शकता, आतापर्यंत काय बनवले आहे ते पाहू शकता आणि नेमकी कुठे मदत हवी आहे हे समजू शकता.

प्रकल्पाचा तपशील: https://dev.to/banana_cool/building-a-native-c-ai-engine-catai-from-scratch-looking-for-collaborators-l8m

ज्यांना लगेच पुल रिक्वेस्ट (pull request) मध्ये सहभागी न होता फक्त गप्पा मारायच्या आहेत, प्रश्न विचारायचे आहेत किंवा प्रगती फॉलो करायची आहे, त्यांच्यासाठी टेलिग्राम ग्रुप देखील उपलब्ध आहे.

कम्युनिटी: https://t.me/GyaanSetuAi

खरा निष्कर्ष (The Real Takeaway)

आधुनिक AI स्टॅक एक 'ब्लॅक बॉक्स' बनला आहे. आपण फ्रेमवर्क्सकडे जादूच्या उपकरणांप्रमाणे पाहतो: डेटा आत जातो, मॉडेल बाहेर येते आणि आपण आशा करतो की डिप्लॉयमेंटच्या वेळी ही अस्पष्टता आपल्याला अडचणीत आणणार नाही. CatAI ही सोय नाकारते. अशा प्रकारे बांधणे थोडे संथ आहे. तुम्हाला अधिक कोड लिहावा लागेल, अधिक 'segfaults' डीबग करावे लागतील आणि हाय-लेव्हल फ्रेमवर्क्स तुमच्यापासून लपवत असलेल्या गृहितकांचा पुनर्विचार करावा लागेल. परंतु तुम्हाला हे देखील समजेल की मशीन नेमकी तशीच का वागते. ज्या उद्योगात प्रत्येकजण हार्डवेअरपासून दूर जाण्यासाठी (abstract away) स्पर्धा करत आहे, तिथे विरुद्ध दिशेने जाऊन थेट हार्डवेअरशी (touching the metal) जोडले जाण्यात खरा मूल्य आहे. ही समजच एखाद्याला API कॉल करणाऱ्या व्यक्तीपासून आणि सिस्टम बनवणाऱ्या व्यक्तीपासून वेगळे करते.