
مقدمة
مرحبا عزيزي خبروفيتيس!
تم ربط السنتين الأخيرتين من عملي في
Synesis ارتباطًا وثيقًا بعملية إنشاء وتطوير
Synet - وهي مكتبة مفتوحة لتشغيل الشبكات العصبية التلافيفية المُدرَّبة مسبقًا على وحدة المعالجة المركزية. خلال عملية هذا العمل ، اضطررت إلى مواجهة عدد من النقاط المثيرة للاهتمام التي تتعلق بتحسين خوارزميات انتشار الإشارة المباشرة في الشبكات العصبية. يبدو لي أن وصف هذه النقاط سيكون مثيراً للاهتمام لقراء هبراهار. ما أريد تكريس سلسلة من مقالاتي. تعتمد مدة الدورة على اهتمامك بهذا الموضوع ، وبالطبع على قدرتي على التغلب على الكسل. أريد أن أبدأ الدورة مع وصف إطار
الدراجة نفسه. سيتم الكشف عن أسئلة الخوارزميات التي تكمن وراءها في مقالات لاحقة:
- طبقة الالتفاف: تقنيات تحسين الضرب بالمصفوفة
- طبقة تلافيفية: الإلتواء السريع وفقًا لطريقة شموئيل فينوغراد
إجابات على الأسئلة
قبل البدء في وصف مفصل للإطار ، سأحاول الإجابة فورًا على عدد من الأسئلة التي قد يطرحها القراء. تشير التجربة إلى أنه من الأفضل القيام بذلك مقدمًا ، حيث يبدأ الكثيرون على الفور في كتابة تعليقات غاضبة ، دون قراءة حتى النهاية.
السؤال الأول الذي ينشأ عادة في مثل هذه الحالات:
من الذي يدير الشبكات على المعالجات التقليدية الآن ، متى توجد مسرعات الرسومات ومسرعات المصفوفات (المصفوفة)؟سأجيب عن ذلك بنعم - ليس من المستحسن حقًا إجراء تدريب على الشبكات العصبية على وحدة المعالجة المركزية ، ولكن تشغيل الشبكات العصبية الجاهزة يعد مطلبًا كبيرًا ، خاصة إذا كانت الشبكة صغيرة بدرجة كافية. قد تكون أسباب ذلك مختلفة ، ولكن الأسباب الرئيسية:
- وحدات المعالجة المركزية هي أكثر شيوعا. ليس كل الأجهزة لديها GPU ، وخاصة الخوادم.
- على الشبكات العصبية الصغيرة ، المكاسب من استخدام GPU صغيرة ، وأحيانًا غائبة تمامًا.
- يتطلب إشراك وحدة معالجة الرسومات (GPU) بشكل فعال لتسريع الشبكات العصبية عادةً بنية تطبيق أكثر تعقيدًا.
السؤال التالي المحتمل:
لماذا استخدم حلًا متخصصًا لبدء التشغيل عند وجود Tensorflow أو Caffe أو MXNet ؟يمكنك الإجابة على ما يلي:
- مجموعة متنوعة من الأطر ليست جيدة دائمًا - لذلك إذا كان هناك العديد من النماذج المدربة على أطر مختلفة في المشروع ، فسيتعين عليك تضمينها جميعًا في حل جاهز ، وهو أمر غير مريح للغاية.
- تم تصميم الأطر الكلاسيكية لتدريب نماذج GPU - وهي بالتأكيد جيدة في ذلك! ولكن لتشغيل نماذج مدربة على وحدة المعالجة المركزية ، تكون وظائفها ضرورية وليست مثالية.
- تأكيد الحاجة إلى حل متخصص هو شعبية OpenVINO - إطار عمل من Intel ، والذي يؤدي نفس الوظيفة.
هنا على الفور يطرح سؤال منطقي حول اختراع الدراجة:
لماذا تستخدم حرفتك عندما يكون هناك حل احترافي تمامًا من قائد عالمي معترف به؟جوابي هو:
- في بداية العمل على Synet ، كان OpenVINO لا يزال في بدايته. وفي الحقيقة ، إذا كان OpenVINO في ذلك الوقت في حالته الحالية ، فعندئذ مع درجة عالية من الاحتمال ، لن أشارك في مشروعي الخاص.
- يمكنك تكييف إطارك الخاص مع احتياجاتك. لذلك في حالتي ، كان الشرط الرئيسي هو الحد الأقصى لأداء الخيوط المفردة.
- يمكنك تقديم الدعم للوظيفة الجديدة بأسرع ما يمكن إذا كنت في حاجة إليها فجأة (على سبيل المثال ، قم بإضافة طبقة جديدة والتخلص من خطأ في الأداء).
- سهل الاندماج في حل جاهز.
- تشغيل المكتبة على الأنظمة الأساسية بخلاف x86 / x86_64 - على سبيل المثال ، على ARM.
من المحتمل أن يكون لدى القراء أسئلة أو اعتراضات أخرى - لكن ما زلت لا أستطيع التنبؤ بها ، وبالتالي سأجيب عليها في التعليقات على المقال. في غضون ذلك ، دعونا نبدأ بوصف مباشر لـ Synet.
Synet وصف قصير
Synet هو مكتوب في
C ++ ويحتوي فقط على
ملفات الرأس . يتم تنفيذ تحسينات خاصة
بالنظام الأساسي منخفضة المستوى في
Simd ، وهو مشروع مفتوح المصدر آخر مخصص لتسريع معالجة الصور على وحدة المعالجة المركزية. وهذه هي التبعية الخارجية الوحيدة لـ Synet (تم اختيار مثل هذا المخطط لتسهيل دمج المكتبة في مشاريع الجهات الخارجية). لإطلاق الشبكات العصبية ، يتم استخدام نماذج من التنسيق الداخلي الخاص بها.

يتم تحويل النماذج المدربة مسبقًا إلى التنسيق الداخلي وفقًا لمخطط من خطوتين: 1) أولاً ، قم بتحويل النموذج إلى تنسيق محرك الاستدلال (جيد
OpenVINO لديه كل
الأدوات اللازمة لهذا). 2) ثم ، من هذا التمثيل الوسيط ، قم بالتحويل مباشرة إلى تنسيق Synet الداخلي.

يحتوي نموذج Synet على ملفين: 1) * .XML - ملف مع وصف لبنية النموذج. 2) * .BIN - ملف مع الأوزان المدربة.

مثال Synet
فيما يلي مثال لاستخدام Synet للكشف عن الوجوه. يؤخذ نموذج محرك الاستدلال الأصلي
هنا .
#define SYNET_SIMD_LIBRARY_ENABLE #include "Synet/Network.h" #include "Synet/Converters/InferenceEngine.h" #include "Simd/SimdDrawing.hpp" typedef Synet::Network<float> Net; typedef Synet::View View; typedef Synet::Shape Shape; typedef Synet::Region<float> Region; typedef std::vector<Region> Regions; int main(int argc, char* argv[]) { Synet::ConvertInferenceEngineToSynet("ie_fd.xml", "ie_fd.bin", true, "synet.xml", "synet.bin"); Net net; net.Load("synet.xml", "synet.bin"); net.Reshape(256, 256, 1); Shape shape = net.NchwShape(); View original; original.Load("faces_0.ppm"); View resized(shape[3], shape[2], original.format); Simd::Resize(original, resized, ::SimdResizeMethodArea); net.SetInput(resized, 0.0f, 255.0f); net.Forward(); Regions faces = net.GetRegions(original.width, original.height, 0.5f, 0.5f); uint32_t white = 0xFFFFFFFF; for (size_t i = 0; i < faces.size(); ++i) { const Region & face = faces[i]; ptrdiff_t l = ptrdiff_t(face.x - face.w / 2); ptrdiff_t t = ptrdiff_t(face.y - face.h / 2); ptrdiff_t r = ptrdiff_t(face.x + face.w / 2); ptrdiff_t b = ptrdiff_t(face.y + face.h / 2); Simd::DrawRectangle(original, l, t, r, b, white); } original.Save("annotated_faces_0.ppm"); return 0; }
نتيجة للمثال ، يجب أن تظهر صورة ذات وجوه مشروحة:

الآن لنأخذ مثالاً على الخطوات:
- أولاً ، يتم تحويل النموذج من تنسيق Inference Engine إلى Synet:
Synet::ConvertInferenceEngineToSynet("ie_fd.xml", "ie_fd.bin", true, "synet.xml", "synet.bin");
في الواقع ، تتم هذه الخطوة مرة واحدة ، ثم يتم استخدام النموذج المحول بالفعل في كل مكان. - تنزيل النموذج المحول:
Net net; net.Load("synet.xml", "synet.bin");
- خطوة اختيارية لتغيير حجم صورة الإدخال والدُفعة (بشكل طبيعي ، يجب أن يدعم النموذج تغيير حجم صورة الإدخال):
net.Reshape(256, 256, 1);
- تحميل صورة وإدخالها في حجم إدخال النموذج:
View original; original.Load("faces_0.ppm"); View resized(net.NchwShape()[3], net.NchwShape()[2], original.format); Simd::Resize(original, resized, ::SimdResizeMethodArea);
- تحميل الصورة في النموذج:
net.SetInput(resized, 0.0f, 255.0f);
- بدء نشر إشارة مباشرة في الشبكة:
net.Forward();
- الحصول على مجموعة من المناطق ذات الوجوه التي تم العثور عليها:
Regions faces = net.GetRegions(original.width, original.height, 0.5f, 0.5f);
مقارنة الأداء
قد لا يكون من الصحيح تمامًا مقارنة Synet مع الأطر الكلاسيكية للتعلم الآلي ، على سبيل المثال ، يتجاوزهم Inference Engine
عدة مرات في عدد من الاختبارات .
لذلك ، فيما يلي مثال على مقارنة الأداء المفرد لمؤشر Inference Engine (منتج ذو وظائف مماثلة) و Synet على عينة من
مجموعة من النماذج المفتوحة :
كما يتضح من الجدول ، في هذه الاختبارات على جهاز يدعم AVX2 (i7-6700) ، يتوافق أداء Synet عمومًا مع أداء Inference Engine (على الرغم من أنه يختلف اختلافًا كبيرًا من طراز إلى آخر). على جهاز مزود بدعم AVX-512 (i9-7900X) ، يكون أداء Synet أعلى بنسبة 25٪ في المتوسط من أداء محرك الاستدلال.
تم إجراء جميع القياسات بواسطة تطبيق الاختبار ، والذي يوجد في Synet. لذلك ، إذا رغبت في ذلك ، سيتمكن القراء من إعادة إنتاج الاختبارات بأنفسهم:
git clone -b master --recurse-submodules -v https://github.com/ermig1979/Synet.git synet cd synet ./build.sh inference_engine ./test.sh
مزايا وعيوب
سأبدأ مع الايجابيات:
- المشروع صغير الحجم ، ويتم تنفيذه بسهولة في مشاريع الطرف الثالث.
- يُظهر أداء أحادي الترابط.
- يعمل على المعالجات المتنقلة (يدعم ARM-NEON).
حسنا وسلبيات ، حيث بدونهم:
- لا يوجد دعم ل GPU وغيرها من المعجلات الخاصة.
- سوء توحيد مهمة واحدة على وحدات المعالجة المركزية متعددة النواة.
- لا يوجد دعم ل INT8 (تكميم الأوزان).
استنتاج
يتم استخدام Synet حاليًا كجزء من مشروع
Kipod ، وهو نظام أساسي قائم على السحابة لتحليلات الفيديو. ربما لديه مستخدمين آخرين ، ولكن هذا ليس بالتأكيد :). في المستقبل ، مع تطور المشروع ، أود أن أضيف الأشياء التالية إليه:
- دعم نماذج جديدة ، طبقات ، خوارزميات.
- دعم العمليات الحسابية الصحيحة بتنسيق INT8 (الأوزان الكمية).
- دعم الحوسبة GPU.
- تحويل من تنسيق ONNX.
هذه القائمة أبعد ما تكون عن الاكتمال ، وأود أن أكملها مع مراعاة رأي المجتمع - لذلك أنا في انتظار ملاحظاتك! لجعل الأداة مفيدة ليس فقط لشركتنا ، ولكن أيضًا لمجموعة واسعة من المستخدمين. أيضًا ، لن يرفض المؤلف مساعدة المجتمع في عملية التطوير.
عند وصف Synet ، الذي قمت بإعداده في هذه المقالة ، لم أتعمد الخوض في تفاصيل تطبيقه الداخلي - هناك الكثير من الخوارزميات اللذيذة تحت الغطاء ، لكنني أود الكشف عن تفاصيل تنفيذها في المقالات التالية من السلسلة:
- طبقة الالتفاف: تقنيات تحسين الضرب بالمصفوفة
- طبقة تلافيفية: الإلتواء السريع وفقًا لطريقة شموئيل فينوغراد