ہر چند ماہ بعد اوپن سورس کمیونٹی ایک نیا AI فریم ورک متعارف کراتی ہے۔ ان میں سے اکثر بھاری C++ kernels کے گرد Python bindings کا استعمال کرتے ہیں، یا پھر وہ ایبسٹریکشن لیئرز (abstraction layers) کو اتنا زیادہ بڑھا دیتے ہیں کہ صرف رن ٹائم (runtime) کا وزن ان ماڈلز سے زیادہ ہو جاتا ہے جن کی وہ خدمت کرتے ہیں۔ CatAI اس کے برعکس سمت میں کام کرتا ہے۔ یہ مکمل طور پر C++ میں لکھا گیا ایک نیٹیو (native) AI انجن ہے، جسے ٹینسر میتھ (tensor math) سے بنیاد کے ساتھ بنایا گیا ہے۔ مقصد PyTorch کے اوپر ایک اور دوستانہ اسکن (skin) تیار کرنا نہیں ہے۔ مقصد ہارڈ ویئر کی حد سے شروع کرتے ہوئے میموری کے ہر بائٹ اور کمپیوٹ کے ہر سائیکل پر مکمل کنٹرول حاصل کرنا ہے۔

ایک اور انجن کیوں؟

اگر آپ نے پروڈکشن (production) میں کچھ بھی لانچ کیا ہے، تو آپ اس تکلیف سے واقف ہوں گے۔ ایک اسٹینڈرڈ ڈیپ لرننگ اسٹیک (deep-learning stack) کو کنٹینر میں ڈالیں اور دیکھیں کہ کیسے امیج کا سائز بڑھ کر کئی گیگا بائٹس تک پہنچ جاتا ہے۔ ڈیپینڈنسیز (Dependencies) آپس میں ٹکراتی ہیں۔ Python انٹرپریٹر لیٹنسی (latency) کا باعث بنتا ہے۔ وہ ڈسپیچر (dispatcher) جو ops کو CUDA یا CPU تک پہنچاتا ہے، ایک ایسا باریک اوور ہیڈ (overhead) پیدا کرتا ہے جسے درجنوں نییسٹڈ (nested) فریم ورکس میں گم ہونے کے بعد پروفائل کرنا ناممکن ہو جاتا ہے۔ ایج ڈیوائسز (edge devices)، ایمبیڈڈ روبوٹکس، یا لیٹنسی کے حساس بیک اینڈز کے لیے، یہ نقصان حقیقی ہے۔ ایک خالص C++ انجن درمیانی واسطے کو ختم کر دیتا ہے۔ یہ بغیر کسی گاربیج کلیکشن (garbage collection)، گلوبل انٹرپریٹر لاک (global interpreter lock)، اور زبانوں کے درمیان سیریلائزیشن (serialization) کے عمل کے، براہ راست آپریٹنگ سسٹم اور سلیکون سے بات کرتا ہے۔

CatAI اسے ایک سمجھوتہ نہیں بلکہ ایک فیچر کے طور پر دیکھتا ہے۔ یہ پروجیکٹ شروع سے (from scratch) C++ میں لکھا جا رہا ہے کیونکہ مصنف یہ فیصلہ کرنا چاہتا ہے کہ ٹینسرز (tensors) RAM میں کس طرح رہیں گے، وہ کیش ہائیرارکیز (cache hierarchies) کے ذریعے کیسے حرکت کریں گے، اور تھریڈز (threads) کے درمیان کرنلز (kernels) کو کیسے شیڈول کیا جائے گا۔ یہ خود کو تکلیف دینا نہیں ہے۔ محدود ہارڈ ویئر سے بہترین کارکردگی حاصل کرتے وقت رویے (behavior) کے قابل پیش گوئی ہونے کی ضمانت دینے کا یہی واحد طریقہ ہے۔

"From Scratch" کا اصل مطلب کیا ہے

زیادہ تر جدید فریم ورکس میں، ٹینسر میتھ کو cuDNN، oneMKL، یا MPS جیسی وینڈر لائبریریز کے غیر شفاف (opaque) کالز کے ذریعے سنبھالا جاتا ہے۔ تیزی سے کام مکمل کرنے کے لیے یہ بالکل مناسب ہے، لیکن یہ آپریشن کے میکانزم کو چھپا دیتا ہے۔ CatAI اپنا بنیادی ٹینسر میتھ اور میموری لے آؤٹ (memory layouts) خود لکھ رہا ہے۔ اس کا مطلب ہے ان بنیادی ڈیٹا اسٹرکچرز کو ڈیزائن کرنا جو ملٹی ڈائمینشنل ایریز (multi-dimensional arrays) کو رکھتے ہیں، یہ منتخب کرنا کہ strides اور offsets کا حساب کیسے لگایا جائے، اور ایکسیس پیٹرن (access pattern) کے مطابق ڈیٹا کو row-major، column-major، یا کسٹم ٹائلڈ (custom tiled) فارمیٹس میں اسٹور کرنے کا فیصلہ کرنا۔

یہ گہرا سسٹم ورک (systems work) ہے۔ جب آپ ہاتھ سے ایک میٹرکس ملٹی پلائی کرنل (matrix-multiply kernel) لکھتے ہیں، تو آپ torch.matmul کے بارے میں سوچنا چھوڑ دیتے ہیں اور L1 cache lines، رجسٹر پریشر (register pressure)، اور لوپ ٹائلنگ (loop tiling) کے بارے میں سوچنا شروع کر دیتے ہیں۔ آپ ٹارگٹ CPU کی SIMD چوڑائی کی بنیاد پر فیصلہ کرتے ہیں کہ 32x32 ٹائلز کے لیے بلاک کرنا ہے یا 64x64 کے لیے۔ آپ الیکیشنز (allocations) کو 64-بائٹ کی حدود کے مطابق ترتیب دیتے ہیں تاکہ AVX-512 لوڈز کیش لائنز کو عبور نہ کریں۔ آپ سوال کرتے ہیں کہ آیا ٹینسر اسٹوریج کے لیے std::vector صحیح کنٹینر ہے، یا آیا ایک کسٹم ایرینا الوکٹر (custom arena allocator) آپ کو پورے انفرنس گراف (inference graph) میں بہتر لوکالٹی (locality) اور زیرو فرگمنٹیشن (zero fragmentation) فراہم کرتا ہے۔

میموری لے آؤٹ بھی اتنا ہی اہم ہے۔ ایک سادہ n-dimensional array کارکردگی کو تباہ کر سکتا ہے اگر channels-last امیج ڈیٹا کو channels-first پیٹرن میں استعمال کیا جائے۔ CatAI میں، یہ لے آؤٹس "فرسٹ کلاس سٹیزنز" (first-class citizens) ہیں، نہ کہ ایکسپورٹ کے وقت چلنے والے گراف آپٹیمائزر کے ذریعے سنبھالے جانے والے بعد کے خیالات۔

آپٹیمائزیشن کا طرزِ فکر

بیئر میٹل آپٹیمائزیشن (Bare-metal optimization) ایک محض اصطلاح معلوم ہوتی ہے جب تک کہ آپ نینو سیکنڈز گننا شروع نہ کر دیں۔ اس کا مطلب ہے آپریشنز کو اس طرح فیوز (fuse) کرنا کہ درمیانی نتائج کبھی بھی CPU رجسٹرز یا L1 کیش سے باہر نہ نکلیں۔ اس کا مطلب ہے layer-norm کے بعد GELU کو ایک ہی کرنل کے طور پر نافذ کرنا، جس سے DRAM تک کا پورا راؤنڈ ٹرپ بچ جاتا ہے۔ اس کا مطلب ہے OpenMP کے ڈیفالٹس پر انحصار کرنے کے بجائے اپنا تھریڈ پول (thread pool) خود لکھنا، کیونکہ آپ جانتے ہیں کہ آپ کا ورک لوڈ اچانک بڑھنے والا (bursty) ہے اور آپ نہیں چاہتے کہ رن ٹائم ہر فارورڈ پاس (forward pass) کے دوران تھریڈز کو پیدا اور جوڑتا رہے۔

اس کا مطلب یہ بھی ہے کہ یہ سمجھنا کہ اسمبلی کب نہیں لکھنی چاہیے۔ بعض اوقات کمپائلر ہاتھ سے لکھے گئے intrinsics کے مقابلے میں لوپ کو بہتر طریقے سے ویکٹرائز (vectorize) کرتا ہے۔ اس کا نظم و ضبط پیمائش ہے: پروفائل کریں، مفروضہ لگائیں، ایک متغیر (variable) تبدیل کریں، اور دوبارہ پروفائل کریں۔ یہ انجن ان لوگوں کے ذریعے بنایا جا رہا ہے جو اس محنت سے لطف اندوز ہوتے ہیں۔ اگر آپ نے کبھی کسی بیچ (batch) سے دو ملی سیکنڈ کم کرنے کے لیے کنولوشن لوپ (convolution loop) کو دوبارہ لکھنے میں دوپہر گزاری ہے، تو آپ پہلے ہی اس کلچر کو سمجھتے ہیں۔

ہمیں کن کی ضرورت ہے

یہ کوئی ایک شخص کا کام نہیں ہے۔ زیرو سے بیک اینڈ بنانے کے لیے ایسی منفرد مہارتوں کی ضرورت ہوتی ہے جو شاذ و نادر ہی ایک ہی ذہن میں یکجا ہوتی ہیں۔ اگر آپ یہ پڑھ رہے ہیں اور اس میں شامل ہونے پر غور کر رہے ہیں، تو یہاں وہ جگہیں ہیں جہاں آپ فٹ ہو سکتے ہیں:

  • C++ ڈویلپرز جو جدید معیار (modern standards) سے واقف ہیں لیکن یہ بھی جانتے ہیں کہ کب ٹیمپلیٹس (templates) کی وجہ سے کمپلیشن بلوٹ (compilation bloat) ہوتا ہے۔ آپ ضرورت پڑنے پر را پوائنٹرز (raw pointers) اور مناسب جگہوں پر اسمارٹ پوائنٹرز (smart pointers) کے استعمال میں مہارت رکھتے ہوں، اور آپ کو سنٹیکس شوگر (syntax sugar) کی طرح بائنری سائز کی بھی اتنی ہی فکر ہو۔

  • ریاضی کے ماہرین جو غیر معیاری ایکٹیویشنز (non-standard activations) کے لیے بیک ورڈ پاس گریڈینٹس (backward-pass gradients) اخذ کر سکیں، مکسڈ پریسیژن ٹریننگ (mixed-precision training) میں عددی استحکام (numerical stability) کے بارے میں سوچ سکیں، اور الگورتھم کو کوڈ بننے سے پہلے ہی بہتر (optimize) بنا سکیں۔ اگر آپ یہ سمجھا سکتے ہیں کہ log-sum-exp ٹرک کیوں اہم ہے، تو آپ بالکل صحیح ذہنی سطح پر ہیں۔

  • لو-لیول میموری کے ماہرین جو الوکیشنرز (allocators)، پیج فالٹس (page faults)، اور NUMA ٹوپولوجی کے بارے میں سوچتے ہوں۔ انجن کو گراف ایگزیکیوشن کے لیے میموری پولز (memory pools)، کرنلز (kernels) کے لیے اسکریچ بفرز (scratch buffers)، اور ٹریننگ کے مراحل کے دوران ٹینسر اسٹوریج کو بغیر کسی لیک یا فرگمنٹیشن (leaking or fragmenting) کے دوبارہ استعمال کرنے کی حکمت عملیوں کی ضرورت ہے۔

  • سسٹم انجینئرز جو سمجھتے ہیں کہ ایک غلط سسٹم کال (syscall) کس طرح پورے ٹریننگ لوپ کو روک سکتی ہے۔ شیڈولنگ، I/O، اور سنکرونائزیشن پرائمٹیوز (synchronization primitives) وہ جوڑ ہیں جو ریاضی کو ایک ساتھ جوڑے رکھتے ہیں۔

آپ کو ان چاروں شعبوں میں عالمی سطح کا ماہر ہونے کی ضرورت نہیں ہے۔ زیادہ تر حصہ دار (contributors) ایک کرنل یا ایک الوکیشنر سے آغاز کریں گے اور جیسے جیسے آرکیٹیکچر مستحکم ہوگا، باقی چیزیں سیکھتے جائیں گے۔

آرکیٹیکچر اور کسٹم میتھ (Architecture and Custom Math)

بیک اینڈ لاجک مل کر بنائی جا رہی ہے، اور اس کا آغاز آرکیٹیکچر کے مباحثوں سے ہوتا ہے۔ کیا انجن ایک اسٹیٹک کمپیوٹیشن گراف (static computation graph) استعمال کرے گا، جہاں رن ٹائم سے پہلے پورے ماڈل کو ڈیفائن اور آپٹیمائز کیا جاتا ہے؟ یا یہ خودکار تفریق (automatic differentiation) کے لیے ٹیپ (tape) کے ساتھ ایگر ایگزیکیوشن (eager execution) کو سپورٹ کرے گا؟ خودکار تفریق (autodiff) کو کیسے ظاہر کیا جائے گا—آپریٹر اوور لوڈنگ (operator overloading)، سورس ٹرانسفارمیشن (source transformation)، یا گراف IR؟ یہ فیصلے باقی سب کچھ تشکیل دیتے ہیں۔

کسٹم نیورل نیٹ میتھ کا مطلب صرف معیاری لیئرز (standard layers) کو دوبارہ نافذ کرنا نہیں ہے۔ اس کا مطلب نئے لیئرز ایجاد کرنے کی آزادی ہے۔ اگر آپ کسی غیر معیاری سپارس کرنل (sparse kernel) کے ساتھ کنولوشن ویریئنٹ (convolution variant) یا ایسا ایکٹیویشن فنکشن چاہتے ہیں جس کا لٹریچر میں کوئی نام نہ ہو، تو آپ C++ کے فارورڈ اور بیک ورڈ پاس لکھتے ہیں اور انہیں براہ راست انجن میں شامل کر دیتے ہیں۔ وہاں لڑنے کے لیے کوئی Python API نہیں ہے، اور نہ ہی منکی پیچنگ (monkey-patching) کی ضرورت ہے۔ ریاضی ہی کوڈ ہے، اور کوڈ ہی انٹرفیس ہے۔

کیسے شامل ہوں (How to Get Involved)

اگر یہ آپ کو متاثر کرتا ہے، تو پروجیکٹ کی مکمل تفصیلات اور موجودہ روڈ میپ مصنف کی 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 اسٹیک ایک بلیک باکس (black box) بن چکا ہے۔ ہم فریم ورکس کو جادوئی آلات کی طرح استعمال کرتے ہیں: ڈیٹا اندر جاتا ہے، ماڈل باہر آتا ہے، اور ہم امید کرتے ہیں کہ ڈیپلائمنٹ (deployment) کے وقت اس کی غیر شفافیت (opacity) ہمیں نقصان نہیں پہنچائے گی۔ CatAI اس سکون کو مسترد کرتا ہے۔ اس طرح اسے بنانا سست ہے۔ آپ کو زیادہ کوڈ لکھنا پڑے گا، زیادہ سیگ فالٹس (segfaults) کو ڈی بگ کرنا پڑے گا، اور ان مفروضوں پر دوبارہ غور کرنا پڑے گا جنہیں ہائیر-لیول فریم ورکس آپ سے چھپاتے ہیں۔ لیکن آپ یہ بھی سمجھ سکیں گے کہ مشین اسی طرح کیوں کام کرتی ہے۔ ایک ایسی صنعت میں جہاں ہر کوئی ہارڈ ویئر کو نظر انداز (abstract away) کرنے کی دوڑ میں ہے، وہاں اس کے بالکل برعکس سمت میں جانا اور ہارڈ ویئر کے قریب ترین کام کرنا (touching the metal) اصل اہمیت رکھتا ہے۔ یہی وہ سمجھ ہے جو کسی ایسے شخص کو جو صرف APIs استعمال کرتا ہے، اس سے الگ کرتی ہے جو سسٹم بناتا ہے۔