التحسين المستند إلى الملف الشخصي

يُعد التحسين الموجَّه إلى الملف الشخصي (PGO) أسلوبًا معروفًا في تحسين برامج التجميع. في PGO، يستخدم برنامج التجميع الملفات الشخصية لوقت التشغيل من عمليات تنفيذ أحد البرامج، وذلك لاتخاذ الخيارات المثلى حول التنسيق المضمّن وتخطيط التعليمات البرمجية. ويؤدي هذا إلى تحسين الأداء وتقليل حجم الرمز.

يمكن نشر PGO في تطبيقك أو مكتبتك باتّباع الخطوات التالية: 1. تحديد عبء العمل التمثيلي. 2. جمع الملفات الشخصية 3. يمكنك استخدام الملفات الشخصية في إصدار التطبيق.

الخطوة 1: تحديد عبء العمل التمثيلي

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

من المفيد أيضًا تحديد عبء عمل جيد لتتبع الأداء بشكل عام.

الخطوة 2: جمع الملفات التجارية

وتتضمن عملية جمع الملفات الشخصية ثلاث خطوات: - إنشاء رمز برمجي أصلي باستخدام الأدوات، - تشغيل التطبيق المعدّ على الجهاز وإنشاء ملفات شخصية، - دمج/بعد معالجتها للملفات الشخصية على الجهاز المضيف.

إنشاء إصدار مبرمج

يتم جمع الملفات الشخصية عن طريق تشغيل عبء العمل من الخطوة 1 على إصدار مبرمج للتطبيق. لإنشاء إصدار موجَّه، أضِف -fprofile-generate إلى علامتَي برنامج التجميع والربط. يجب التحكّم في هذه العلامة من خلال متغيّر إصدار منفصل، لأنّ العلامة ليست مطلوبة أثناء الإصدار التلقائي.

إنشاء ملفات شخصية

بعد ذلك، شغِّل التطبيق المزوّد بأداة قياس الأداء على الجهاز وأنشئ ملفات شخصية. يتم جمع الملفات الشخصية في الذاكرة عند تشغيل البرنامج الثنائي المراقب ويتم كتابته في ملف عند الخروج. ومع ذلك، لا يتم استدعاء الوظائف المسجَّلة في atexit في تطبيقات Android، بل يتم فقط إيقاف التطبيق.

يجب أن يبذل التطبيق/عبء العمل جهدًا إضافيًا لتعيين مسار لملف الملف الشخصي ثم تشغيل كتابة الملف الشخصي بشكل صريح.

  • لضبط مسار ملف الملف الشخصي، يُرجى استدعاء __llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw. يكون %m مفيدًا عندما يكون هناك مكتبات مشتركة متعددة. يتوسع %m` إلى توقيع وحدة فريدة لهذه المكتبة، مما ينتج عنه ملف شخصي منفصل لكل مكتبة. انظر هنا للاطّلاع على محددات أخرى مفيدة للأنماط. PROFILE_DIR هو دليل يمكن الكتابة فيه من التطبيق. انظر العرض التوضيحي لاكتشاف هذا الدليل في وقت التشغيل.
  • لتشغيل كتابة ملف شخصي بشكل صريح، يمكنك استدعاء الدالة __llvm_profile_write_file.
extern "C" {
extern int __llvm_profile_set_filename(const char*);
extern int __llvm_profile_write_file(void);
}

#define PROFILE_DIR "<location-writable-from-app>"
void workload() {
  // ...
  // run workload
  // ...

  // set path and write profiles after workload execution
  __llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw");
  __llvm_profile_write_file();
  return;
}

ملاحظة: يكون إنشاء ملف الملف الشخصي أبسط إذا كان عبء العمل ثنائيًا مستقلاً، ما عليك سوى ضبط متغير بيئة LLVM_PROFILE_FILE على %t/default-%m.profraw قبل تشغيل البرنامج الثنائي.

الملفات الشخصية بعد المعالجة

تكون ملفات الملف الشخصي بتنسيق .profraw. يجب أولاً جلبها من الجهاز باستخدام adb pull. بعد الجلب، يمكنك استخدام الأداة llvm-profdata في NDK للتحويل من .profraw إلى .profdata والذي يمكن تمريره بعد ذلك إلى برنامج التحويل.

$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-profdata \
    merge --output=pgo_profile.profdata \
    <list-of-profraw-files>

استخدِم llvm-profdata وclang من إصدار NDK نفسه لتجنُّب عدم تطابق النسخة مع تنسيقات ملفات الملف الشخصي.

الخطوة 3: استخدام الملفات الشخصية لإنشاء طلب الانضمام

استخدِم الملف الشخصي من الخطوة السابقة أثناء إصدار إصدار لتطبيقك من خلال تمرير -fprofile-use=<>.profdata إلى برنامج التجميع والربط. ويمكن استخدام الملفات الشخصية حتى مع تطوّر التعليمات البرمجية، وقد يتقبّل المحول البرمجي Clang تطابقًا طفيفًا بين المصدر والملفات الشخصية.

ملاحظة: بشكل عام، في معظم المكتبات، تكون الملفات الشخصية شائعة عبر البنى. على سبيل المثال، يمكن استخدام الملفات الشخصية التي تم إنشاؤها من إصدار Arm64 للمكتبة لجميع البُنى الأساسية. تنبيه: في حال توفُّر مسارات تعليمات برمجية خاصة بالبنية في المكتبة (arm مقابل x86 أو 32 بت مقابل 64 بت)، يجب استخدام ملفات شخصية منفصلة لكل إعداد من هذا القبيل.

جمع كل شيء معًا

يعرض https://github.com/DanAlbert/ndk- sample/tree/pgo/pgo عرضًا توضيحيًا شاملاً لاستخدام PGO من أحد التطبيقات. ويقدّم هذا المستند تفاصيل إضافية تم الاطّلاع عليها في هذا المستند.

  • توضّح قواعد إنشاء CMake كيفية إعداد متغيّر CMake الذي ينشئ تعليمة برمجية أصلية باستخدام الأدوات. عند عدم ضبط متغيّر الإصدار، يتم تحسين الرموز البرمجية الأصلية باستخدام ملفات PGO التي تم إنشاؤها سابقًا.
  • في إصدار متكامل، يكتب pgodemo.cpp الملفات الشخصية هي تنفيذ عبء العمل.
  • يتم الحصول على موقع قابل للكتابة للملفات الشخصية في وقت التشغيل على MainActivity.kt باستخدام applicationContext.cacheDir.toString().
  • لسحب الملفات الشخصية من الجهاز بدون الحاجة إلى adb root، استخدِم وصفة الطعام adb هنا.