گردانندگان «میانای برنامه‌سازی کاربردی شبکه‌های عصبی»

این صفحه نمای کلی از نحوه پیاده‌سازی درایور «میانای برنامه‌سازی کاربردی شبکه‌های عصبی» (NNAPI) ارائه می‌دهد. برای جزئیات بیشتر، به مستندات موجود در فایل‌های تعریف HAL در hardware/interfaces/neuralnetworks مراجعه کنید. پیاده‌سازی نمونه درایور در frameworks/ml/nn/driver/sample قرار دارد.

برای کسب اطلاعات بیشتر درباره «میانای برنامه‌سازی کاربردی شبکه‌های عصبی»، میانای برنامه‌سازی کاربردی شبکه‌های عصبی را ببینید.

لایه انتزاع سخت‌افزار شبکه‌های عصبی

«لایه انتزاع سخت‌افزار» (HAL) «شبکه‌های عصبی» (NN) انتزاعی از دستگاه‌های مختلف، مثل واحدهای پردازش گرافیکی (GPU) و پردازنده‌های سیگنال دیجیتال (DSP)، که در یک محصول (برای نمونه، تلفن یا رایانه لوحی) وجود دارند را تعریف می‌کند. گردانندگان این دستگاه‌ها باید با NN HAL مطابقت داشته باشند. این میان‌رو در فایل‌های تعریف HAL در hardware/interfaces/neuralnetworks مشخص شده است.

جریان کلی میانای بین چارچوب و درایور در شکل ۱ نشان داده شده است.

جریان شبکه‌های عصبی

شکل ۱. جریان «شبکه‌های عصبی»

مقداردهی اولیه

در زمان مقداردهی اولیه، چارچوب بااستفاده از IDevice::getCapabilities_1_3 از درایور درباره قابلیت‌های آن پُرسمان می‌کند. ساختار @1.3::Capabilities شامل همه انواع داده‌ها است و عملکرد غیرآسان‌گیر را بااستفاده از بردار نشان می‌دهد.

برای تعیین نحوه تخصیص محاسبات به دستگاه‌های دردسترس، چارچوب از قابلیت‌ها استفاده می‌کند تا بفهمد هر درایور با چه سرعتی و با چه میزان بهینگی انرژی می‌تواند اجرا کند. برای ارائه این اطلاعات، گرداننده باید اعداد عملکرد استانداردشده‌ای را براساس اجرای حجم‌های کاری مرجع ارائه دهد.

برای تعیین مقادیری که درایور در پاسخ به IDevice::getCapabilities_1_3 برمی‌گرداند، از برنامه محک NNAPI برای اندازه‌گیری عملکرد انواع داده‌های مربوطه استفاده کنید. مدل‌های MobileNet v1 و v2، asr_float، و tts_float برای اندازه‌گیری عملکرد مقادیر ممیز شناور ۳۲ بیتی توصیه می‌شوند و مدل‌های MobileNet v1 و v2 کمی‌سازی‌شده برای مقادیر کمی‌سازی‌شده ۸ بیتی توصیه می‌شوند. برای کسب اطلاعات بیشتر، به مجموعه آزمایش یادگیری ماشین Android مراجعه کنید.

در Android 9 و نسخه‌های پایین‌تر، ساختار Capabilities فقط شامل اطلاعات عملکرد راننده برای تانسورهای ممیز شناور و کوانتیزه است و شامل انواع داده‌های اسکالر نمی‌شود.

به‌عنوان بخشی از فرایند مقداردهی اولیه، چارچوب ممکن است اطلاعات بیشتری را بااستفاده از IDevice::getType، IDevice::getVersionString، IDevice:getSupportedExtensions، و IDevice::getNumberOfCacheFilesNeeded پرس‌وجو کند.

بین بازراه‌اندازی‌های محصول، چارچوب انتظار دارد که همه پُرسمان‌های توصیف‌شده در این بخش همیشه مقادیر یکسانی را برای یک درایور معین گزارش کنند. درغیراین‌صورت، برنامه‌ای که از آن درایور استفاده می‌کند ممکن است عملکرد ضعیف یا رفتار نادرستی نشان دهد.

گردآوری‌شده

وقتی چارچوب درخواستی از برنامه دریافت می‌کند، تعیین می‌کند از کدام دستگاه‌ها استفاده کند. در Android 10، برنامه‌ها می‌توانند دستگاه‌هایی را که چارچوب از میان آن‌ها انتخاب می‌کند پیدا و مشخص کنند. برای اطلاعات بیشتر، به کشف و تخصیص دستگاه مراجعه کنید.

در زمان تدوین مدل، چارچوب با فراخوانی IDevice::getSupportedOperations_1_3 مدل را به هر درایور نامزد ارسال می‌کند. هر درایور آرایه‌ای از مقادیر بولی برمی‌گرداند که نشان می‌دهد کدام عملیات مدل پشتیبانی می‌شود. گرداننده می‌تواند تشخیص دهد که به دلایل مختلفی نمی‌تواند از عملیات خاصی پشتیبانی کند. برای مثال:

  • گرداننده از نوع داده پشتیبانی نمی‌کند.
  • گرداننده فقط از عملیات با پارامترهای ورودی خاص پشتیبانی می‌کند. برای مثال، یک درایور ممکن است از عملیات پیچش ۳×۳ و ۵×۵ پشتیبانی کند، اما از عملیات پیچش ۷×۷ پشتیبانی نکند.
  • گرداننده محدودیت‌های حافظه دارد که مانع از مدیریت گراف‌ها یا ورودی‌های بزرگ می‌شود.

درطول گردآوری، عملوندهای ورودی، خروجی، و داخلی مدل، همان‌طور که در OperandLifeTime توضیح داده شده است، می‌توانند ابعاد یا رتبه ناشناخته داشته باشند. برای اطلاعات بیشتر، به شکل برونداد مراجعه کنید.

چارچوب به هر راننده انتخابی دستور می‌دهد تا برای اجرای زیرمجموعه‌ای از مدل با فراخوانی IDevice::prepareModel_1_3 آماده شود. سپس هر درایور زیرمجموعه خود را گردآوری می‌کند. برای مثال، یک درایور ممکن است کد تولید کند یا کپی مرتب‌شده‌ای از وزن‌ها ایجاد کند. چون ممکن است بین کامپایل مدل و اجرای درخواست‌ها زمان قابل‌توجهی وجود داشته باشد، منابعی مانند بخش‌های بزرگ حافظه دستگاه نباید درطول کامپایل اختصاص داده شوند.

درصورت موفقیت، درایور یک @1.3::IPreparedModel دستگیره برمی‌گرداند. اگر درایور هنگام آماده‌سازی زیرمجموعه مدل کد خرابی برگرداند، چارچوب کل مدل را در واحد پردازش مرکزی اجرا می‌کند.

برای کاهش زمان استفاده‌شده برای ترجمه هنگام شروع برنامه، درایور می‌تواند آرتیفکت‌های ترجمه را در حافظه نهان ذخیره کند. برای اطلاعات بیشتر، ترکیب ذخیره در حافظه نهان را ببینید.

اجرا

وقتی برنامه‌ای از چارچوب می‌خواهد درخواستی را اجرا کند، چارچوب به‌طور پیش‌فرض روش HAL IPreparedModel::executeSynchronously_1_3 را فراخوانی می‌کند تا اجرای همگامی را روی مدل آماده‌شده انجام دهد. درخواست را می‌توان به‌صورت ناهم‌زمان بااستفاده از execute_1_3 روش، executeFenced روش (به اجرای محدود مراجعه کنید)، یا بااستفاده از اجرای پشت‌سرهم اجرا کرد.

فراخوانی‌های اجرای هم‌زمان در مقایسه با فراخوانی‌های غیرهم‌زمان، عملکرد را بهبود می‌بخشد و سربار رشته‌بندی را کاهش می‌دهد زیرا کنترل تنها پس‌از تکمیل اجرا به فرایند برنامه برمی‌گردد. این یعنی درایور به سازوکار جداگانه‌ای برای مطلع کردن فرایند برنامه از تکمیل شدن اجرا نیاز ندارد.

با روش ناهم‌زمان execute_1_3، پس‌از شروع اجرا، کنترل به فرایند برنامه برمی‌گردد و درایور باید بااستفاده از @1.3::IExecutionCallback، چارچوب را از تکمیل اجرا مطلع کند.

پارامتر Request که به روش اجرا ارسال می‌شود، عملوندهای ورودی و خروجی مورد استفاده برای اجرا را فهرست می‌کند. حافظه‌ای که داده‌های عملوند را ذخیره می‌کند باید از ترتیب سطری استفاده کند و اولین بُعد آن کندترین تکرار را داشته باشد و در انتهای هیچ ردیفی نباید حاشیه داشته باشد. برای اطلاعات بیشتر درباره انواع عملوندها، به عملوندها مراجعه کنید.

برای درایورهای NN HAL 1.2 یا بالاتر، وقتی درخواستی تکمیل می‌شود، وضعیت خطا، شکل برونداد، و اطلاعات زمان‌بندی به چارچوب برگردانده می‌شود. درطول اجرا، برونداد یا عملوندهای داخلی مدل می‌تواند یک یا چند بُعد ناشناخته یا رتبه ناشناخته داشته باشد. وقتی حداقل یک عملوند برونداد دارای بُعد یا رتبه ناشناخته باشد، درایور باید اطلاعات برونداد با اندازه پویا برگرداند.

برای رانندگان دارای NN HAL نسخه ۱.۱ یا پایین‌تر، فقط وضعیت خطا هنگام تکمیل درخواست برگردانده می‌شود. ابعاد عملوندهای ورودی و خروجی باید به‌طور کامل مشخص شوند تا اجرا با موفقیت تکمیل شود. عملوندهای داخلی می‌توانند یک یا چند بُعد ناشناخته داشته باشند، اما باید رتبه مشخصی داشته باشند.

برای درخواست‌های کاربر که چندین درایور را دربرمی‌گیرد، چارچوب مسئول رزرو حافظه واسطه و ترتیب دادن تماس‌ها با هر درایور است.

چندین درخواست می‌تواند به‌صورت موازی در همان @1.3::IPreparedModel آغاز شود. گرداننده می‌تواند درخواست‌ها را به‌طور موازی اجرا کند یا اجراها را به‌صورت سریالی انجام دهد.

چارچوب می‌تواند از درایور بخواهد بیش‌از یک مدل آماده‌شده را نگه دارد. برای مثال، مدل m1 را آماده کنید، m2 را آماده کنید، درخواست r1 را در m1 اجرا کنید، r2 را در m2 اجرا کنید، r3 را در m1 اجرا کنید، r4 را در m2 اجرا کنید، m1 را آزاد کنید (در پاک‌سازی شرح داده شده است)، و m2 را آزاد کنید.

برای جلوگیری از اجرای اولیه کند که می‌تواند منجر به تجربه کاربری ضعیف شود (برای مثال، لرزش اولین قاب)، درایور باید بیشتر مقداردهی‌های اولیه را در مرحله تدوین انجام دهد. مقداردهی اولیه در اولین اجرا باید به کنش‌هایی محدود شود که اگر زود انجام شوند، بر سلامت سیستم تأثیر منفی می‌گذارند، مانند رزرو کردن میان‌گیرهای موقت بزرگ یا افزایش نرخ ساعت دستگاه. گردانندگانی که فقط می‌توانند تعداد محدودی مدل هم‌زمان آماده کنند ممکن است مجبور شوند مقداردهی اولیه را در اولین اجرا انجام دهند.

در Android 10 یا بالاتر، در مواردی که چندین اجرا با مدل آماده یکسان به‌سرعت پشت سر هم اجرا می‌شوند، مشتری می‌تواند از یک شیء انفجار اجرا برای ارتباط بین فرایندهای برنامه و درایور استفاده کند. برای اطلاعات بیشتر، اجراهای انفجاری و صف‌های پیام سریع را ببینید.

برای بهبود عملکرد در اجرای‌های متعدد و سریع، گرداننده می‌تواند بافرهای موقت را نگه دارد یا نرخ ساعت را افزایش دهد. توصیه می‌شود رشته ناظر ایجاد کنید تا اگر بعداز مدت زمان مشخصی درخواست جدیدی ایجاد نشد، منابع آزاد شوند.

شکل برونداد

برای درخواست‌هایی که یک یا چند عملوند خروجی همه ابعاد را ندارند مشخص شده است، درایور باید فهرستی از شکل‌های خروجی حاوی اطلاعات ابعاد برای هر عملوند خروجی پس‌از اجرا. برای اطلاعات بیشتر درباره ابعاد، OutputShape را ببینید.

اگر اجرایی به‌دلیل کوچک بودن بافر برونداد ناموفق باشد، درایور باید در فهرست شکل‌های برونداد، نشان دهد کدام عملوندهای برونداد بافر کافی ندارند، و باید تا حد امکان اطلاعات ابعادی را گزارش کند، و برای ابعادی که ناشناخته هستند از صفر استفاده کند.

زمان‌بندی

در Android 10، اگر برنامه دستگاه واحدی را برای استفاده درطول فرایند تدوین مشخص کرده باشد، برنامه می‌تواند زمان اجرای آن را درخواست کند. برای جزئیات، MeasureTiming و کشف و تخصیص دستگاه را ببینید. در این مورد، هنگام اجرای درخواست، درایور NN HAL 1.2 باید مدت اجرا را اندازه‌گیری کند یا UINT64_MAX را گزارش کند (برای نشان دادن اینکه مدت دردسترس نیست). راننده باید هرگونه جریمه عملکردی ناشی از اندازه‌گیری مدت اجرای برنامه را به حداقل برساند.

درایور مدت‌های زیر را برحسب میکروثانیه در ساختار Timing گزارش می‌کند:

  • زمان اجرا در دستگاه: شامل زمان اجرا در گرداننده که در پردازنده میزبان اجرا می‌شود نمی‌شود.
  • زمان اجرا در درایور: شامل زمان اجرا در دستگاه می‌شود.

این مدت‌ها باید شامل زمانی باشد که اجرا به‌حالت تعلیق درآمده است، برای مثال، زمانی که اجرا توسط کارهای دیگر پیش‌دستی شده است یا زمانی که منتظر است تا منبعی دردسترس قرار گیرد.

وقتی از درایور خواسته نشده است مدت زمان اجرا را اندازه‌گیری کند، یا وقتی خطای اجرا وجود دارد، درایور باید مدت زمان‌ها را به‌صورت UINT64_MAX گزارش کند. حتی وقتی از درایور خواسته شده است مدت اجرای دستور را اندازه‌گیری کند، می‌تواند به‌جای آن UINT64_MAX را برای زمان در دستگاه، زمان در درایور، یا هر دو گزارش کند. وقتی درایور هر دو مدت را به‌عنوان مقداری غیراز UINT64_MAX گزارش می‌کند، زمان اجرا در درایور باید برابر یا بیشتر از زمان در دستگاه باشد.

اجرای حصارکشی‌شده

در Android 11،‏ NNAPI به اجراها اجازه می‌دهد تا منتظر فهرستی از دسته‌های sync_fence بمانند و به‌طور اختیاری یک شیء sync_fence را برگردانند که پس‌از تکمیل اجرا علامت‌دهی می‌شود. این کار سربار را برای مدل‌های توالی کوچک و موارد استفاده جاری‌سازی کاهش می‌دهد. اجرای محدودشده همچنین امکان تعامل‌پذیری کارآمدتر با دیگر مؤلفه‌هایی را فراهم می‌کند که می‌توانند sync_fence را علامت‌گذاری کنند یا منتظر آن بمانند. برای اطلاعات بیشتر درباره sync_fence، چارچوب همگام‌سازی را ببینید.

در اجرای حصارکشی‌شده، چارچوب متد IPreparedModel::executeFenced را برای راه‌اندازی اجرای ناهمگام حصارکشی‌شده در مدل آماده‌شده با بردار حصارهای همگام‌سازی برای انتظار فراخوانی می‌کند. اگر تکلیف ناهم‌زمان قبل‌از برگشت تماس تمام شود، می‌توان شناسه مجازی خالی برای sync_fence برگرداند. برای اینکه چارچوب بتواند وضعیت خطا و اطلاعات مدت را پُرسمان کند، باید شیء IFencedExecutionCallback نیز برگردانده شود.

پس‌از تکمیل اجرا، دو مقدار زمان‌بندی زیر که مدت‌زمان اجرا را اندازه‌گیری می‌کنند می‌توانند ازطریق IFencedExecutionCallback::getExecutionInfo پرس‌وجو شوند.

  • timingLaunched: مدت‌زمان از وقتی که executeFenced فراخوانی می‌شود تا وقتی که executeFenced syncFence برگردانده‌شده را علامت‌گذاری می‌کند.
  • timingFenced: مدت زمانی که همه موانع همگام‌سازی که اجرا منتظر آن‌ها است علامت‌گذاری می‌شوند تا زمانی که executeFenced syncFence برگشتی را علامت‌گذاری می‌کند.

کنترل جریان

برای دستگاه‌های دارای Android 11 یا بالاتر، NNAPI شامل دو عملیات جریان کنترل، IF و WHILE، است که مدل‌های دیگر را به‌عنوان آرگومان می‌گیرند و آن‌ها را به‌صورت شرطی (IF) یا مکرر (WHILE) اجرا می‌کنند. برای اطلاعات بیشتر درباره نحوه پیاده‌سازی این، به جریان کنترل مراجعه کنید.

کیفیت خدمات

در Android 11، «میانای برنامه‌سازی کاربردی شبکه عصبی» با امکان دادن به برنامه برای نشان دادن اولویت‌های نسبی مدل‌هایش، حداکثر زمان موردانتظار برای آماده شدن مدل، و حداکثر زمان موردانتظار برای تکمیل اجرا، کیفیت خدمات (QoS) را بهبود می‌بخشد. برای اطلاعات بیشتر، کیفیت خدمات را ببینید.

پاک‌سازی

وقتی برنامه استفاده از مدل آماده‌شده را تمام می‌کند، چارچوب ارجاع خود به شیء @1.3::IPreparedModel را منتشر می‌کند. وقتی دیگر به شیء IPreparedModel ارجاع داده نمی‌شود، این شیء به‌طور خودکار در سرویس درایوری که آن را ایجاد کرده است ازبین می‌رود. منابع مختص مدل را می‌توان در این زمان در پیاده‌سازی درایور تخریب‌کننده بازیابی کرد. اگر سرویس درایور می‌خواهد شیء IPreparedModel وقتی دیگر توسط کارخواه موردنیاز نیست به‌طور خودکار ازبین برود، نباید پس‌از اینکه شیء IPreparedeModel ازطریق IPreparedModelCallback::notify_1_3 برگردانده شد، هیچ ارجاعی به شیء IPreparedModel داشته باشد.

استفاده واحد پردازش مرکزی

انتظار می‌رود که درایورها از واحد پردازش مرکزی برای راه‌اندازی محاسبات استفاده کنند. راه‌اندازها نباید از CPU برای انجام محاسبات گراف استفاده کنند زیرا این کار با توانایی چارچوب برای تخصیص صحیح کار تداخل دارد. گرداننده باید بخش‌هایی را که نمی‌تواند مدیریت کند به چارچوب گزارش دهد و به چارچوب اجازه دهد بقیه را مدیریت کند.

این چارچوب پیاده‌سازی CPU را برای همه عملیات NNAPI به‌جز عملیات تعریف‌شده توسط فروشنده ارائه می‌دهد. برای اطلاعات بیشتر، به افزونه‌های فروشنده مراجعه کنید.

عملیات معرفی‌شده در Android 10 (سطح میانای برنامه‌سازی کاربردی ۲۹) فقط یک پیاده‌سازی CPU مرجع دارند تا تأیید کنند که آزمایش‌های CTS و VTS صحیح هستند. پیاده‌سازی‌های بهینه‌شده‌ای که در چارچوب‌های یادگیری ماشین تلفن همراه گنجانده شده‌اند بر پیاده‌سازی NNAPI CPU ترجیح داده می‌شوند.

توابع سودمندی

پایگاه کد NNAPI شامل توابع سودمندی است که سرویس‌های درایور می‌توانند از آن‌ها استفاده کنند.

این frameworks/ml/nn/common/include/Utils.h فایل حاوی توابع کمکی متنوعی است، مانند توابعی که برای ثبت گزارش و برای تبدیل بین نسخه‌های مختلف NN HAL استفاده می‌شوند.

  • VLogging: VLOG یک کلان‌دستور بسته‌بندی در اطراف LOG در Android است که فقط اگر برچسب مناسب در دارایی debug.nn.vlog تنظیم شده باشد، پیام را ثبت می‌کند. initVLogMask() باید قبل‌از هرگونه تماس با VLOG فراخوانی شود. از کلان‌دستور VLOG_IS_ON می‌توان برای بررسی اینکه آیا VLOG درحال‌حاضر فعال است یا نه استفاده کرد، و درصورت نیاز نبودن، از کد گزارش‌گیری پیچیده صرف‌نظر کرد. مقدار این دارایی باید یکی از موارد زیر باشد:

    • رشته خالی، نشان‌دهنده این است که هیچ گزارشی نباید انجام شود.
    • نشان 1 یا all، که نشان می‌دهد همه گزارش‌گیری‌ها باید انجام شود.
    • فهرستی از برچسب‌ها که با فاصله، کاما، یا دونقطه از هم جدا شده‌اند و نشان می‌دهند کدام گزارش‌گیری باید انجام شود. برچسب‌ها عبارت‌اند از compilation، cpuexe، driver، execution، manager، و model.
  • compliantWithV1_*: اگر بتوان شیء NN HAL را بدون ازدست دادن اطلاعات به نوع یکسان نسخه HAL دیگری تبدیل کرد، true را برمی‌گرداند. برای مثال، فراخوانی compliantWithV1_0 در V1_2::Model درصورتی‌که مدل شامل انواع عملیاتی باشد که در NN HAL 1.1 یا NN HAL 1.2 معرفی شده‌اند، false را برمی‌گرداند.

  • ‫convertToV1_*: شیء NN HAL را از یک نسخه به نسخه دیگر تبدیل می‌کند. اگر تبدیل منجر به ازدست رفتن اطلاعات شود (یعنی اگر نسخه جدید نوع نتواند مقدار را به‌طور کامل نشان دهد)، هشداری ثبت می‌شود.

  • قابلیت‌ها: از توابع nonExtensionOperandPerformance و update می‌توان برای کمک به ساختن فیلد Capabilities::operandPerformance استفاده کرد.

  • درحال جستجوی ویژگی‌های انواع: isExtensionOperandType، isExtensionOperationType، nonExtensionSizeOfData، nonExtensionOperandSizeOfData، nonExtensionOperandTypeIsScalar، tensorHasUnspecifiedDimensions.

این frameworks/ml/nn/common/include/ValidateHal.h فایل حاوی کارکردهای کمکی برای تأیید اعتبار شیء NN HAL براساس مشخصات نسخه HAL آن است.

  • ‫validate*: اگر شیء NN HAL طبق مشخصات نسخه HAL آن معتبر باشد، true را برمی‌گرداند. انواع OEM و انواع افزونه اعتبارسنجی نمی‌شوند. برای مثال، اگر مدل حاوی عملیاتی باشد که به نمایه عملوندی ارجاع می‌دهد که وجود ندارد، یا عملیاتی که در آن نسخه HAL پشتیبانی نمی‌شود، validateModel مقدار false را برمی‌گرداند.

این frameworks/ml/nn/common/include/Tracing.h فایل حاوی ماکروهایی برای ساده کردن افزودن اطلاعات systracing به کد «شبکه‌های عصبی» است. برای مثال، فراخوانی‌های کلان NNTRACE_* را در درایور نمونه ببینید.

فایل frameworks/ml/nn/common/include/GraphDump.h حاوی تابع سودمندی برای روبرداری محتوای Model به‌صورت گرافیکی برای اهداف اشکال‌زدایی است.

  • graphDump: نمایش مدل را در قالب Graphviz (.dot) در جاری‌سازی مشخص‌شده (درصورت ارائه) یا در logcat (درصورت عدم ارائه جاری‌سازی) می‌نویسد.

اعتبارسنجی

برای آزمایش پیاده‌سازی NNAPI، از آزمایش‌های VTS و CTS موجود در چارچوب Android استفاده کنید. ‫VTS مستقیماً درایورهای شما را تمرین می‌دهد (بدون استفاده از چارچوب)، درحالی‌که CTS آن‌ها را به‌طور غیرمستقیم ازطریق چارچوب تمرین می‌دهد. این آزمایش‌ها هر روش میانای برنامه‌سازی کاربردی را آزمایش می‌کنند و تأیید می‌کنند که همه عملیات پشتیبانی‌شده توسط راه‌اندازها به‌درستی کار می‌کنند و نتایجی ارائه می‌دهند که الزامات دقت را برآورده می‌کنند.

الزامات دقت در CTS و VTS برای NNAPI به‌شرح زیر است:

  • نقطه شناور: abs(expected - actual) <= atol + rtol  * abs(expected); where:

    • برای fp32،‏ atol = 1e-5f،‏ rtol = 5.0f * 1.1920928955078125e-7
    • برای fp16، atol = rtol = 5.0f * 0.0009765625f
  • کوانتیزه: یک واحد خطا (به‌جز mobilenet_quantized، که سه واحد خطا دارد)

  • بولی: انطباق دقیق

یکی از روش‌های تست NNAPI توسط CTS، تولید گراف‌های شبه‌تصادفی ثابت است که برای تست و مقایسه نتایج اجرای هر درایور با پیاده‌سازی مرجع NNAPI استفاده می‌شود. برای درایورهای دارای NN HAL نسخه ۱.۲ یا بالاتر، اگر نتایج معیارهای دقت را برآورده نکند، CTS خطا گزارش می‌کند و فایل مشخصات مدل ناموفق را در /data/local/tmp برای اشکال‌زدایی تخلیه می‌کند. برای جزئیات بیشتر درباره معیارهای دقت، TestRandomGraph.cpp و TestHarness.h را ببینید.

آزمایش فاز

هدف از آزمایش فاز پیدا کردن خرابی‌ها، ادعاها، نقض‌های حافظه، یا رفتار تعریف‌نشده عمومی در کد تحت آزمایش به‌دلیل عواملی مانند ورودی‌های غیرمنتظره است. برای آزمایش فاز NNAPI، ‏Android از آزمایش‌های مبتنی بر libFuzzer استفاده می‌کند که در فاز کردن کارآمد هستند زیرا از پوشش خطی موارد آزمایش قبلی برای تولید ورودی‌های تصادفی جدید استفاده می‌کنند. برای مثال، libFuzzer چارچوب‌های تستی را ترجیح می‌دهد که روی خطوط جدید کد اجرا می‌شوند. این کار زمان لازم برای یافتن کد مشکل‌دار توسط آزمایش‌ها را به‌شدت کاهش می‌دهد.

برای انجام آزمایش فاز جهت اعتبارسنجی پیاده‌سازی درایور، frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp را در ابزار کمکی آزمایشی libneuralnetworks_driver_fuzzer موجود در AOSP اصلاح کنید تا کد درایور شما را دربرگیرد. برای کسب اطلاعات بیشتر درباره آزمایش فازی NNAPI، به frameworks/ml/nn/runtime/test/android_fuzzing/README.md مراجعه کنید.

امنیت

ازآنجایی‌که فرایندهای برنامه مستقیماً با فرایند درایور ارتباط برقرار می‌کنند، درایورها باید متغیرهای مستقل تماس‌هایی را که دریافت می‌کنند اعتبارسنجی کنند. این اعتبارسنجی توسط VTS درستی‌سنجی شده است. کد اعتبارسنجی در frameworks/ml/nn/common/include/ValidateHal.h است.

رانندگان همچنین باید مطمئن شوند که برنامه‌ها هنگام استفاده از یک دستگاه نمی‌توانند با برنامه‌های دیگر تداخل داشته باشند.

مجموعه آزمون یادگیری ماشین Android

«مجموعه آزمایشی یادگیری ماشین Android» (MLTS) یک معیار NNAPI است که در CTS و VTS برای اعتبارسنجی دقت مدل‌های واقعی در دستگاه‌های فروشنده گنجانده شده است. این معیار سنجش، تأخیر و دقت را ارزیابی می‌کند و نتایج درایورها را با نتایج استفاده از TF Lite که روی CPU اجرا می‌شود برای همان مدل و مجموعه‌های داده مقایسه می‌کند. این کار تضمین می‌کند که دقت درایور از پیاده‌سازی مرجع CPU بدتر نباشد.

توسعه‌دهندگان پلاتفرم Android نیز از MLTS برای ارزیابی تأخیر و دقت درایورها استفاده می‌کنند.

شاخص ارزیابی NNAPI را می‌توانید در دو پروژه در AOSP پیدا کنید:

مدل‌ها و مجموعه‌های داده

معیار NNAPI از مدل‌ها و مجموعه داده‌های زیر استفاده می‌کند.

  • MobileNetV1 ممیز شناور و u8 کوانتیزه‌شده در اندازه‌های مختلف، دربرابر زیرمجموعه کوچکی (۱۵۰۰ تصویر) از Open Images Dataset v4 اجرا می‌شود.
  • ‫MobileNetV2 ممیز شناور و کوانتیزه u8 در اندازه‌های مختلف، دربرابر زیرمجموعه کوچکی (۱۵۰۰ تصویر) از مجموعه داده Open Images v4 اجرا می‌شود.
  • مدل صوتی مبتنی بر حافظه کوتاه‌مدت بلندمدت (LSTM) برای تبدیل نوشتار به گفتار، که دربرابر زیرمجموعه کوچکی از مجموعه CMU Arctic اجرا می‌شود.
  • مدل صوتی مبتنی بر LSTM برای تشخیص خودکار گفتار، که دربرابر زیرمجموعه کوچکی از مجموعه داده LibriSpeech اجرا می‌شود.

برای اطلاعات بیشتر، به platform/test/mlts/models مراجعه کنید.

آزمایش فشار

«مجموعه آزمایشی یادگیری ماشین Android» شامل مجموعه‌ای از آزمون‌های خرابی برای تأیید انعطاف‌پذیری درایورها تحت شرایط استفاده سنگین یا در موقعیت‌های خاص رفتار مشتریان است.

همه آزمایش‌های خرابی ویژگی‌های زیر را ارائه می‌دهند:

  • تشخیص توقف: اگر مشتری NNAPI درطول آزمایش متوقف شود، آزمایش با دلیل خرابی HANG ناموفق می‌شود و مجموعه آزمایش به آزمایش بعدی می‌رود.
  • تشخیص خرابی کارخواه NNAPI: آزمایش‌ها از خرابی‌های کارخواه جان سالم به‌در می‌برند و آزمایش‌ها با دلیل خرابی CRASH ناموفق می‌شوند.
  • تشخیص خرابی درایور: آزمایش‌ها می‌توانند خرابی درایور را که باعث ایجاد خطا در تماس NNAPI می‌شود تشخیص دهند. توجه داشته باشید که ممکن است در فرایندهای درایور خرابی‌هایی وجود داشته باشد که باعث خرابی NNAPI نشود و باعث عدم موفقیت آزمایش نشود. برای پوشش دادن این نوع خرابی، توصیه می‌شود فرمان tail را در گزارش سیستم برای خطاها یا ازکارافتادن‌های مربوط به درایور اجرا کنید.
  • هدف‌یابی همه شتاب‌دهنده‌های دردسترس: آزمایش‌ها دربرابر همه درایورهای دردسترس اجرا می‌شوند.

همه آزمایش‌های تصادف چهار نتیجه احتمالی زیر را دارند:

  • ‫SUCCESS: اجرا بدون خطا تکمیل شد.
  • FAILURE: اجرا ناموفق بود. معمولاً به‌دلیل خطایی هنگام آزمایش مدل رخ می‌دهد و نشان می‌دهد که درایور نتوانسته است مدل را اجرا یا تدوین کند.
  • ‫HANG: فرایند آزمایش پاسخ نمی‌دهد.
  • ‫CRASH: فرایند آزمایش ازکار افتاد.

برای کسب اطلاعات بیشتر درباره آزمایش استرس و فهرست کامل آزمایش‌های خرابی، به platform/test/mlts/benchmark/README.txt مراجعه کنید.

استفاده از MLTS

برای استفاده از MLTS:

  1. دستگاه هدفی را به ایستگاه کاری‌تان متصل کنید و مطمئن شوید ازطریق adb قابل‌دسترسی باشد. اگر بیش‌از یک دستگاه متصل است، متغیر محیطی ANDROID_SERIAL دستگاه هدف را صادر کنید.
  2. cd در فهرست راهنمای منبع سطح بالای Android.

    source build/envsetup.sh
    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available.
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    در پایان اجرای معیار، نتایج به‌عنوان صفحه HTML ارائه می‌شود و به xdg-open ارسال می‌شود.

برای اطلاعات بیشتر، به platform/test/mlts/benchmark/README.txt مراجعه کنید.

نسخه‌های HAL «شبکه‌های عصبی»

این بخش تغییرات معرفی‌شده در نسخه‌های Android و Neural Networks HAL را شرح می‌دهد.

Android 11

‫Android 11 نسخه NN HAL 1.3 را معرفی می‌کند که شامل تغییرات قابل‌توجه زیر است.

  • پشتیبانی از کم‌سازی ۸ بیتی امضادار در NNAPI. نوع عملوند را اضافه می‌کند. TENSOR_QUANT8_ASYMM_SIGNED گردانندگان دارای NN HAL 1.3 که از عملکردها با کمیت‌سازی بدون علامت پشتیبانی می‌کنند باید از گونه‌های علامت‌دار آن عملکردها نیز پشتیبانی کنند. هنگام اجرای نسخه‌های امضاشده و امضانشده اکثر عملیات‌های کمی‌سازی‌شده، درایورها باید نتایج یکسانی تا انحراف ۱۲۸ تولید کنند. پنج استثنا برای این الزام وجود دارد: CAST، HASHTABLE_LOOKUP، LSH_PROJECTION، PAD_V2، و QUANTIZED_16BIT_LSTM. عملیات QUANTIZED_16BIT_LSTM از عملوندهای علامت‌دار پشتیبانی نمی‌کند و چهار عملیات دیگر از کوانتش علامت‌دار پشتیبانی می‌کنند اما نیازی نیست نتایج یکسان باشد.
  • پشتیبانی از اجراهای حصارکشی‌شده که در آن چارچوب، روش IPreparedModel::executeFenced را برای راه‌اندازی اجرای ناهمگام حصارکشی‌شده در مدل آماده‌شده با بردار حصارهای همگام‌سازی برای انتظار فراخوانی می‌کند. برای اطلاعات بیشتر، به اجرای محصور مراجعه کنید.
  • پشتیبانی از جریان کنترل. عملیات IF و WHILE را اضافه می‌کند که مدل‌های دیگر را به‌عنوان آرگومان می‌گیرند و آن‌ها را به‌صورت شرطی (IF) یا مکرر (WHILE) اجرا می‌کنند. برای اطلاعات بیشتر، به جریان کنترل مراجعه کنید.
  • بهبود کیفیت سرویس (QoS) زیرا برنامه‌ها می‌توانند اولویت‌های نسبی مدل‌های خود، حداکثر زمان موردانتظار برای آماده شدن مدل، و حداکثر زمان موردانتظار برای تکمیل اجرا را نشان دهند. برای اطلاعات بیشتر، کیفیت خدمات را ببینید.
  • پشتیبانی از دامنه‌های حافظه که میاناهای تخصیص‌دهنده برای میان‌گیرهای تحت مدیریت درایور ارائه می‌دهند. این کار امکان می‌دهد حافظه‌های بومی دستگاه در سراسر اجراها منتقل شود و کپی و تبدیل داده‌های غیرضروری بین اجراهای متوالی در یک درایور سرکوب شود. برای اطلاعات بیشتر، دامنه‌های حافظه را ببینید.

Android 10

‫Android 10 «لایه انتزاع سخت‌افزاری شبکه عصبی» نسخه ۱.۲ را معرفی می‌کند که شامل تغییرات قابل‌توجه زیر است.

  • ساختار Capabilities شامل همه انواع داده ازجمله انواع داده اسکالر است و عملکرد غیرآزاد را بااستفاده از بردار به‌جای فیلدهای نام‌دار نشان می‌دهد.
  • روش‌های getVersionString و getType به چارچوب اجازه می‌دهد تا نوع دستگاه (DeviceType) و اطلاعات نسخه را بازیابی کند. به کشف و تخصیص دستگاه مراجعه کنید.
  • روش executeSynchronously به‌طور پیش‌فرض برای انجام اجرای هم‌زمان فراخوانی می‌شود. روش execute_1_2 به چارچوب می‌گوید که اجرا را به‌صورت ناهم‌زمان انجام دهد. اجرا را ببینید.
  • پارامتر MeasureTiming برای executeSynchronously، execute_1_2، و اجرای انفجاری مشخص می‌کند که آیا درایور باید مدت اجرای را اندازه‌گیری کند یا نه. نتایج در ساختار Timing گزارش می‌شود. به بخش زمان‌بندی مراجعه کنید.
  • پشتیبانی از اجراهایی که در آن‌ها یک یا چند عملوند برونداد دارای بُعد یا رتبه ناشناخته است. شکل برونداد را ببینید.
  • پشتیبانی از افزونه‌های فروشنده که مجموعه‌ای از عملیات و انواع داده‌های تعریف‌شده توسط فروشنده هستند. افزونه‌های پشتیبانی‌شده را ازطریق روش IDevice::getSupportedExtensions گزارش می‌کند. افزونه‌های فروشنده را ببینید.
  • توانایی کنترل مجموعه‌ای از اجراهای پشت سر هم توسط یک شیء پشت سر هم بااستفاده از صف‌های پیام سریع (FMQ) برای برقراری ارتباط بین برنامه و فرایندهای گرداننده، که باعث کاهش تأخیر می‌شود. اجراهای پشت سر هم و صف‌های پیام سریع را ببینید.
  • پشتیبانی از AHardwareBuffer برای اینکه درایور بتواند اجراها را بدون کپی کردن داده‌ها انجام دهد. AHardwareBuffer را ببینید.
  • پشتیبانی بهبودیافته برای ذخیره کردن مصنوعات تدوین در حافظه نهان به‌منظور کاهش زمان مورد استفاده برای تدوین هنگام شروع برنامه. به ذخیره کردن در حافظه نهان گردآوری مراجعه کنید.

‫Android 10 انواع عملوند و عملگرهای زیر را معرفی می‌کند.

  • انواع عملوند

    • ANEURALNETWORKS_BOOL
    • ANEURALNETWORKS_FLOAT16
    • ANEURALNETWORKS_TENSOR_BOOL8
    • ANEURALNETWORKS_TENSOR_FLOAT16
    • ANEURALNETWORKS_TENSOR_QUANT16_ASYMM
    • ANEURALNETWORKS_TENSOR_QUANT16_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
  • عملیات

    • ANEURALNETWORKS_ABS
    • ANEURALNETWORKS_ARGMAX
    • ANEURALNETWORKS_ARGMIN
    • ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN
    • ANEURALNETWORKS_BOX_WITH_NMS_LIMIT
    • ANEURALNETWORKS_CAST
    • ANEURALNETWORKS_CHANNEL_SHUFFLE
    • ANEURALNETWORKS_DETECTION_POSTPROCESSING
    • ANEURALNETWORKS_EQUAL
    • ANEURALNETWORKS_EXP
    • ANEURALNETWORKS_EXPAND_DIMS
    • ANEURALNETWORKS_GATHER
    • ANEURALNETWORKS_GENERATE_PROPOSALS
    • ANEURALNETWORKS_GREATER
    • ANEURALNETWORKS_GREATER_EQUAL
    • ANEURALNETWORKS_GROUPED_CONV_2D
    • ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT
    • ANEURALNETWORKS_INSTANCE_NORMALIZATION
    • ANEURALNETWORKS_LESS
    • ANEURALNETWORKS_LESS_EQUAL
    • ANEURALNETWORKS_LOG
    • ANEURALNETWORKS_LOGICAL_AND
    • ANEURALNETWORKS_LOGICAL_NOT
    • ANEURALNETWORKS_LOGICAL_OR
    • ANEURALNETWORKS_LOG_SOFTMAX
    • ANEURALNETWORKS_MAXIMUM
    • ANEURALNETWORKS_MINIMUM
    • ANEURALNETWORKS_NEG
    • ANEURALNETWORKS_NOT_EQUAL
    • ANEURALNETWORKS_PAD_V2
    • ANEURALNETWORKS_POW
    • ANEURALNETWORKS_PRELU
    • ANEURALNETWORKS_QUANTIZE
    • ANEURALNETWORKS_QUANTIZED_16BIT_LSTM
    • ANEURALNETWORKS_RANDOM_MULTINOMIAL
    • ANEURALNETWORKS_REDUCE_ALL
    • ANEURALNETWORKS_REDUCE_ANY
    • ANEURALNETWORKS_REDUCE_MAX
    • ANEURALNETWORKS_REDUCE_MIN
    • ANEURALNETWORKS_REDUCE_PROD
    • ANEURALNETWORKS_REDUCE_SUM
    • ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR
    • ANEURALNETWORKS_ROI_ALIGN
    • ANEURALNETWORKS_ROI_POOLING
    • ANEURALNETWORKS_RSQRT
    • ANEURALNETWORKS_SELECT
    • ANEURALNETWORKS_SIN
    • ANEURALNETWORKS_SLICE
    • ANEURALNETWORKS_SPLIT
    • ANEURALNETWORKS_SQRT
    • ANEURALNETWORKS_TILE
    • ANEURALNETWORKS_TOPK_V2
    • ANEURALNETWORKS_TRANSPOSE_CONV_2D
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN

‫Android 10 به‌روزرسانی‌هایی را برای بسیاری از عملکردهای موجود معرفی می‌کند. به‌روزرسانی‌ها بیشتر مربوط به موارد زیر است:

  • پشتیبانی از چیدمان حافظه NCHW
  • پشتیبانی از تانسورهایی با رتبه متفاوت از ۴ در عملیات softmax و نرمال‌سازی
  • پشتیبانی از پیچیدگی‌های گسترده
  • پشتیبانی از ورودی‌های دارای کوانتش مختلط در ANEURALNETWORKS_CONCATENATION

فهرست زیر عملیاتی را نشان می‌دهد که در Android 10 اصلاح شده‌اند. برای جزئیات کامل تغییرات، به OperationCode در اسناد مرجع NNAPI مراجعه کنید.

  • ANEURALNETWORKS_ADD
  • ANEURALNETWORKS_AVERAGE_POOL_2D
  • ANEURALNETWORKS_BATCH_TO_SPACE_ND
  • ANEURALNETWORKS_CONCATENATION
  • ANEURALNETWORKS_CONV_2D
  • ANEURALNETWORKS_DEPTHWISE_CONV_2D
  • ANEURALNETWORKS_DEPTH_TO_SPACE
  • ANEURALNETWORKS_DEQUANTIZE
  • ANEURALNETWORKS_DIV
  • ANEURALNETWORKS_FLOOR
  • ANEURALNETWORKS_FULLY_CONNECTED
  • ANEURALNETWORKS_L2_NORMALIZATION
  • ANEURALNETWORKS_L2_POOL_2D
  • ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION
  • ANEURALNETWORKS_LOGISTIC
  • ANEURALNETWORKS_LSH_PROJECTION
  • ANEURALNETWORKS_LSTM
  • ANEURALNETWORKS_MAX_POOL_2D
  • ANEURALNETWORKS_MEAN
  • ANEURALNETWORKS_MUL
  • ANEURALNETWORKS_PAD
  • ANEURALNETWORKS_RELU
  • ANEURALNETWORKS_RELU1
  • ANEURALNETWORKS_RELU6
  • ANEURALNETWORKS_RESHAPE
  • ANEURALNETWORKS_RESIZE_BILINEAR
  • ANEURALNETWORKS_RNN
  • ANEURALNETWORKS_ROI_ALIGN
  • ANEURALNETWORKS_SOFTMAX
  • ANEURALNETWORKS_SPACE_TO_BATCH_ND
  • ANEURALNETWORKS_SPACE_TO_DEPTH
  • ANEURALNETWORKS_SQUEEZE
  • ANEURALNETWORKS_STRIDED_SLICE
  • ANEURALNETWORKS_SUB
  • ANEURALNETWORKS_SVDF
  • ANEURALNETWORKS_TANH
  • ANEURALNETWORKS_TRANSPOSE

Android 9

‫NN HAL 1.1 در Android 9 معرفی شده است و شامل تغییرات قابل‌توجه زیر است.

  • ‫IDevice::prepareModel_1_1 شامل پارامتر ExecutionPreference است. راننده می‌تواند از این برای تنظیم آماده‌سازی خود استفاده کند، با این آگاهی که برنامه ترجیح می‌دهد باتری را حفظ کند یا مدل را در تماس‌های متوالی سریع اجرا خواهد کرد.
  • نه عملیات جدید اضافه شده است: BATCH_TO_SPACE_ND، DIV، MEAN، PAD، SPACE_TO_BATCH_ND، SQUEEZE، STRIDED_SLICE، SUB، TRANSPOSE.
  • برنامه می‌تواند مشخص کند که محاسبات ممیز شناور ۳۲ بیتی می‌تواند بااستفاده از محدوده و/یا دقت ممیز شناور ۱۶ بیتی با تنظیم Model.relaxComputationFloat32toFloat16 روی true اجرا شود. ساخت Capabilities فیلد اضافی relaxedFloat32toFloat16Performance را دارد تا کاربر بتواند عملکرد آسان‌گیر خود را به چارچوب گزارش کند.

Android 8.1

«لایه انتزاع سخت‌افزاری شبکه‌های عصبی» اولیه (۱.۰) در Android 8.1 منتشر شد. برای اطلاعات بیشتر، /neuralnetworks/1.0/ را ببینید.