মেমরি পুল

এই পৃষ্ঠায় ড্রাইভার এবং ফ্রেমওয়ার্কের মধ্যে অপারেন্ড বাফারগুলো দক্ষতার সাথে আদান-প্রদান করতে ব্যবহৃত ডেটা স্ট্রাকচার এবং পদ্ধতিগুলো বর্ণনা করা হয়েছে।

মডেল কম্পাইলেশনের সময়, ফ্রেমওয়ার্কটি ড্রাইভারকে কনস্ট্যান্ট অপারেন্ডগুলোর মান সরবরাহ করে। কনস্ট্যান্ট অপারেন্ডের জীবনকালের উপর নির্ভর করে, এর মানগুলো একটি HIDL ভেক্টর অথবা একটি শেয়ার্ড মেমরি পুলে অবস্থিত থাকে।

  • যদি লাইফটাইম CONSTANT_COPY হয়, তাহলে মানগুলো মডেল স্ট্রাকচারের operandValues ​​ফিল্ডে থাকে। যেহেতু ইন্টারপ্রসেস কমিউনিকেশন (IPC) চলাকালীন HIDL ভেক্টরের মানগুলো কপি করা হয়, তাই এটি সাধারণত শুধুমাত্র অল্প পরিমাণ ডেটা ধারণ করতে ব্যবহৃত হয়, যেমন স্কেলার অপারেন্ড (উদাহরণস্বরূপ, ADD এর অ্যাক্টিভেশন স্কেলার) এবং ছোট টেনসর প্যারামিটার (উদাহরণস্বরূপ, RESHAPE এর শেপ টেনসর)।
  • যদি লাইফটাইম CONSTANT_REFERENCE হয়, তাহলে মানগুলো মডেল স্ট্রাকচারের ` pools ফিল্ডে অবস্থান করে। IPC-এর সময় র' ভ্যালু কপি করার পরিবর্তে শুধুমাত্র শেয়ার্ড মেমোরি পুলের হ্যান্ডেলগুলো ডুপ্লিকেট করা হয়। তাই, HIDL ভেক্টরের চেয়ে শেয়ার্ড মেমোরি পুল ব্যবহার করে বিপুল পরিমাণ ডেটা (যেমন, কনভোলিউশনের ওয়েট প্যারামিটার) সংরক্ষণ করা বেশি কার্যকর।

মডেল এক্সিকিউশনের সময়, ফ্রেমওয়ার্কটি ড্রাইভারকে ইনপুট এবং আউটপুট অপারেন্ডের বাফারগুলো সরবরাহ করে। HIDL ভেক্টরে পাঠানো হতে পারে এমন কম্পাইল-টাইম কনস্ট্যান্টের বিপরীতে, একটি এক্সিকিউশনের ইনপুট এবং আউটপুট ডেটা সর্বদা একাধিক মেমরি পুলের মাধ্যমে আদান-প্রদান করা হয়।

HIDL ডেটা টাইপ hidl_memory কম্পাইলেশন এবং এক্সিকিউশন উভয় ক্ষেত্রেই একটি আনম্যাপড শেয়ার্ড মেমরি পুলকে উপস্থাপন করতে ব্যবহৃত হয়। hidl_memory ডেটা টাইপের নামের উপর ভিত্তি করে মেমরিটিকে ব্যবহারযোগ্য করার জন্য ড্রাইভারের উচিত যথাযথভাবে ম্যাপ করা। সমর্থিত মেমরির নামগুলো হলো:

  • ashmem : অ্যান্ড্রয়েডের শেয়ার্ড মেমরি। আরও বিস্তারিত জানতে, মেমরি দেখুন।
  • mmap_fd : mmap মাধ্যমে ফাইল ডেসক্রিপ্টর দ্বারা সমর্থিত শেয়ার্ড মেমরি।
  • hardware_buffer_blob : একটি শেয়ার্ড মেমরি যা AHARDWARE_BUFFER_FORMAT_BLOB ফরম্যাটের একটি AHardwareBuffer দ্বারা সমর্থিত। এটি নিউরাল নেটওয়ার্কস (NN) HAL 1.2 থেকে পাওয়া যায়। আরও বিস্তারিত জানতে, AHardwareBuffer দেখুন।
  • hardware_buffer : একটি সাধারণ AHardwareBuffer দ্বারা সমর্থিত শেয়ার্ড মেমরি যা AHARDWARE_BUFFER_FORMAT_BLOB ফরম্যাট ব্যবহার করে না। নন-BLOB মোড হার্ডওয়্যার বাফার শুধুমাত্র মডেল এক্সিকিউশনে সমর্থিত। NN HAL 1.2 থেকে উপলব্ধ। আরও বিস্তারিত জানতে, AHardwareBuffer দেখুন।

NN HAL 1.3 থেকে, NNAPI মেমরি ডোমেইন সমর্থন করে যা ড্রাইভার-পরিচালিত বাফারের জন্য অ্যালোকেটর ইন্টারফেস প্রদান করে। এই ড্রাইভার-পরিচালিত বাফারগুলো এক্সিকিউশন ইনপুট বা আউটপুট হিসেবেও ব্যবহার করা যেতে পারে। আরও বিস্তারিত জানতে, মেমরি ডোমেইন দেখুন।

NNAPI ড্রাইভারগুলোকে অবশ্যই ashmem এবং mmap_fd মেমরি নামগুলোর ম্যাপিং সমর্থন করতে হবে। NN HAL 1.3 থেকে, ড্রাইভারগুলোকে অবশ্যই hardware_buffer_blob এর ম্যাপিংও সমর্থন করতে হবে। সাধারণ নন-BLOB মোড hardware_buffer এবং মেমরি ডোমেইনগুলোর জন্য সমর্থন ঐচ্ছিক।

এহার্ডওয়্যারবাফার

AHardwareBuffer হলো এক ধরনের শেয়ার্ড মেমরি যা একটি Gralloc বাফারকে আবৃত করে রাখে। Android 10-এ, নিউরাল নেটওয়ার্কস এপিআই (NNAPI) AHardwareBuffer ব্যবহার সমর্থন করে, যা ড্রাইভারকে ডেটা কপি না করেই এক্সিকিউশন সম্পাদন করার সুযোগ দেয় এবং এর ফলে অ্যাপের পারফরম্যান্স ও বিদ্যুৎ খরচ উন্নত হয়। উদাহরণস্বরূপ, একটি ক্যামেরা HAL স্ট্যাক, ক্যামেরা NDK এবং মিডিয়া NDK এপিআই দ্বারা জেনারেট করা AHardwareBuffer হ্যান্ডেল ব্যবহার করে মেশিন লার্নিং ওয়ার্কলোডের জন্য NNAPI-তে AHardwareBuffer অবজেক্ট পাস করতে পারে। আরও তথ্যের জন্য, ANeuralNetworksMemory_createFromAHardwareBuffer দেখুন।

NNAPI-তে ব্যবহৃত AHardwareBuffer অবজেক্টগুলো hardware_buffer অথবা hardware_buffer_blob নামের একটি hidl_memory struct-এর মাধ্যমে ড্রাইভারের কাছে পাঠানো হয়। hidl_memory struct hardware_buffer_blob শুধুমাত্র AHARDWAREBUFFER_FORMAT_BLOB ফরম্যাটের AHardwareBuffer অবজেক্টগুলোকেই প্রতিনিধিত্ব করে।

ফ্রেমওয়ার্কের জন্য প্রয়োজনীয় তথ্য hidl_memory struct-এর hidl_handle ফিল্ডে এনকোড করা থাকে। hidl_handle ফিল্ডটি native_handle র‍্যাপ করে, যা AHardwareBuffer বা Gralloc বাফার সম্পর্কিত সমস্ত প্রয়োজনীয় মেটাডেটা এনকোড করে।

ড্রাইভারকে অবশ্যই প্রদত্ত hidl_handle ফিল্ডটি সঠিকভাবে ডিকোড করতে হবে এবং hidl_handle দ্বারা বর্ণিত মেমরি অ্যাক্সেস করতে হবে। যখন getSupportedOperations_1_2 , getSupportedOperations_1_1 , বা getSupportedOperations মেথড কল করা হয়, তখন ড্রাইভারের শনাক্ত করা উচিত যে এটি প্রদত্ত hidl_handle ডিকোড করতে এবং hidl_handle দ্বারা বর্ণিত মেমরি অ্যাক্সেস করতে পারে কি না। যদি কোনো কনস্ট্যান্ট অপারেন্ডের জন্য ব্যবহৃত hidl_handle ফিল্ডটি সমর্থিত না হয়, তাহলে মডেল প্রিপারেশন অবশ্যই ব্যর্থ হবে। যদি এক্সিকিউশনের কোনো ইনপুট বা আউটপুট অপারেন্ডের জন্য ব্যবহৃত hidl_handle ফিল্ডটি সমর্থিত না হয়, তাহলে এক্সিকিউশন অবশ্যই ব্যর্থ হবে। মডেল প্রিপারেশন বা এক্সিকিউশন ব্যর্থ হলে ড্রাইভারের জন্য একটি GENERAL_FAILURE এরর কোড রিটার্ন করার পরামর্শ দেওয়া হয়।

মেমরি ডোমেইন

অ্যান্ড্রয়েড ১১ বা তার উচ্চতর সংস্করণে চালিত ডিভাইসগুলির জন্য, NNAPI মেমরি ডোমেইন সমর্থন করে যা ড্রাইভার-পরিচালিত বাফারগুলির জন্য অ্যালোকেটর ইন্টারফেস প্রদান করে। এটি ডিভাইসের নেটিভ মেমরিগুলিকে এক এক্সিকিউশন থেকে অন্য এক্সিকিউশনে পাস করার সুযোগ দেয়, এবং একই ড্রাইভারের অধীনে পরপর এক্সিকিউশনের মধ্যে অপ্রয়োজনীয় ডেটা কপি ও রূপান্তর রোধ করে। এই কার্যপ্রবাহটি চিত্র ১-এ দেখানো হয়েছে।

মেমরি ডোমেন সহ এবং ছাড়া বাফার ডেটা প্রবাহ

চিত্র ১. মেমরি ডোমেইন ব্যবহার করে বাফার ডেটা প্রবাহ

মেমরি ডোমেইন ফিচারটি এমন টেনসরগুলোর জন্য তৈরি করা হয়েছে যেগুলো মূলত ড্রাইভারের অভ্যন্তরীণ এবং ক্লায়েন্ট সাইডে ঘন ঘন অ্যাক্সেসের প্রয়োজন হয় না। এই ধরনের টেনসরের উদাহরণ হলো সিকোয়েন্স মডেলের স্টেট টেনসরগুলো। যেসব টেনসরের ক্লায়েন্ট সাইডে ঘন ঘন সিপিইউ অ্যাক্সেসের প্রয়োজন হয়, সেগুলোর জন্য শেয়ার্ড মেমরি পুল ব্যবহার করা শ্রেয়।

মেমরি ডোমেইন বৈশিষ্ট্যটি সমর্থন করার জন্য, IDevice::allocate প্রয়োগ করুন, যাতে ফ্রেমওয়ার্ক ড্রাইভার-পরিচালিত বাফার বরাদ্দের জন্য অনুরোধ করতে পারে। বরাদ্দের সময়, ফ্রেমওয়ার্ক বাফারের জন্য নিম্নলিখিত বৈশিষ্ট্য এবং ব্যবহারের ধরণ সরবরাহ করে:

  • BufferDesc বাফারের প্রয়োজনীয় বৈশিষ্ট্যগুলো বর্ণনা করে।
  • BufferRole একটি প্রস্তুত মডেলের ইনপুট বা আউটপুট হিসাবে বাফারটির সম্ভাব্য ব্যবহারের ধরণ বর্ণনা করে। বাফার বরাদ্দের সময় একাধিক ভূমিকা নির্দিষ্ট করা যেতে পারে, এবং বরাদ্দকৃত বাফারটি শুধুমাত্র সেই নির্দিষ্ট ভূমিকাগুলোতেই ব্যবহার করা যাবে।

বরাদ্দকৃত বাফারটি ড্রাইভারের অভ্যন্তরীণ। একজন ড্রাইভার যেকোনো বাফার অবস্থান বা ডেটা বিন্যাস বেছে নিতে পারে। বাফারটি সফলভাবে বরাদ্দ করা হলে, ড্রাইভারের ক্লায়েন্ট ফেরত আসা টোকেন বা IBuffer অবজেক্ট ব্যবহার করে বাফারটিকে উল্লেখ করতে বা এর সাথে যোগাযোগ করতে পারে।

কোনো এক্সিকিউশনের Request স্ট্রাকচারে MemoryPool অবজেক্টগুলোর একটি হিসেবে বাফারটিকে রেফারেন্স করার সময় IDevice::allocate থেকে প্রাপ্ত টোকেনটি সরবরাহ করা হয়। একটি প্রসেস যাতে অন্য কোনো প্রসেসে বরাদ্দ করা বাফার অ্যাক্সেস করার চেষ্টা করতে না পারে, সেজন্য ড্রাইভারকে অবশ্যই বাফারটির প্রতিটি ব্যবহারের সময় যথাযথ ভ্যালিডেশন প্রয়োগ করতে হবে। ড্রাইভারকে অবশ্যই যাচাই করতে হবে যে বাফারের ব্যবহারটি বরাদ্দের সময় প্রদত্ত BufferRole রোলগুলোর মধ্যে একটি কি না এবং ব্যবহারটি অবৈধ হলে অবিলম্বে এক্সিকিউশনটি ব্যর্থ করে দিতে হবে।

IBuffer অবজেক্টটি সুস্পষ্ট মেমরি কপি করার জন্য ব্যবহৃত হয়। কিছু পরিস্থিতিতে, ড্রাইভারের ক্লায়েন্টকে অবশ্যই একটি শেয়ার্ড মেমরি পুল থেকে ড্রাইভার-পরিচালিত বাফারটি ইনিশিয়ালাইজ করতে হয় অথবা বাফারটিকে একটি শেয়ার্ড মেমরি পুলে কপি করে নিতে হয়। এর ব্যবহারের উদাহরণগুলো হলো:

  • স্টেট টেনসরের প্রারম্ভিকীকরণ
  • অন্তর্বর্তী ফলাফল ক্যাশিং করা হচ্ছে
  • সিপিইউতে ফলব্যাক এক্সিকিউশন

এই ব্যবহারের ক্ষেত্রগুলিকে সমর্থন করার জন্য, ড্রাইভারটিকে অবশ্যই ashmem , mmap_fd , এবং hardware_buffer_blob সাথে IBuffer::copyTo এবং IBuffer::copyFrom প্রয়োগ করতে হবে, যদি এটি মেমরি ডোমেইন অ্যালোকেশন সমর্থন করে। ড্রাইভারের জন্য নন-BLOB মোড hardware_buffer সমর্থন করা ঐচ্ছিক।

বাফার বরাদ্দের সময়, BufferRole দ্বারা নির্দিষ্ট করা সমস্ত রোলের সংশ্লিষ্ট মডেল অপারেন্ড এবং BufferDesc এ প্রদত্ত ডাইমেনশন থেকে বাফারের ডাইমেনশন অনুমান করা যেতে পারে। সমস্ত ডাইমেনশনাল তথ্য একত্রিত করার পর, বাফারটির ডাইমেনশন বা র‍্যাঙ্ক অজানা থাকতে পারে। এমন ক্ষেত্রে, বাফারটি একটি ফ্লেক্সিবল অবস্থায় থাকে, যেখানে মডেল ইনপুট হিসাবে ব্যবহৃত হলে ডাইমেনশন স্থির থাকে এবং মডেল আউটপুট হিসাবে ব্যবহৃত হলে এটি একটি ডাইনামিক অবস্থায় থাকে। একই বাফার বিভিন্ন এক্সিকিউশনে ভিন্ন ভিন্ন আকারের আউটপুটের সাথে ব্যবহার করা যেতে পারে এবং ড্রাইভারকে অবশ্যই বাফারের আকার পরিবর্তনের বিষয়টি সঠিকভাবে পরিচালনা করতে হবে।

মেমরি ডোমেইন একটি ঐচ্ছিক বৈশিষ্ট্য। একটি ড্রাইভার বিভিন্ন কারণে কোনো নির্দিষ্ট অ্যালোকেশন অনুরোধ সমর্থন করতে পারবে না বলে সিদ্ধান্ত নিতে পারে। উদাহরণস্বরূপ:

  • অনুরোধকৃত বাফারটির আকার পরিবর্তনশীল।
  • ড্রাইভারটির মেমোরির সীমাবদ্ধতা থাকায় এটি বড় বাফার পরিচালনা করতে পারে না।

একাধিক ভিন্ন থ্রেড একই সাথে ড্রাইভার-পরিচালিত বাফার থেকে ডেটা পড়তে পারে। একই সাথে বাফারটি লেখা বা পড়া/লেখার জন্য অ্যাক্সেস করা অসংজ্ঞায়িত, তবে এটি ড্রাইভার সার্ভিসকে ক্র্যাশ করবে না বা কলারকে অনির্দিষ্টকালের জন্য ব্লক করবে না। ড্রাইভার একটি ত্রুটি ফেরত দিতে পারে অথবা বাফারের বিষয়বস্তুকে একটি অনির্ধারিত অবস্থায় রেখে দিতে পারে।