Android 10 থেকে, Neural Networks API (NNAPI)
কম্পাইলেশন আর্টিফ্যাক্ট ক্যাশ করার
সুবিধা প্রদান করে, যা কোনও অ্যাপ শুরু হলে কম্পাইলেশনের
জন্য ব্যবহৃত সময় কমিয়ে দেয়। এই ক্যাশিং কার্যকারিতা ব্যবহার করে, ড্রাইভারকে ক্যাশে করা ফাইলগুলি
ম্যানেজ বা ক্লিন-আপ করতে হবে না। এটি একটি ঐচ্ছিক ফিচার যা
NN HAL 1.2-এর সাথে প্রয়োগ করা যেতে পারে। এই ফাংশন সম্পর্কে আরও তথ্য পেতে,
ANeuralNetworksCompilation_setCaching দেখুন।
এছাড়াও, ড্রাইভার NNAPI থেকে স্বাধীনভাবে কম্পাইলেশন ক্যাশিং প্রয়োগ করতে পারে। NNAPI NDK এবং HAL ক্যাশিং ফিচার ব্যবহার করা হোক বা না হোক, এটি ইমপ্লিমেন্ট করা যেতে পারে। AOSP একটি লো-লেভেল ইউটিলিটি লাইব্রেরি (ক্যাশিং ইঞ্জিন) প্রদান করে। আরও তথ্যের জন্য, ক্যাশিং ইঞ্জিন প্রয়োগ করা দেখুন।
ওয়ার্কফ্লো ওভারভিউ
এই বিভাগে কম্পাইলেশন ক্যাশিং ফিচার প্রয়োগ করে সাধারণ ওয়ার্কফ্লো বর্ণনা করা হয়েছে।
ক্যাশে সংক্রান্ত তথ্য প্রদান করা হয়েছে এবং ক্যাশে হিট হয়েছে
- অ্যাপটি একটি ক্যাশিং ডিরেক্টরি এবং মডেলের জন্য অনন্য একটি চেকসাম পাস করে।
- NNAPI রানটাইম চেকসাম, এক্সিকিউশন প্রেফারেন্স এবং পার্টিশনিং ফলাফলের উপর ভিত্তি করে ক্যাশে ফাইল খোঁজে এবং ফাইলগুলি খুঁজে পায়।
- NNAPI ক্যাশে ফাইল খোলে এবং ড্রাইভারকে হ্যান্ডেল পাস করে
prepareModelFromCacheসহ। - ড্রাইভার ক্যাশে ফাইল থেকে সরাসরি মডেল প্রস্তুত করে এবং প্রস্তুত করা মডেল ফেরত দেয়।
ক্যাশে সংক্রান্ত তথ্য প্রদান করা হয়েছে এবং ক্যাশে মিস হয়েছে
- অ্যাপটি মডেলের জন্য অনন্য একটি চেকসাম এবং একটি ক্যাশিং ডিরেক্টরি পাস করে।
- NNAPI রানটাইম চেকসাম, এক্সিকিউশন প্রেফারেন্স এবং পার্টিশনিং ফলাফলের উপর ভিত্তি করে ক্যাশিং ফাইল খোঁজে এবং ক্যাশে ফাইল খুঁজে পায় না।
- NNAPI চেকসাম, এক্সিকিউশন প্রেফারেন্স ও পার্টিশনের উপর ভিত্তি করে খালি ক্যাশে ফাইল তৈরি করে, ক্যাশে ফাইল খোলে এবং
prepareModel_1_2-এর মাধ্যমে হ্যান্ডেল ও মডেল ড্রাইভারের কাছে পাস করে। - ড্রাইভার মডেলটি কম্পাইল করে, ক্যাশে ফাইলে ক্যাশিং তথ্য লেখে এবং প্রস্তুত মডেলটি ফেরত দেয়।
ক্যাশে সংক্রান্ত তথ্য প্রদান করা হয়নি
- অ্যাপটি কোনও ক্যাশিং তথ্য প্রদান না করেই কম্পাইলেশন শুরু করে।
- অ্যাপটি ক্যাশিং সম্পর্কিত কিছু পাস করে না।
- NNAPI রানটাইম, ড্রাইভারকে
prepareModel_1_2-এর মাধ্যমে মডেলটি পাস করে। - ড্রাইভার মডেলটি কম্পাইল করে এবং তৈরি করা মডেলটি ফেরত দেয়।
ক্যাশে সংক্রান্ত তথ্য
ড্রাইভারকে দেওয়া ক্যাশিং তথ্যের মধ্যে একটি টোকেন ও ক্যাশে ফাইল হ্যান্ডেল থাকে।
টোকেন
প্রস্তুত করা মডেলকে শনাক্ত করে এমন
Constant::BYTE_SIZE_OF_CACHE_TOKEN
দৈর্ঘ্যের একটি ক্যাশিং টোকেন হল
টোকেন
। prepareModel_1_2-এর মাধ্যমে ক্যাশে ফাইল সেভ করার সময় এবং prepareModelFromCache-এর মাধ্যমে
প্রস্তুত মডেল রিট্রিভ করার সময় একই টোকেন
প্রদান করা হয়। ড্রাইভারের ক্লায়েন্টকে এমন টোকেন বেছে নিতে হবে যাতে
সংঘর্ষের হার কম হয়। ড্রাইভার টোকেন কোলাইড শনাক্ত করতে পারে না। কলিশনের ফলে
এক্সিকিউশন ব্যর্থ হয় অথবা এক্সিকিউশন সফল হলেও
ভুল আউটপুট ভ্যালু তৈরি হয়।
ক্যাশে ফাইল হ্যান্ডেল (দুই ধরনের ক্যাশে ফাইল)
দুই ধরনের ক্যাশে ফাইল হল ডেটা ক্যাশে ও মডেল ক্যাশে।
- ডেটা ক্যাশে: প্রসেস করা ও পরিবর্তিত টেনসর বাফার সহ ধ্রুবক ডেটা ক্যাশে করার জন্য ব্যবহার করা হয়। ডেটা ক্যাশে পরিবর্তন করা হলে, এক্সিকিউশন টাইমে খারাপ আউটপুট ভ্যালু তৈরি হওয়ার চেয়ে খারাপ কিছু হওয়ার কথা নয়।
- মডেল ক্যাশে: ডিভাইসের নেটিভ বাইনারি ফর্ম্যাটে কম্পাইল করা এক্সিকিউটেবল মেশিন কোডের মতো নিরাপত্তা-সংবেদনশীল ডেটা ক্যাশে করার জন্য ব্যবহার করা হয়। মডেল ক্যাশেতে পরিবর্তন করা হলে তা ড্রাইভারের এক্সিকিউশন আচরণকে প্রভাবিত করতে পারে এবং কোনও ক্ষতিকর ক্লায়েন্ট অনুমতি ছাড়াই এক্সিকিউট করার জন্য এটি ব্যবহার করতে পারে। তাই, ক্যাশে থেকে মডেল প্রস্তুত করার আগে ড্রাইভারকে অবশ্যই চেক করতে হবে যে মডেল ক্যাশে খারাপ হয়েছে কিনা। আরও তথ্যের জন্য, নিরাপত্তা দেখুন।
ড্রাইভারকে সিদ্ধান্ত নিতে হবে যে কীভাবে দুই ধরনের ক্যাশে ফাইলের মধ্যে ক্যাশে তথ্য বিতরণ করা হয় এবং প্রতিটি ধরনের জন্য কতগুলি ক্যাশে ফাইল প্রয়োজন তা রিপোর্ট করতে হবে
getNumberOfCacheFilesNeeded-এর সাথে।
NNAPI রানটাইম সবসময় রিড ও রাইট পারমিশন সহ ক্যাশে ফাইল হ্যান্ডেল খোলে।
নিরাপত্তা
কম্পাইলেশন ক্যাশিংয়ের ক্ষেত্রে, মডেল ক্যাশেতে নিরাপত্তা-সংবেদনশীল ডেটা থাকতে পারে, যেমন ডিভাইসের নেটিভ বাইনারি ফর্ম্যাটে কম্পাইল করা এক্সিকিউটেবল মেশিন কোড। মডেল ক্যাশে সঠিকভাবে সুরক্ষিত না থাকলে, এতে করা পরিবর্তন ড্রাইভারের এক্সিকিউশন আচরণকে প্রভাবিত করতে পারে। যেহেতু ক্যাশে কন্টেন্ট অ্যাপ ডিরেক্টরিতে সেভ করা থাকে, তাই ক্লায়েন্ট ক্যাশে ফাইল পরিবর্তন করতে পারে। কোনও বাগ থাকা ক্লায়েন্ট ভুলবশত ক্যাশে নষ্ট করে দিতে পারে এবং কোনও ক্ষতিকর ক্লায়েন্ট ইচ্ছাকৃতভাবে এটি ব্যবহার করে ডিভাইসে যাচাই না করা কোড চালাতে পারে। ডিভাইসের বৈশিষ্ট্যের উপর নির্ভর করে, এটি একটি নিরাপত্তা সংক্রান্ত সমস্যা হতে পারে। তাই, ক্যাশে থেকে মডেল প্রস্তুত করার আগে ড্রাইভারকে সম্ভাব্য মডেল ক্যাশে দূষণ ডিটেক্ট করতে হবে।
এটি করার একটি উপায় হল, ড্রাইভারকে টোকেন থেকে মডেল ক্যাশের
ক্রিপ্টোগ্রাফিক হ্যাশ পর্যন্ত একটি ম্যাপ বজায় রাখতে হবে। ড্রাইভার, কম্পাইলেশন ক্যাশে সেভ করার সময় টোকেন ও
মডেল ক্যাশের হ্যাশ সেভ করতে পারে। ক্যাশে থেকে কম্পাইলেশন নেওয়ার সময়
ড্রাইভার রেকর্ড করা টোকেন ও হ্যাশ পেয়ারের সাথে মডেল ক্যাশের
নতুন হ্যাশ চেক করে। সিস্টেম রিবুট করা হলেও এই ম্যাপিং
অপরিবর্তিত থাকতে হবে। ম্যাপিং ম্যানেজার প্রয়োগ করার জন্য ড্রাইভার
Android কীস্টোর পরিষেবা,
framework/ml/nn/driver/cache-এ ইউটিলিটি লাইব্রেরি
বা অন্য কোনও উপযুক্ত পদ্ধতি ব্যবহার করতে পারে। ড্রাইভার আপডেট করার পরে, আগের ভার্সন থেকে ক্যাশে ফাইল তৈরি করা আটকাতে এই ম্যাপিং ম্যানেজারকে আবার শুরু করতে হবে।
চেক করার সময় থেকে ব্যবহার করার সময় (TOCTOU) পর্যন্ত অ্যাটাক প্রতিরোধ করতে, ড্রাইভারকে ফাইলে সেভ করার আগে রেকর্ড করা হ্যাশ গণনা করতে হবে এবং ফাইলের কন্টেন্ট ইন্টার্নাল বাফারে কপি করার পরে নতুন হ্যাশ গণনা করতে হবে।
এই স্যাম্পেল কোড থেকে বোঝা যায় যে কীভাবে এই লজিক প্রয়োগ করতে হয়।
bool saveToCache(const sp<V1_2::IPreparedModel> preparedModel,
const hidl_vec<hidl_handle>& modelFds, const hidl_vec<hidl_handle>& dataFds,
const HidlToken& token) {
// Serialize the prepared model to internal buffers.
auto buffers = serialize(preparedModel);
// This implementation detail is important: the cache hash must be computed from internal
// buffers instead of cache files to prevent time-of-check to time-of-use (TOCTOU) attacks.
auto hash = computeHash(buffers);
// Store the {token, hash} pair to a mapping manager that is persistent across reboots.
CacheManager::get()->store(token, hash);
// Write the cache contents from internal buffers to cache files.
return writeToFds(buffers, modelFds, dataFds);
}
sp<V1_2::IPreparedModel> prepareFromCache(const hidl_vec<hidl_handle>& modelFds,
const hidl_vec<hidl_handle>& dataFds,
const HidlToken& token) {
// Copy the cache contents from cache files to internal buffers.
auto buffers = readFromFds(modelFds, dataFds);
// This implementation detail is important: the cache hash must be computed from internal
// buffers instead of cache files to prevent time-of-check to time-of-use (TOCTOU) attacks.
auto hash = computeHash(buffers);
// Validate the {token, hash} pair by a mapping manager that is persistent across reboots.
if (CacheManager::get()->validate(token, hash)) {
// Retrieve the prepared model from internal buffers.
return deserialize<V1_2::IPreparedModel>(buffers);
} else {
return nullptr;
}
}
উন্নত ব্যবহারিক ক্ষেত্র
কিছু উন্নত ব্যবহারের ক্ষেত্রে, কম্পাইলেশন কলের পরে ড্রাইভারকে ক্যাশে কন্টেন্ট অ্যাক্সেস করতে হয় (পড়তে বা লিখতে হয়)। ব্যবহারের উদাহরণ:
- জাস্ট-ইন-টাইম কম্পাইলেশন: প্রথমবার এক্সিকিউট না করা পর্যন্ত কম্পাইলেশন বিলম্বিত হয়।
- মাল্টি-স্টেজ কম্পাইলেশন: প্রথমে দ্রুত কম্পাইলেশন করা হয় এবং ব্যবহারের ফ্রিকোয়েন্সির উপর নির্ভর করে পরে অপ্টিমাইজ করা কম্পাইলেশন করা হয় যা ঐচ্ছিক।
কম্পাইলেশন কলের পরে ক্যাশে কন্টেন্ট অ্যাক্সেস (পড়া বা লেখা) করতে, নিশ্চিত করুন যে ড্রাইভার:
prepareModel_1_2বাprepareModelFromCache-এর ইনভোকেশনের সময় ফাইল হ্যান্ডেল ডুপ্লিকেট করে এবং পরে ক্যাশে কন্টেন্ট পড়ে/আপডেট করে।- সাধারণ কম্পাইলেশন কলের বাইরে ফাইল লকিং লজিক প্রয়োগ করে যাতে রিড করার সময় বা অন্য কোনও রাইট করার সময় একই সাথে রাইট করা না যায়।
ক্যাশিং ইঞ্জিন প্রয়োগ করা
NN HAL 1.2 কম্পাইলেশন ক্যাশিং ইন্টারফেস ছাড়াও, আপনি
frameworks/ml/nn/driver/cache
ডিরেক্টরিতে একটি ক্যাশিং ইউটিলিটি লাইব্রেরিও খুঁজে পেতে পারেন।
nnCache
সাবডিরেক্টরিতে ড্রাইভারের জন্য পারসিস্ট্যান্ট স্টোরেজ কোড থাকে, যা NNAPI ক্যাশিং ফিচার ব্যবহার না করেই
কম্পাইলেশন ক্যাশিং প্রয়োগ করে। এই ধরনের
কম্পাইলেশন ক্যাশিং NN HAL-এর যেকোনও ভার্সনের সাথে প্রয়োগ করা যেতে পারে। ড্রাইভার যদি HAL ইন্টারফেস থেকে ডিসকানেক্ট করা ক্যাশিং প্রয়োগ করার
বিকল্প বেছে নেয়, তাহলে ক্যাশ করা আর্টিফ্যাক্ট আর প্রয়োজন না হলে সেগুলি মুছে দেওয়ার
দায়িত্ব ড্রাইভারের
।