মেমরি পুল

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

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

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

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

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

  • ashmem: Android শেয়ার করা মেমরি। আরও বিবরণের জন্য, মেমরি দেখুন।
  • mmap_fd: mmap-এর মাধ্যমে ফাইল ডেসক্রিপটর দ্বারা ব্যাক-আপ নেওয়া শেয়ার করা মেমরি।
  • hardware_buffer_blob: AHardwareBuffer দ্বারা ব্যাক-আপ নেওয়া শেয়ার করা মেমরি যার ফর্ম্যাট হল AHARDWARE_BUFFER_FORMAT_BLOB. Neural Networks (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

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

NNAPI-তে ব্যবহৃত AHardwareBuffer অবজেক্টগুলি ড্রাইভারের কাছে hidl_memory স্ট্রাকচারের মাধ্যমে পাঠানো হয়, যার নাম hardware_buffer বা hardware_buffer_blob। hidl_memory স্ট্রাক্ট 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 সমস্যা কোড রিটার্ন করার জন্য সাজেস্ট করা হয়।

মেমরি ডোমেন

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

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

ছবি ১. মেমরি ডোমেন ব্যবহার করে ডেটা ফ্লো বাফার করা

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

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

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

ড্রাইভারের ইন্টার্নাল মেমরিতে বরাদ্দ করা বাফার থাকে। ড্রাইভার যেকোনও বাফার লোকেশন বা ডেটা লেআউট বেছে নিতে পারেন। বাফার সফলভাবে বরাদ্দ করা হলে, ড্রাইভারের ক্লায়েন্ট, ফেরত দেওয়া টোকেন বা IBuffer অবজেক্ট ব্যবহার করে বাফারের সাথে ইন্টার‍্যাক্ট করতে বা রেফারেন্স দিতে পারে।

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

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

  • স্টেট টেনসর ইনিশিয়ালাইজ করা
  • মধ্যবর্তী ফলাফল ক্যাশে করা
  • সিপিইউতে ফলব্যাক এক্সিকিউশন

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

বাফার অ্যালোকেশনের সময়, বাফারের ডাইমেনশন BufferRole-এর মাধ্যমে নির্দিষ্ট করা সব রোলের সংশ্লিষ্ট মডেল অপারেন্ড এবং BufferDesc-এ দেওয়া ডাইমেনশন থেকে অনুমান করা যেতে পারে। সব ডাইমেনশনাল তথ্য একত্রিত করার পরে, বাফারের অজানা ডাইমেনশন বা র‍্যাঙ্ক থাকতে পারে। এই ধরনের ক্ষেত্রে, বাফারটি একটি নমনীয় অবস্থায় থাকে যেখানে মডেল ইনপুট হিসেবে ব্যবহার করার সময় ডাইমেনশনগুলি ফিক্স করা হয় এবং মডেল আউটপুট হিসেবে ব্যবহার করার সময় ডাইমেনশনগুলি ডায়নামিক অবস্থায় থাকে। The same buffer can be used with different shapes of outputs in different executions and the driver must handle the buffer resizing properly.

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

  • অনুরোধ করা বাফারের সাইজ ডায়নামিক।
  • ড্রাইভারের মেমরি সংক্রান্ত সীমাবদ্ধতা আছে, যার ফলে এটি বড় বাফার ম্যানেজ করতে পারে না।

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