मैंने एक चुनौती स्वीकार की: वेनिला ONNX राउंडटाइम का उपयोग करके एक वास्तविक समय YOLOv8 वीडियो पाइपलाइन का निर्माण करें. कोई सूखा फ्रेमवर्क नहीं है. कोई पियथन बोतलें नहीं हैं. बस कच्चे सी ++ ग्रिट। चलो ईमानदार बनें: पायथन अनुसंधान प्रयोगशाला का निस्संदेह राजा है. लेकिन यदि आप एज हार्डवेयर पर एक क्रमशः तंत्रिका नेटवर्क के माध्यम से लाइव एच.264 वीडियो स्ट्रीम करने की कोशिश कर रहे हैं? मुझे हाल ही में एक सरल लक्ष्य के साथ कार्य किया गया था: एक वेनिला ONNX runtime और एक YOLOv8 विभाजन मॉडल का उपयोग करके एक वीडियो स्ट्रीम के लिए तेजी से निष्कर्ष निकालना। यहां यह है कि मैंने एक धीमी 10 एफपीएस प्रोटोटाइप को एक रॉक-स्टॉल्ड 29 एफपीएस जानवर में कैसे खींचा, और "अंतिम बॉस" बग जो मुझे रास्ते में मारना पड़ा। In reality, it was a journey through engineering hell. (मासोचिस्ट के लिए पूर्ण स्रोत कोड: वीडियो-योलो-डैश-प्रोसेसर) वीडियो-योलो-डैश प्रोसेसर FogAI सैंडबॉक्स: एकीकरण से पहले सत्यापन यह भंडारण एक स्वतंत्र खिलौना नहीं है--यह एक मैं इस वातावरण का उपयोग कड़ी मेहनत से कंप्यूटर दृष्टि के विशिष्ट मॉडल, इंजन बिल्डिंग और अनुकूलन पैटर्न का परीक्षण करने के लिए करता हूं, इससे पहले कि वे कंप्यूटर में प्रोत्साहित किए जाएं। . dedicated testbed FogAI core यदि एक रणनीति (जैसे शून्य कॉपी हार्डवेयर मानचित्रण) यहां 29 एफपीएस पर जीवित नहीं रह सकती है, तो इसमें एक औद्योगिक स्वायत्त तंत्रिका तंत्र के अंदर कोई व्यवसाय नहीं है। Previous Chapters in the FogAI Saga: Manifesto: Prompts overrated हैं. Here's How I Built a Zero-Copy Fog AI Node Without Python कैरियर की कहानी: प्रॉम्प्ट्स अत्याधुनिक हैं: मैंने पायथन के बिना एक शून्य कॉपी नब्बे एआई नोड बनाया (और यह चोट लगती है) पीड़ा का स्रोत: GitHub: NickZt/FogAi मेमोरी कॉपी टैक्स (Memory Copy Tax) अधिकांश कंप्यूटर दृष्टि प्रोटोटाइप धीरे-धीरे होते हैं क्योंकि वे स्मृति को गर्म आलू की तरह व्यवहार करते हैं। मेरी प्रारंभिक वास्तुकला "मानक" गड़बड़ी थी: FFmpeg ने H.264 को YUV हार्डवेयर प्रारूपों में डिकोड किया, इसे एक OpenCV में परिवर्तित किया (BGR) मॉडल को खिलाने के लिए, RGB छवि पर मास्क लगाया, इसे परिवर्तित YUV पर जाएं, और अंत में एन्कोडर को हिट करें। cv::Mat वापस 4K फ्रेम को संसाधित करने वाले एक ARM CPU पर, जो ओवरहेड बस चारों ओर बिट्स चलते हैं। That's three unnecessary memory copies and two heavy pixel-format conversions. 30% of your cycles मैंने इसे लागू करके फ्रेम को परिवर्तित करने के बजाय, मैंने मैप किया हार्डवेयर Y-plane (Luminance) सीधे एक OpenCV में Wrapper के लिए Zero-Copy Hardware Mapping AVFrame cv::Mat सी + + // Mapping the hardware Y-plane natively - zero memcpy, zero overhead. cv::Mat y_plane(yuvFrame->height, yuvFrame->width, CV_8UC1, yuvFrame->data, yuvFrame->linesize); // YOLO segmentation masks now inject binary modifications directly // onto the hardware Y sequence. y_plane(bbox).setTo(0, valid_mask); रूपांतरण ओवरहेड को दूर करके, मैंने पूरी तरह से सीपीयू बोतललेन को छोड़ दिया. लेकिन मैं अभी भी 23 एफपीएस पर सीमित था. Why? Mutability और Asynchronous रीऑर्डिंग प्रोफाइलिंग से पता चला कि मेरे तारों को एक अनुक्रमित मौत के पकड़ में बंद कर दिया गया था। अवलोकन साझा आंतरिक बफरों को बदलने पर निर्भर करता है. अगर मैंने सिर्फ एक ही मॉडल पर अधिक तारों को जन्म दिया, तो वे एक-दूसरे को प्रदूषित करते हैं, और सिस्टम अलग हो गया। YOLO मैं एक प्रतिस्पर्धी पूल की स्थापना की मॉडल--एक अद्वितीय ONNX मॉडल संस्करण प्रति वर्कर थ्रेड। The Fix: std::unique_ptr<YOLO_Segment> लेकिन एक पकड़ था: चूंकि श्रमिकों को अलग-अलग समय पर समाप्त किया जाता है, फ्रेम 2 फ्रेम 1 से पहले समाप्त हो सकता है, जिससे वीडियो 90 के दशक में एक कूद-कूद की तरह टूट जाता है। यह H.264 सिंक्रनाइज़ेशन को सुनिश्चित करता है। DASH video requires strict frame order. std::map सी + + // Reorder buffer logic to keep the stream sequential std::map<int64_t, FramePayload> reorderBuffer; int64_t expected_pts = 0; while (true) { auto payload = inferenceQueue.pop(); // Workers drop processed frames here reorderBuffer[payload.pts] = payload; // Emit frames only when the sequential timestamp flags align while (!reorderBuffer.empty() && reorderBuffer.begin()->first == expected_pts) { auto it = reorderBuffer.begin(); encoder.writeFrame(it->second.yuvFrame, it->second.pts); reorderBuffer.erase(it); expected_pts++; } } अंतिम बॉस: Thread Cache Thrashing कागज पर, तर्क सही था. अभ्यास में, मेरे एफपीएस मेरी टाइम-टू-इंफ़रेंस (टीटीटीआई) लाटेंस 43ms से 890ms तक बढ़ी। 10 FPS I was a victim of CPU Cache Thrashing. हालांकि मैंने अपने लॉक को अलग कर दिया था, अंतर्निहित एमएल लाइब्रेरी (OpenCV और ONNX) अपने स्वयं के आंतरिक तारों को जन्म देने से मुझे "सहायता" कर रहे थे। ONNX राउंडटाइम: डिफ़ॉल्ट है hardware_concurrency() / सत्र प्रति 2 थ्रेड. 10 कर्मचारियों के साथ, यह मेरे 20 कोर CPU पर 100+ आंतरिक थ्रेड पैदा किया। OpenCV: स्वचालित रूप से .setTo() जैसे ऑपरेशनों के लिए कर्मचारी तैनात करता है। मेरे नियुक्त कर्मचारी ONNX के थ्रेड्स से लड़ रहे थे, जो OpenCV के थ्रेडों से लड़ रहे थे। Thousands of context switches were destroying my L1/L2 caches every second. सुधार एक क्रूर "नहीं" था implicit concurrency के लिए. मैंने पुस्तकालयों को अपने तारों को जन्म देने का अधिकार से वंचित कर दिया: सी + + int main() { // Globally disable implicit OpenCV threading cv::setNumThreads(1); // Cap ONNX Runtime to a single thread per op Ort::SessionOptions session_options; session_options.SetIntraOpNumThreads(1); session_options.SetInterOpNumThreads(1); } संदर्भ स्विच शोर गायब हो गया है. मेरा सीपीयू निर्देश कैश सिंक्रनाइज़ किया गया है. पाइपलाइन तुरंत एक त्रुटिहीन हिट एक टीटीआई छत के साथ ~ 329ms। 29 FPS Ego पर रखरखाव: वेनिला रणनीति एक आम प्रश्न मैं मिलता है: "यदि आप प्रदर्शन पर इतना ध्यान केंद्रित कर रहे हैं, तो इंजन को फॉर्क क्यों न करें और खुद कोरल्स को अनुकूलित करें? जवाब है Technical Debt avoidance. यदि आप इंजन के आंतरिक को हैक करते हैं, तो आप एक अंतहीन रखरखाव चक्र के लिए साइन अप कर रहे हैं. हर बार एक नया संस्करण ताजा हार्डवेयर के लिए समर्थन के साथ गिर जाता है---जैसे (57% प्रीफिल बूस्ट) या --- आपको अपने कस्टम अनुकूलन को मैन्युअल रूप से फिर से पोर्ट करना होगा। , मैं इन हार्डवेयर अद्यतनों को बस एक संस्करण संख्या को हिट करके मुफ्त में "खेल" कर सकता हूं। ARM KleidiAI Intel DL Boost (VNNI) Vanilla Inference Engine इसी तरह, मैंने कोडिंग / डिकोडिंग पाइपलाइन को अनुकूलित करने का विकल्प नहीं चुना. क्यों? क्योंकि हार्डवेयर विक्रेताओं ने पहले से ही किया है. चाहे यह है या नहीं या उस , इन चिप्स के पास H.264 के लिए सिलिकॉन स्तर की गति है। • कोडेक को उस धातु के लिए छोड़ दें जिसके लिए वे बनाए गए थे। Intel QuickSync Rockchip VPU Zero-Copy Bridge परिणाम: अनुमान लगाना बंद करें, प्रोफाइल करना शुरू करें वास्तविक दुनिया के लिए एआई का स्केलिंग उन अवलोकन परतों को वापस खोलने की आवश्यकता होती है जिनके साथ हम बहुत आराम कर चुके हैं। यदि आप वीडियो पर भारी टेंसर प्लॉट लोड के साथ कार्य कर रहे हैं: पिक्सेल रूपांतरण को मारो - हार्डवेयर विमानों पर सीधे काम करें। अपने मॉडल को अलग करें - प्रति कर्मचारी एक उदाहरण। अनुक्रमित आउटपुट को पुनर्निर्देशित करें---आइसेनक समाप्त समय को अपने प्रवाह को तोड़ने न दें। अपनी पुस्तकालयों को कभी भी अपने स्वयं के तारों को जन्म देने न दें। बेनिला रहें - तकनीकी ऋण को कम रखने के लिए अपनी वास्तुकला, इंजन नहीं, को अनुकूलित करें। Next Next post: हम तैयारी में हैं एक शून्य कॉपी चलाने के लिए ... Grounding DINO