การเพิ่มประสิทธิภาพที่แนะนําโดยโปรไฟล์ (PGO) เป็นเทคนิคการเพิ่มประสิทธิภาพคอมไพเลอร์ที่รู้จักกันดี ใน PGO คอมไพเลอร์จะใช้โปรไฟล์รันไทม์จากการเรียกใช้โปรแกรมเพื่อเลือกการฝังและเลย์เอาต์โค้ดที่เหมาะสมที่สุด ซึ่งจะนำไปสู่ประสิทธิภาพที่ดีขึ้นและลดขนาดโค้ดลง
คุณสามารถใช้ PGO กับแอปพลิเคชันหรือไลบรารีได้โดยทำตามขั้นตอนต่อไปนี้ 1. ระบุภาระงานตัวแทน 2. รวบรวมโปรไฟล์ 3. ใช้โปรไฟล์ในรุ่นที่เผยแพร่
ขั้นตอนที่ 1: ระบุภาระงานที่แสดงถึง
ก่อนอื่นให้ระบุการเปรียบเทียบที่เป็นตัวแทนหรือภาระงานสำหรับแอปพลิเคชันของคุณ ขั้นตอนนี้เป็นขั้นตอนสําคัญเนื่องจากโปรไฟล์ที่รวบรวมจากภาระงานจะระบุภูมิภาคที่ร้อนและเย็นในโค้ด เมื่อใช้โปรไฟล์ คอมไพเลอร์จะดำเนินการเพิ่มประสิทธิภาพในเชิงรุกและแทรกอยู่ในพื้นที่ที่มีอากาศร้อน นอกจากนี้ คอมไพเลอร์ยังอาจเลือกลดขนาดโค้ดของภูมิภาคที่ไม่ค่อยมีการใช้งานไปพร้อมกับการลดประสิทธิภาพด้วย
การระบุปริมาณงานที่ดียังช่วยให้ติดตามประสิทธิภาพโดยทั่วไปได้ด้วย
ขั้นตอนที่ 2: รวบรวมโปรไฟล์
การรวบรวมโปรไฟล์ประกอบด้วย 3 ขั้นตอน ได้แก่ - การสร้างโค้ดเนทีฟด้วยเครื่องมือ - การเรียกใช้แอปที่มีการวัดในอุปกรณ์และการสร้างโปรไฟล์ และ - การรวม/หลังการประมวลผลโปรไฟล์ในโฮสต์
สร้างบิลด์ที่มีเครื่องมือวัด
ระบบจะรวบรวมโปรไฟล์โดยเรียกใช้เวิร์กโหลดจากขั้นตอนที่ 1 ในบิลด์ของแอปพลิเคชันที่เครื่องมือวัด หากต้องการสร้างบิลด์ที่มีเครื่องมือวัด ให้เพิ่ม -fprofile-generate
ลงใน Flag คอมไพเลอร์และ linker แฟล็กนี้ควรควบคุมโดยตัวแปรบิลด์ที่แยกต่างหาก เนื่องจากไม่จำเป็นต้องใช้แฟล็กระหว่างบิลด์เริ่มต้น
สร้างโปรไฟล์
ถัดไป ให้เรียกใช้แอปที่มีเครื่องมือวัดผลในอุปกรณ์และสร้างโปรไฟล์
ระบบจะรวบรวมโปรไฟล์ในหน่วยความจำเมื่อเรียกใช้ไบนารีที่มีเครื่องมือวัด และเขียนโปรไฟล์ลงในไฟล์เมื่อออก อย่างไรก็ตาม ระบบจะไม่เรียกใช้ฟังก์ชันที่ลงทะเบียนด้วย 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-samples/tree/pgo/pgo แสดงการสาธิตการใช้ PGO จากแอปต่างๆ ตั้งแต่ต้นจนจบ โดยจะให้รายละเอียดเพิ่มเติมโดยดูคร่าวๆ ในเอกสารฉบับนี้
- กฎการสร้าง CMake จะแสดงวิธีตั้งค่าตัวแปร CMake ที่สร้างโค้ดเนทีฟด้วยเครื่องมือวัด เมื่อไม่ได้ตั้งค่าตัวแปรการสร้าง ระบบจะเพิ่มประสิทธิภาพโค้ดเนทีฟโดยใช้โปรไฟล์ PGO ที่สร้างขึ้นก่อนหน้านี้
- ในบิลด์ที่มีเครื่องดนตรี pgodemo.cpp จะเขียนว่าโปรไฟล์เป็นการดำเนินการกับภาระงาน
- ระบบจะรับตำแหน่งที่เขียนได้สำหรับโปรไฟล์ขณะรันไทม์ใน MainActivity.kt โดยใช้
applicationContext.cacheDir.toString()
- หากต้องการดึงโปรไฟล์จากอุปกรณ์โดยไม่ต้องใช้
adb root
ให้ใช้สูตรadb
ที่นี่