การเพิ่มประสิทธิภาพแบบแนะนำโปรไฟล์

การเพิ่มประสิทธิภาพตามโปรไฟล์ (PGO) เป็นการเพิ่มประสิทธิภาพคอมไพเลอร์ซึ่งเป็นที่รู้จักกันดี ใน PGO โปรไฟล์รันไทม์จากการดำเนินการของโปรแกรมจะใช้โดย คอมไพเลอร์เพื่อตัดสินใจเลือกสิ่งที่เหมาะสมที่สุดเกี่ยวกับการแทรกในบรรทัดและการจัดวางโค้ด ซึ่งนำไปสู่ ประสิทธิภาพที่ดีขึ้นและลดขนาดโค้ดลง

คุณสามารถทำให้ PGO ใช้งานได้ในแอปพลิเคชันหรือไลบรารีของคุณโดยทำตามขั้นตอนต่อไปนี้ 1. ระบุภาระงานตัวแทน 2. รวบรวมโปรไฟล์ 3. ใช้โปรไฟล์ในรุ่นที่เผยแพร่

ขั้นตอนที่ 1: ระบุภาระงานตัวแทน

ก่อนอื่นให้ระบุการเปรียบเทียบที่เป็นตัวแทนหรือภาระงานสำหรับแอปพลิเคชันของคุณ ซึ่งเป็นขั้นตอนสำคัญเนื่องจากโปรไฟล์ที่รวบรวมจากภาระงานจะระบุ ร้อนและเย็นในโค้ด เมื่อใช้โปรไฟล์ คอมไพเลอร์จะ ทำการเพิ่มประสิทธิภาพอย่างเข้มงวดและแทรกอยู่ในพื้นที่ที่มีอากาศร้อน ผู้คอมไพเลอร์ อาจเลือกที่จะลดขนาดรหัสของพื้นที่หนาวเย็น ด้านประสิทธิภาพ

การระบุปริมาณงานที่ดียังช่วยให้ติดตามประสิทธิภาพใน ทั่วไป

ขั้นตอนที่ 2: รวบรวมโปรไฟล์

การเก็บรวบรวมโปรไฟล์มี 3 ขั้นตอนดังนี้ - การสร้างโค้ดแบบเนทีฟพร้อมการวัดคุม - การเรียกใช้แอปที่มีการวัดบนอุปกรณ์และสร้างโปรไฟล์ และ - การรวม/หลังการประมวลผลโปรไฟล์ในโฮสต์

สร้างบิลด์ที่มีเครื่องดนตรี

โปรไฟล์จะรวบรวมโดยการเรียกใช้ภาระงานจากขั้นตอนที่ 1 ใน บิลด์ที่มีการวัดคุมของแอปพลิเคชัน หากต้องการสร้างบิลด์ที่มีการวัดคุม ให้เพิ่ม -fprofile-generate ไปยังแฟล็กของคอมไพเลอร์และ Linker การตั้งค่าสถานะนี้ควรเป็น ควบคุมโดยตัวแปรบิลด์ที่แยกต่างหาก เนื่องจากไม่จำเป็นต้องมี Flag ในระหว่าง บิลด์เริ่มต้น

สร้างโปรไฟล์

จากนั้นเรียกใช้แอปที่มีการวัดในอุปกรณ์แล้วสร้างโปรไฟล์ ระบบจะรวบรวมโปรไฟล์ในหน่วยความจำเมื่อเรียกใช้ไบนารีที่มีการวัดและรับ เขียนลงในไฟล์เมื่อออก แต่ฟังก์ชันที่ลงทะเบียนด้วย 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 ไปยังคอมไพเลอร์และ Linker ยังสามารถใช้โปรไฟล์ได้แม้ในขณะที่โค้ดพัฒนาขึ้น โดยคอมไพเลอร์ Clang สามารถทนต่อ แหล่งที่มาและโปรไฟล์ไม่ตรงกันเล็กน้อย

หมายเหตุ: โดยทั่วไปแล้ว โปรไฟล์สำหรับไลบรารีส่วนใหญ่จะใช้กันตามสถาปัตยกรรม เช่น โปรไฟล์ที่สร้างจากบิลด์ arm64 ของไลบรารีสามารถใช้เพื่อ สถาปัตยกรรมทั้งหมด ข้อควรระวังก็คือหากมีงานด้านสถาปัตยกรรม เส้นทางโค้ดในไลบรารี (Arm กับ x86 หรือ 32 บิตกับ 64 บิต) โปรไฟล์แยกต่างหาก ควรใช้สำหรับการกำหนดค่าดังกล่าวแต่ละรายการ

สรุปข้อมูลทั้งหมด

https://github.com/DanAlbert/ndk-ตัวอย่าง/tree/pgo/pgo แสดงการสาธิตการใช้ PGO จากแอปตั้งแต่ต้นจนจบ จะให้รางวัลเพิ่มเติม รายละเอียดคร่าวๆ ในเอกสารฉบับนี้

  • บิลด์ CMake กฎ แสดงวิธีการตั้งค่าตัวแปร CMake ที่สร้างโค้ดแบบเนทีฟพร้อมการวัดคุม เมื่อไม่ได้ตั้งค่าตัวแปรบิลด์ โค้ดเนทีฟจะได้รับการเพิ่มประสิทธิภาพโดยใช้ สร้างโปรไฟล์ PGO แล้ว
  • ในบิลด์ที่มีเครื่องดนตรี pgodemo.cpp เขียนว่าโปรไฟล์เป็นการดำเนินการสำหรับภาระงาน
  • จะได้รับตำแหน่งที่เขียนได้สำหรับโปรไฟล์ขณะรันไทม์ใน MainActivity.kt โดยใช้ applicationContext.cacheDir.toString()
  • หากต้องการดึงโปรไฟล์จากอุปกรณ์โดยไม่ต้องใช้ adb root ให้ใช้ adb สูตรอาหาร ที่นี่