প্রোফাইল-গাইডেড অপ্টিমাইজেশন ব্যবহার করা

Android 13 ও এর আগের যেকোনও ভার্সনের জন্য Android বিল্ড সিস্টেম, ব্লুপ্রিন্ট বিল্ড নিয়ম আছে এমন নেটিভ Android মডিউলে Clang-এর প্রোফাইল-গাইডেড অপ্টিমাইজেশন (PGO) ব্যবহার করার সুবিধা দেয়। এই পৃষ্ঠায় Clang PGO, PGO-এর জন্য ব্যবহৃত প্রোফাইল কীভাবে ক্রমাগত জেনারেট ও আপডেট করতে হয় এবং কীভাবে বিল্ড সিস্টেমের সাথে PGO ইন্টিগ্রেট করতে হয় (ইউজ কেস সহ) তা বর্ণনা করা হয়েছে।

NB: এই ডকুমেন্ট Android প্ল্যাটফর্মে PGO-এর ব্যবহার বর্ণনা করে। Android অ্যাপ থেকে PGO ব্যবহার করার ব্যাপারে জানতে, এই পৃষ্ঠা দেখুন।

Clang PGO সম্পর্কে

Clang দুই ধরনের প্রোফাইল ব্যবহার করে প্রোফাইল-নির্দেশিত অপ্টিমাইজেশন করতে পারে:

  • ইনস্ট্রুমেন্টেশন-ভিত্তিক প্রোফাইল কোনও ইনস্ট্রুমেন্টেড টার্গেট প্রোগ্রাম থেকে তৈরি করা হয়। এই প্রোফাইলগুলি বিস্তারিত এবং উচ্চ রানটাইম ওভারহেড আরোপ করে।
  • স্যাম্পলিং-ভিত্তিক প্রোফাইল সাধারণত স্যাম্পলিং হার্ডওয়্যার কাউন্টার তৈরি করে। এগুলি রানটাইম ওভারহেড কম করে এবং বাইনারিতে কোনও ইন্সট্রুমেন্টেশন বা পরিবর্তন না করেই সংগ্রহ করা যেতে পারে। এগুলি ইনস্ট্রুমেন্টেশন-ভিত্তিক প্রোফাইলের তুলনায় কম বিস্তারিত হয়।

সব প্রোফাইল এমন একটি প্রতিনিধিত্বমূলক ওয়ার্কলোড থেকে তৈরি করা উচিত যা অ্যাপের সাধারণ আচরণকে কাজে লাগায়। Clang, AST-ভিত্তিক (-fprofile-instr-generate) এবং LLVM IR-ভিত্তিক (-fprofile-generate), Android শুধুমাত্র LLVM IR-ভিত্তিক ইন্সট্রুমেন্টেশন-ভিত্তিক PGO-এর জন্য কাজ করে।

প্রোফাইল কালেকশন তৈরি করার জন্য নিম্নলিখিত ফ্ল্যাগ প্রয়োজন:

  • -fprofile-generate IR-ভিত্তিক ইন্সট্রুমেন্টেশনের জন্য। এই বিকল্পের সাহায্যে, ব্যাকএন্ড, ইন্সট্রুমেন্টেশন পয়েন্টের সংখ্যা কমাতে এবং কম-ওয়েট এজে (লিঙ্ক স্টেপের জন্যও এই বিকল্প ব্যবহার করুন) সেগুলির প্লেসমেন্ট অপ্টিমাইজ করতে ওয়েটেড মিনিমাল স্প্যানিং ট্রি অ্যাপ্রোচ ব্যবহার করে। Clang ড্রাইভার অটোমেটিক প্রোফাইলিং রানটাইম (libclang_rt.profile-arch-android.a) লিঙ্কারে পাস করে। প্রোগ্রাম বন্ধ হয়ে গেলে ডিস্কে প্রোফাইল লেখার রুটিন এই লাইব্রেরিতে থাকে।
  • ন্যূনতম ডিবাগ তথ্য তৈরি করতে স্যাম্পলিং-ভিত্তিক প্রোফাইল সংগ্রহের জন্য -gline-tables-only।

ইনস্ট্রুমেন্টেশন-ভিত্তিক এবং স্যাম্পেলিং-ভিত্তিক প্রোফাইলের জন্য যথাক্রমে -fprofile-use=pathname বা -fprofile-sample-use=pathname ব্যবহার করে PGO-এর জন্য প্রোফাইল ব্যবহার করা যেতে পারে।

মনে রাখবেন: কোডে পরিবর্তন করা হলে, Clang যদি আর প্রোফাইল ডেটা ব্যবহার করতে না পারে, তাহলে এটি একটি -Wprofile-instr-out-of-date সতর্কতা দেখায়।

PGO ব্যবহার করুন

PGO ব্যবহার করার মধ্যে নিম্নলিখিত ধাপগুলি পড়ে:

  1. কম্পাইলার ও লিঙ্কারকে -fprofile-generate পাস করে ইন্সট্রুমেন্টেশন সহ লাইব্রেরি/এক্সিকিউটেবল তৈরি করুন।
  2. ইনস্ট্রুমেন্টেড বাইনারিতে প্রতিনিধিমূলক ওয়ার্কলোড রান করিয়ে প্রোফাইল সংগ্রহ করুন।
  3. llvm-profdata ইউটিলিটি ব্যবহার করে প্রোফাইল পোস্ট-প্রসেস করুন (বিস্তারিত জানতে, LLVM প্রোফাইল ফাইল ম্যানেজ করা দেখুন)।
  4. কম্পাইলার ও লিঙ্কারকে -fprofile-use=<>.profdata পাস করে PGO প্রয়োগ করতে প্রোফাইল ব্যবহার করুন।

Android-এ PGO-এর জন্য, প্রোফাইল অফলাইনে সংগ্রহ করতে হবে এবং পুনরুৎপাদনযোগ্য বিল্ড নিশ্চিত করতে কোডের সাথে চেক করতে হবে। কোড উন্নত হওয়ার সাথে সাথে প্রোফাইল ব্যবহার করা যেতে পারে, তবে তা পর্যায়ক্রমে (অথবা Clang যখনই সতর্ক করে যে প্রোফাইলগুলি পুরনো হয়ে গেছে) আবার তৈরি করতে হবে।

প্রোফাইল সংগ্রহ করা

Clang, লাইব্রেরির ইন্সট্রুমেন্টেড বিল্ড ব্যবহার করে বেঞ্চমার্ক চালানোর মাধ্যমে অথবা বেঞ্চমার্ক চালানোর সময় হার্ডওয়্যার কাউন্টার স্যাম্পেল করার মাধ্যমে সংগ্রহ করা প্রোফাইল ব্যবহার করতে পারে। এই মুহূর্তে, Android স্যাম্পেল-ভিত্তিক প্রোফাইল সংগ্রহ করার সুবিধা দেয় না, তাই আপনাকে অবশ্যই ইন্সট্রুমেন্টেড বিল্ড ব্যবহার করে প্রোফাইল সংগ্রহ করতে হবে:

  1. বেঞ্চমার্ক ও সেই বেঞ্চমার্কের মাধ্যমে সম্মিলিতভাবে ব্যবহৃত লাইব্রেরির সেট শনাক্ত করুন।
  2. বেঞ্চমার্ক ও লাইব্রেরিতে pgo প্রপার্টি যোগ করুন (নিচে বিবরণ দেওয়া হল)।
  3. এইসব লাইব্রেরির ইনস্ট্রুমেন্টেড কপি সহ Android বিল্ড তৈরি করুন ব্যবহার করে:
    make ANDROID_PGO_INSTRUMENT=benchmark

benchmark হল একটি প্লেসহোল্ডার যা বিল্ডের সময় ইন্সট্রুমেন্ট করা লাইব্রেরির সংগ্রহকে শনাক্ত করে। প্রকৃত প্রতিনিধি ইনপুট (এবং সম্ভবত অন্য কোনও এক্সিকিউটেবল যা কোনও লাইব্রেরির বিরুদ্ধে লিঙ্ক করে বেঞ্চমার্ক করা হচ্ছে) PGO-এর জন্য নির্দিষ্ট নয় এবং এই ডকুমেন্টের স্কোপের বাইরে।

  1. কোনও ডিভাইসে ইন্সট্রুমেন্টেড বিল্ড ফ্ল্যাশ বা সিঙ্ক করুন।
  2. প্রোফাইল সংগ্রহ করতে বেঞ্চমার্ক রান করুন।
  3. সোর্স ট্রি-তে চেক-ইন করার জন্য প্রোফাইল পোস্ট-প্রসেস করে রেডি করতে llvm-profdata টুল (নিচে আলোচনা করা হয়েছে) ব্যবহার করুন।

বিল্ড চলাকালীন প্রোফাইল ব্যবহার করা

Android ট্রিতে toolchain/pgo-profiles প্রোফাইল চেক করুন। লাইব্রেরির জন্য pgo প্রপার্টির profile_file সাব-প্রপার্টিতে যা উল্লেখ করা আছে, নামের সাথে সেটি মিলতে হবে। লাইব্রেরি তৈরি করার সময় বিল্ড সিস্টেম অটোমেটিক Clang-এ প্রোফাইল ফাইল পাঠায়। ANDROID_PGO_DISABLE_PROFILE_USE এনভায়রনমেন্ট ভেরিয়েবলকে true হিসেবে সেট করে সাময়িকভাবে PGO বন্ধ করা এবং এর পারফর্ম্যান্স সংক্রান্ত সুবিধা পরিমাপ করা যেতে পারে।

প্রোডাক্ট-নির্দিষ্ট অতিরিক্ত প্রোফাইল ডিরেক্টরি উল্লেখ করতে, BoardConfig.mk-এ PGO_ADDITIONAL_PROFILE_DIRECTORIES মেক ভেরিয়েবলে সেগুলি যোগ করুন। অতিরিক্ত পাথ নির্দিষ্ট করা থাকলে, এইসব পাথের প্রোফাইল toolchain/pgo-profiles-এর প্রোফাইলকে ওভাররাইড করে।

dist টার্গেট ব্যবহার করে রিলিজ ইমেজ তৈরি করার সময় make, বিল্ড সিস্টেম অনুপস্থিত প্রোফাইল ফাইলের নাম $DIST_DIR/pgo_profile_file_missing.txt-এ লেখে। কোন প্রোফাইল ফাইল ভুলবশত ড্রপ করা হয়েছে (যা নীরবে PGO বন্ধ করে দেয়) তা দেখতে আপনি এই ফাইল চেক করতে পারেন।

Android.bp ফাইলে PGO চালু করুন

নেটিভ মডিউলের জন্য Android.bp ফাইলে PGO চালু করতে, শুধু pgo প্রপার্টি উল্লেখ করুন। এই প্রপার্টিতে নিম্নলিখিত সাব-প্রপার্টি আছে:

প্রপার্টি বিবরণ
instrumentation ইনস্ট্রুমেন্টেশন ব্যবহার করে PGO-এর জন্য true-এ সেট করুন। ডিফল্ট হল false।
sampling স্যাম্পেলিং ব্যবহার করে PGO-এর জন্য true হিসেবে সেট করুন। ডিফল্ট হল false.
benchmarks স্ট্রিংয়ের তালিকা। ANDROID_PGO_INSTRUMENT বিল্ড বিকল্পে তালিকায় থাকা কোনও বেঞ্চমার্ক নির্দিষ্ট করা থাকলে এই মডিউলটি প্রোফাইলিংয়ের জন্য তৈরি করা হয়েছে।
profile_file PGO-এর সাথে ব্যবহার করার জন্য প্রোফাইল ফাইল (toolchain/pgo-profile-এর সাপেক্ষে) । এই ফাইলটি $DIST_DIR/pgo_profile_file_missing.txt-এ যোগ করে বিল্ড সতর্ক করে যে এই ফাইলটি নেই যদি না enable_profile_use প্রপার্টি false-এ সেট করা থাকে অথবা ANDROID_PGO_NO_PROFILE_USE বিল্ড ভেরিয়েবল true-এ সেট করা থাকে।
enable_profile_use বিল্ড চলাকালীন প্রোফাইল ব্যবহার করা না হলে false হিসেবে সেট করুন। প্রোফাইল সংগ্রহ চালু করতে বা PGO সাময়িকভাবে বন্ধ করতে বুটস্ট্র্যাপের সময় ব্যবহার করা যেতে পারে। ডিফল্ট হল true।
cflags ইনস্ট্রুমেন্টেড বিল্ডের সময় ব্যবহার করার জন্য অতিরিক্ত ফ্ল্যাগের তালিকা।

PGO সহ মডিউলের উদাহরণ:

cc_library {
    name: "libexample",
    srcs: [
        "src1.cpp",
        "src2.cpp",
    ],
    static: [
        "libstatic1",
        "libstatic2",
    ],
    shared: [
        "libshared1",
    ]
    pgo: {
        instrumentation: true,
        benchmarks: [
            "benchmark1",
            "benchmark2",
        ],
        profile_file: "example.profdata",
    }
}

যদি বেঞ্চমার্ক benchmark1 এবং benchmark2 লাইব্রেরি libstatic1, libstatic2, বা libshared1-এর জন্য প্রতিনিধিত্বমূলক আচরণ করে, তাহলে এই লাইব্রেরিগুলির pgo প্রপার্টিতেও বেঞ্চমার্ক অন্তর্ভুক্ত থাকতে পারে। Android.bp-এর মধ্যে থাকা defaults মডিউলে একাধিক মডিউলের জন্য একই বিল্ড নিয়ম বার বার ব্যবহার করা এড়াতে, লাইব্রেরির একটি সেটের জন্য সাধারণ pgo স্পেসিফিকেশন অন্তর্ভুক্ত থাকতে পারে।

আলাদা প্রোফাইল ফাইল বেছে নিতে বা কোনও আর্কিটেকচারের জন্য বেছে বেছে PGO বন্ধ করতে, প্রতি আর্কিটেকচারের জন্য profile_file, enable_profile_use ও cflags প্রপার্টি নির্দিষ্ট করুন। উদাহরণ (বোল্ড অক্ষরে আর্কিটেকচার টার্গেট সহ):

cc_library {
    name: "libexample",
    srcs: [
          "src1.cpp",
          "src2.cpp",
    ],
    static: [
          "libstatic1",
          "libstatic2",
    ],
    shared: [
          "libshared1",
    ],
    pgo: {
         instrumentation: true,
         benchmarks: [
              "benchmark1",
              "benchmark2",
         ],
    }

    target: {
         android_arm: {
              pgo: {
                   profile_file: "example_arm.profdata",
              }
         },
         android_arm64: {
              pgo: {
                   profile_file: "example_arm64.profdata",
              }
         }
    }
}

ইনস্ট্রুমেন্টেশন-ভিত্তিক প্রোফাইলিংয়ের সময় প্রোফাইলিং রানটাইম লাইব্রেরির রেফারেন্স সংক্রান্ত সমস্যার সমাধান করতে, লিঙ্কারে বিল্ড ফ্ল্যাগ -fprofile-generate পাস করুন। PGO-এর সাথে ইন্সট্রুমেন্ট করা স্ট্যাটিক লাইব্রেরি, সব শেয়ার করা লাইব্রেরি এবং স্ট্যাটিক লাইব্রেরির উপর সরাসরি নির্ভর করে এমন যেকোনও বাইনারিকেও PGO-এর জন্য ইন্সট্রুমেন্ট করতে হবে। তবে, এই ধরনের শেয়ার করা লাইব্রেরি বা এক্সিকিউটেবলকে PGO প্রোফাইল ব্যবহার করতে হয় না এবং তাদের enable_profile_use প্রপার্টি false হিসেবে সেট করা যেতে পারে। এই বিধিনিষেধের বাইরে, আপনি যেকোনও স্ট্যাটিক লাইব্রেরি, শেয়ার করা লাইব্রেরি বা এক্সিকিউটেবল ফাইলে PGO প্রয়োগ করতে পারবেন।

LLVM প্রোফাইল ফাইল ম্যানেজ করা

ইনস্ট্রুমেন্টেড লাইব্রেরি বা এক্সিকিউটেবল এক্সিকিউট করলে, default_unique_id_0.profraw নামে /data/local/tmp-এ একটি প্রোফাইল ফাইল তৈরি হয় (যেখানে unique_id হল একটি নিউমেরিক হ্যাশ যা এই লাইব্রেরির জন্য অনন্য)। এই ফাইলটি আগে থেকেই থাকলে, প্রোফাইলিং রানটাইম প্রোফাইল লেখার সময় নতুন প্রোফাইলটিকে পুরনোটির সাথে মার্জ করে দেয়। মনে রাখবেন, অ্যাপ ডেভেলপাররা /data/local/tmp অ্যাক্সেস করতে পারেন না; তাদের পরিবর্তে /storage/emulated/0/Android/data/packagename/files-এর মতো কোনও জায়গা ব্যবহার করা উচিত। প্রোফাইল ফাইলের লোকেশন পরিবর্তন করতে, রানটাইমে LLVM_PROFILE_FILE এনভায়রনমেন্ট ভেরিয়েবল সেট করুন।

llvm-profdata ইউটিলিটি ব্যবহার করে .profraw ফাইলকে (এবং সম্ভবত একাধিক .profraw ফাইলকে মার্জ করে) .profdata ফাইলে কনভার্ট করা হয়:

  llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>

profile.profdata-কে তারপরে বিল্ড করার সময় ব্যবহারের জন্য সোর্স ট্রিতে চেক-ইন করা যেতে পারে।

বেঞ্চমার্ক চলাকালীন একাধিক ইন্সট্রুমেন্টেড বাইনারি/লাইব্রেরি লোড করা হলে, প্রতিটি লাইব্রেরি আলাদা আলাদা অনন্য আইডি সহ একটি করে .profraw ফাইল তৈরি করে। সাধারণত, এই সমস্ত ফাইল একটি .profdata ফাইলে মার্জ করা যায় এবং PGO বিল্ডের জন্য ব্যবহার করা হয়। যেসব ক্ষেত্রে কোনও লাইব্রেরি অন্য বেঞ্চমার্ক দ্বারা ব্যবহার করা হয়, সেই লাইব্রেরি অবশ্যই দুটি বেঞ্চমার্কের প্রোফাইল ব্যবহার করে অপ্টিমাইজ করতে হবে। এই পরিস্থিতিতে, llvm-profdata-এর show বিকল্পটি কাজে লাগে:

  llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw
llvm-profdata show -all-functions default_unique_id.profdata

আলাদা আলাদা লাইব্রেরিতে unique_id ম্যাপ করতে, লাইব্রেরির জন্য অনন্য ফাংশনের নাম সহ প্রতিটি unique_id-এর জন্য show আউটপুট সার্চ করুন।

কেস স্টাডি: ART-এর জন্য PGO

কেস স্টাডিতে ART-কে একটি প্রাসঙ্গিক উদাহরণ হিসেবে উপস্থাপন করা হয়েছে; তবে, এটি ART-এর জন্য প্রোফাইল করা লাইব্রেরির প্রকৃত সেট বা তাদের পারস্পরিক নির্ভরতার সঠিক বিবরণ নয়।

ART-এ dex2oat সময়ের আগে কম্পাইলার libart-compiler.so-এর উপর নির্ভর করে, যা আবার libart.so-এর উপর নির্ভর করে। ART রানটাইম প্রধানত libart.so-এ প্রয়োগ করা হয়। কম্পাইলার ও রানটাইমের জন্য বেঞ্চমার্ক আলাদা হবে:

বেঞ্চমার্ক প্রোফাইল করা লাইব্রেরি
dex2oat dex2oat (এক্সিকিউটেবল), libart-compiler.so, libart.so
art_runtime libart.so
  1. dex2oat-এ নিম্নলিখিত pgo প্রপার্টি যোগ করুন, libart-compiler.so:
        pgo: {
            instrumentation: true,
            benchmarks: ["dex2oat",],
            profile_file: "dex2oat.profdata",
        }
  2. libart.so-এ নিম্নলিখিত pgo প্রপার্টি যোগ করুন:
        pgo: {
            instrumentation: true,
            benchmarks: ["art_runtime", "dex2oat",],
            profile_file: "libart.profdata",
        }
  3. dex2oat এবং art_runtime বেঞ্চমার্কের জন্য ইন্সট্রুমেন্টেড বিল্ড তৈরি করুন, এর জন্য এগুলি ব্যবহার করুন:
        make ANDROID_PGO_INSTRUMENT=dex2oat
        make ANDROID_PGO_INSTRUMENT=art_runtime
  4. অথবা, নিম্নলিখিত পদ্ধতি ব্যবহার করে সব লাইব্রেরি ইনস্ট্রুমেন্ট করা একটিমাত্র ইনস্ট্রুমেন্টেড বিল্ড তৈরি করুন:

        make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime
        (or)
        make ANDROID_PGO_INSTRUMENT=ALL

    দ্বিতীয় কমান্ডটি প্রোফাইলিংয়ের জন্য PGO চালু করা সব মডিউল তৈরি করে।

  5. dex2oat ও art_runtime প্রয়োগ করে বেঞ্চমার্ক রান করুন, যাতে:
    • dex2oat থেকে তিনটি .profraw ফাইল (dex2oat_exe.profdata, dex2oat_libart-compiler.profdata এবং dexeoat_libart.profdata), LLVM প্রোফাইল ফাইল ম্যানেজ করা-তে বর্ণিত পদ্ধতি ব্যবহার করে শনাক্ত করা হয়েছে।
    • একটি art_runtime_libart.profdata।
  6. dex2oat এক্সিকিউটেবল ও libart-compiler.so-এর জন্য একটি সাধারণ profdata ফাইল তৈরি করুন, এর জন্য:
    llvm-profdata merge -output=dex2oat.profdata \
        dex2oat_exe.profdata dex2oat_libart-compiler.profdata
  7. দুটি বেঞ্চমার্ক থেকে প্রোফাইল মার্জ করে libart.so-এর প্রোফাইল পান:
    llvm-profdata merge -output=libart.profdata \
        dex2oat_libart.profdata art_runtime_libart.profdata

    দুটি প্রোফাইল থেকে পাওয়া libart.so-এর কাঁচা সংখ্যা আলাদা আলাদা হতে পারে কারণ বেঞ্চমার্কের মধ্যে টেস্ট কেসের সংখ্যা এবং সেগুলি কতক্ষণ ধরে চালানো হয়, এই দুটির মধ্যে পার্থক্য থাকে। এই ক্ষেত্রে, আপনি একটি ওয়েটেড মার্জ ব্যবহার করতে পারেন:

    llvm-profdata merge -output=libart.profdata \
        -weighted-input=2,dex2oat_libart.profdata \
        -weighted-input=1,art_runtime_libart.profdata

    উপরের কমান্ডটি dex2oat থেকে প্রোফাইলে দ্বিগুণ ওয়েট অ্যাসাইন করে। ডোমেন জ্ঞান বা এক্সপেরিমেন্টের উপর ভিত্তি করে আসল ওজন নির্ধারণ করতে হবে।

  8. বিল্ড চলাকালীন ব্যবহারের জন্য প্রোফাইল ফাইল dex2oat.profdata এবং libart.profdata-কে toolchain/pgo-profiles-এ চেক করুন।