إنشاء روبوت للمشاركة في كأس AI المصغر. تجربة GPU


استمرار المادة 1 والمادة 2 .


أدناه تحت الخفض ، سأتحدث عن تجربة المؤلف في استخدام GPU للحسابات ، بما في ذلك كجزء من إنشاء روبوت للمشاركة في كأس AI المصغر. ولكن بدلاً من ذلك ، هذه مقالة حول موضوع GPU.


- اسمك سحري ...
-هل تعلم ، جويل؟ .. السحر يغادر ...


في مرحلة الطفولة ، نتحدث عن العمر الذي لا تكون فيه الكيمياء جارية في المدرسة أو بدأت للتو في الظهور ، كان المؤلف مفتونًا برد الفعل المحترق ، وحدث أن والداه لم يتدخلوا معه وأضاءت موسكو القذرة بالقرب من المنزل في بعض الأحيان من خلال ومضات من أنشطة الأطفال المختلفة ، صاروخ محلي الصنع على أسود البارود ، على كراميل نترات السكر ، إلخ. حالتان حدت من تخيلات الأطفال: تحلل النتروجليسرين في المختبر المنزلي بسقف هسهسة من الأحماض والقيادة إلى غرفة الشرطة في محاولة للحصول على مواد كيميائية في إحدى مؤسسات الدفاع المنتشرة بسخاء حول منطقة مترو Aviamotornaya.


ثم ظهرت مدرسة الفيزياء مع أجهزة الكمبيوتر ياماها MSX ، آلة حاسبة MK قابلة للبرمجة في المنزل ، ولم يكن هناك وقت للكيمياء. تحولت مصالح الطفل إلى أجهزة الكمبيوتر. وما افتقر إليه المؤلف من أول معرفة بالكمبيوتر هو رد الفعل المحترق ، وكانت برامجه مشتعلة ، ولم يكن هناك هذا الإحساس بالقوة الطبيعية. يمكنك أن ترى عملية تحسين الحسابات في الألعاب ، ولكن في ذلك الوقت لم يكن المؤلف يعرف كيفية استبدال حساب sin () بجدول قيم هذه الوظيفة ، لم يكن هناك إنترنت ...


لذا ، تمكن المؤلف من الشعور بالفرح من قوة الحوسبة ، والحرق النظيف ، وأنا أستخدم GPU في الحسابات.


توجد بعض المقالات الجيدة حول الحسابات على GPU. هناك أيضًا العديد من الأمثلة على الإنترنت ، لذلك تقرر فقط الكتابة صباح يوم السبت عن المشاعر الشخصية ومن الممكن دفع الآخرين نحو التوازي الجماعي.


لنبدأ بأشكال بسيطة. تدعم حوسبة GPU العديد من الأطر ، لكن الأكثر شهرة هي NVIDIA CUDA و OpenCL. سنأخذ CUDA وعلى الفور سيتعين علينا تضييق مجموعة لغات البرمجة الخاصة بنا إلى C ++. هناك مكتبات للاتصال بـ CUDA بلغات برمجة أخرى ، على سبيل المثال ، ALEA GPU في C # ، ولكن هذا هو موضوع مقالة مراجعة منفصلة.


نظرًا لعدم قدرتهم على صنع سيارة جماعية بمحرك نفاث في وقت واحد ، على الرغم من أن بعض مؤشراتها أعلى من محرك الاحتراق الداخلي ، فإن الحسابات المتوازية لا يمكن دائمًا تطبيقها في مشاكل حقيقية. التطبيق الرئيسي للحوسبة المتوازية: تحتاج إلى مهمة تحتوي على بعض عناصر الطابع الجماعي والتعددية. في حالتنا الخاصة بإنشاء روبوت ، تقع الشبكة العصبية (الكثير من الخلايا العصبية والوصلات العصبية) تحت الكتلة ومجموعة من البوتات (حساب ديناميكيات الحركة ، التصادمات لكل روبوت تستغرق بعض الوقت ، إذا كانت الروبوتات من 300-1000 ، فإن المعالج المركزي يستسلم وستلاحظ ببطء احتراق البرنامج ، مثل فترات التوقف الطويلة بين إطارات التصور).


أفضل خيار الكتلة هو عندما لا يعتمد كل عنصر من الحسابات على نتيجة الحسابات على عنصر آخر من القائمة ، على سبيل المثال ، المهمة البسيطة لفرز صفيف متضخمة بالفعل مع جميع أنواع الحيل ، حيث يعتمد موضع الرقم في الصفيف على أرقام أخرى ولا يمكن أخذه إلى الجبهة في دورة موازية . لتبسيط الصياغة: أول علامة على الطابع الجماعي الناجح هي أنه إذا لم تكن بحاجة إلى تغيير موضع عنصر في الصفيف ، فيمكنك إجراء حسابات عليه بحرية ، واتخاذ قيم العناصر الأخرى لهذا ، ولكن لا تحركه من مكانه. شيء يشبه الحكاية الخيالية: لا تغير ترتيب العناصر ، وإلا ستتحول GPU إلى قرع.


في لغات البرمجة الحديثة ، هناك منشآت يمكن تنفيذها بالتوازي على عدة نوى لمعالج مركزي أو خيوط منطقية ويتم استخدامها على نطاق واسع ، لكن المؤلف يركز القارئ على التوازي الجماعي ، عندما يتجاوز عدد الوحدات التنفيذية مئات أو آلاف الوحدات.


ظهرت العناصر الأولى للهياكل المتوازية: دورة موازية . بالنسبة لمعظم المهام ، سيكون كافيا. بمعنى واسع ، هذا هو الجوهر
الحوسبة المتوازية.


مثال على كتابة الحلقة الرئيسية في CUDA (kernel):


int tid = blockIdx.x * blockDim.x + threadIdx.x; int threadN = gridDim.x * blockDim.x; for (int pos = tid; pos < numElements; pos += threadN) { //    pos,     ,       thread     pos.  :    thread    ,  thread   pos=1146     thread c  pos=956.        .           . } 

لقد كتب الكثير في الوثائق والمراجعات لـ CUDA ، حول كتل GPU ، حول المواضيع التي يتم إنتاجها في هذه الكتل ، وكيفية موازاة المهمة عليها. ولكن إذا كان لديك مجموعة من البيانات وتتكون بوضوح من عناصر جماعية ، فاستخدم شكل الحلقة أعلاه ، حيث إنه يشبه بصريًا الحلقة العادية في الشكل ، وهو أمر ممتع ، ولكن للأسف ليس في المحتوى.


أعتقد أن القارئ يفهم بالفعل أن فئة المهام تضيق بسرعة فيما يتعلق بالبرمجة الموازية الجماعية. إذا كنا نتحدث عن إنشاء الألعاب ، ومحركات التقديم ثلاثية الأبعاد ، والشبكات العصبية ، وتحرير الفيديو ، ومهام أخرى مماثلة ، فإن التخلص من إجراءات القارئ المستقل مهترئ بشدة ، فهناك برامج كبيرة ، وبرامج صغيرة ، وأطر عمل ، ومكتبات معروفة وغير معروفة لهذه المهام. أي أن المنطقة تبقى فقط من الموضوع ، لإنشاء صاروخ حوسبة صغير خاص بك ، وليس SpaceX و Roscosmos ، ولكن شيئًا منزليًا ، ولكنه شرير تمامًا للحسابات.



هذه صورة لصاروخ مشتعل بالكامل.


الحديث عن المهام التي لن تتمكن دورة موازية في يديك من حلها. وقد فكر مبدعو CUDA في شخص مطوري NVIDIA بالفعل في هذا الأمر.


توجد مكتبة اقتحام مفيدة في بعض الأماكن حتى يتم "عدم وجود خيارات" بشكل مختلف. بالمناسبة ، لم تجد مراجعتها الكاملة على حبري.


لفهم كيفية عملها ، عليك أولاً أن تقول ثلاث جمل حول مبادئ CUDA. إذا كنت بحاجة إلى المزيد من الكلمات ، يمكنك قراءة الرابط.


مبادئ CUDA:


يتم إجراء العمليات الحسابية على GPU ، والبرنامج هو النواة ، وعليك كتابتها في C. وتتصل النواة بدورها فقط بذاكرة GPU وعليك تحميل البيانات في ذاكرة معالج الفيديو من البرنامج الرئيسي وتحميلها مرة أخرى إلى البرنامج. تتطلب الخوارزميات المتطورة على CUDA مرونة العقل.


لذا ، فإن مكتبة Thrust تزيل الروتين وتتولى بعض المهام "المعقدة" لـ CUDA ، مثل جمع المصفوفات أو فرزها. لم تعد بحاجة إلى كتابة نواة منفصلة ، وتحميل المؤشرات في الذاكرة ، ونسخ البيانات من هذه المؤشرات إلى ذاكرة GPU. سيحدث كل الغموض أمام عينيك في البرنامج الرئيسي وبسرعة أقل قليلاً من CUDA. تمت كتابة مكتبة Thrust في CUDA ، لذلك هذا هو حقل توت واحد من حيث الأداء.


ما عليك القيام به في Thrust هو إنشاء صفيف (thrust :: vector) داخل مكتبته ، وهو متوافق مع المصفوفات العادية (std :: vector). هذا بالطبع ليس كل شيء بهذه البساطة ، لكن معنى ما قاله المؤلف مشابه للحقيقة. هناك بالفعل صفان ، أحدهما على GPU (الجهاز) ، والآخر في البرنامج الرئيسي (المضيف).


سيظهر مثال بساطة بناء الجملة (المصفوفات X و Y و Z):


 // initialize X to 0,1,2,3, .... thrust::sequence(X.begin(), X.end()); // compute Y = -X thrust::transform(X.begin(), X.end(), Y.begin(), thrust::negate<int>()); // fill Z with twos thrust::fill(Z.begin(), Z.end(), 2); // compute Y = X mod 2 thrust::transform(X.begin(), X.end(), Z.begin(), Y.begin(), thrust::modulus<int>()); // replace all the ones in Y with tens thrust::replace(Y.begin(), Y.end(), 1, 10); 

يمكنك أن ترى كيف يبدو غير ضار على خلفية إنشاء نواة CUDA ، ومجموعة الوظائف في Thrust كبيرة . بدءًا من العمل مع المتغيرات العشوائية ، والتي يتم إجراؤها في CUDA بواسطة مكتبة cuRAND منفصلة (يفضل أن يتم تشغيلها بواسطة نواة منفصلة) ، لفرز وجمع وكتابة وظائفك وفقًا لوظيفة قريبة من وظائف kernel.


المؤلف لديه خبرة قليلة في استخدام CUDA و C ++ ، شهرين. حول هذا العام عن C #. هذا ، بالطبع ، يتناقض قليلاً مع بداية المقالة حول معرفته المبكرة بأجهزة الكمبيوتر والفيزياء المدرسية والرياضيات التطبيقية كتعليم. سأقول ذلك. لكن لماذا أكتب هذه المقالة ، ليس الأمر أنني أتقنت كل شيء من هذا القبيل ، ولكن تبين أن لغة C ++ كانت لغة مريحة (كنت أخشى قليلاً من ذلك ، على خلفية المقالات في نوع Haber "وظائف لامدا → التحميل الزائد للمشغلين الداخليين ، مثل إعادة تعريف كل شيء ") ، من الواضح أن سنوات تطورها أدت إلى بيئات تطوير ودية للغاية (IDEs). اللغة نفسها في أحدث إصدار لها ، يبدو أنها تجمع القمامة من الذاكرة ، ولا أعرف كيف كانت من قبل. على الأقل ، دفعت البرامج التي كتبها المؤلف عن أبسط الخوارزميات الخوارزميات الحسابية للبوتات لأيام ولم يكن هناك تسرب للذاكرة وفشل آخر في الحمل العالي. ينطبق هذا أيضًا على CUDA ، في البداية يبدو معقدًا ، ولكنه يعتمد على مبادئ بسيطة وبالطبع من الصعب تهيئة الأماكن على GPU في الأماكن إذا كان هناك الكثير منها ، ولكن بعد ذلك سيكون لديك صاروخ صغير خاص بك ، مع دخان من بطاقة الفيديو.


من فئات الكائنات للتدريب مع GPU ، يوصي المؤلف بأتمتة الخلايا . في وقت ما كانت هناك زيادة في الشعبية والأزياء بالنسبة لهم ، ولكن الشبكات العصبية استولت بعد ذلك على عقول المطورين.
حتى:


"كل كمية في الفيزياء ، بما في ذلك الزمان والمكان ، محدودة ومتميزة."
من عدم وجود خلية خلوية.


ولكن يكون جميلًا عندما تستطيع ثلاث صيغ بسيطة إنشاء هذا:



إذا كان من المثير للاهتمام أن تقرأ عن الأتمتة الخلوية على CUDA ، اكتب في التعليقات ، سيكون هناك مادة مطبوعة لمقال صغير.
وهذا هو مصدر الأتمتة الخلوية (تحت الفيديو توجد روابط للمصادر):



يبدو لي أن فكرة كتابة مقال بعد الإفطار ، في نفس واحد ، للعمل. وقت القهوة الثاني. هل لديك قارئ عطلة نهاية أسبوع لطيفة.

Source: https://habr.com/ru/post/ar417757/


All Articles