Розробка PyTorch Mobile: де ламається інференс на пристрої
Модель навчена, метрики на валідації в порядку, а на пристрої результат не збігається із серверним. Причина майже завжди в розбіжності обчислювальних шляхів: на сервері працюють одні оператори з плаваючою точкою, на телефоні — квантовані ядра, і частина шарів трактується інакше.
Помилка накопичується по шарах і на виході дає інший клас або зсунуту координату. Ловиться це тільки порівнянням виходів на одному наборі входів — проганяємо еталонний батч через серверну та мобільну збірку і дивимося розбіжність по кожному виходу, а не по підсумковій точності.
Друга відмова — зростання часу відгуку. На папері модель вкладається в бюджет, але на живому пристрої в нього втручаються прогрів, перемикання потоків і робота з пам'яттю. Перший інференс після запуску завжди повільніший за наступні, тому замір «у середньому» бреше.
Ми знімаємо розподіл: час холодного старту, усталений час, поведінка під навантаженням при активному інтерфейсі. Якщо важкі шари впираються в один потік, допомагає перерозподіл обчислень і винесення частини обробки за межі критичного шляху.
Третя і найдорожча — падіння застосунку на слабких пристроях. Модель, яка спокійно живе на флагмані, на бюджетному телефоні впирається в доступну пам'ять і вивантажується системою.
Звідси два напрямки роботи: контроль пікового споживання пам'яті при завантаженні ваг і коректна деградація, коли ресурсів не вистачає — перехід на полегшену гілку моделі замість аварійного завершення.
Усі три відмови пов'язані: оптимізація під швидкість майже завжди змінює чисельний результат, а економія пам'яті впливає на обидва показники. Тому розбираємо їх разом — як єдиний контур, а не окремо.
Що дає перенесення моделі на пристрій
Перенесення моделі на пристрій змінює фізику роботи застосунку: інференс виконується локально, і результат не залежить від якості каналу в момент запиту.
Для сценаріїв, де користувач знімає, розпізнає або класифікує щось «тут і зараз», це принципово — застосунок працює офлайн, а не деградує до заглушки при втраті мережі.
Навантаження на сервер перестає масштабуватися разом із кількістю користувачів. Раніше кожен кадр або запит ішов у хмару, і пікова активність перетворювалася на чергу на бекенді; тепер обчислення розподілене по пристроях, а сервер займається лише синхронізацією та оновленням ваг.
Час відгуку стає передбачуваним: немає мережевого кола, немає очікування в черзі — затримка визначається тільки пристроєм і стабільна від запиту до запиту.
Окремий ефект — зникає цілий клас відмов, пов'язаних з обривом зв'язку та таймаутами: там, де раніше користувач бачив помилку, застосунок продовжує працювати.
Приватність даних посилюється як наслідок: сирі фото, аудіо та текст не залишають пристрій, назовні йде тільки результат, якщо він взагалі потрібен.
Ми збираємо інференс на PyTorch Mobile — це зріла гілка з квантуванням і апаратним прискоренням, тому модель вкладається в розумний розмір і не з'їдає батарею.
Що це дає в цифрах: частка запитів, що йдуть на сервер, падає до нуля для офлайн-сценаріїв, час відгуку перестає залежати від мережі, а витрати на інфраструктуру перестають зростати разом з аудиторією.
Способи запуску моделі на телефоні: порівняння
Вибір точки інференсу — перше архітектурне рішення, яке визначає і розмір застосунку, і сценарії роботи без мережі, і вартість серверної частини. Нижче — три робочі схеми, між якими реально обирають на старті проєкту, з умовами застосовності та тим, чим кожна обмежує.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Повністю на пристрої | Затримка важливіша за точність: розпізнавання мовлення, камера, жести, розмітка фото. Потрібна робота офлайн і без передавання даних назовні | Модель стискається до бюджету пам'яті та тепла; рідкісні класи втрачають точність; оновлення — лише з релізом застосунку |
| Гібридна схема | Важка частина обчислюється на сервері, легка — на телефоні: префільтр кадрів локально, точний розбір у хмарі | Потрібен акуратний контракт між частинами та деградація за поганої мережі; складніше тестувати |
| Лише серверний інференс | Модель часто перенавчається, потрібні свіжі ваги та єдина версія для всіх клієнтів | Без мережі функція не працює; затримка залежить від каналу; витрати на обчислення зростають разом із кількістю активних користувачів |
Гібридна схема зазвичай виграє там, де потік даних великий, а корисних подій мало: локальний фільтр відсікає зайве до відправлення, і сервер отримує вже відібрані кадри або фрагменти.
Це знижує і затримку відповіді, і навантаження на серверну частину, але вимагає явно описати, що відбувається при обриві зв'язку — інакше функція «завмирає» без пояснення для користувача.
Обмеження важливіші за можливості: на пристрої ви обмежені пам'яттю, нагрівом і часом автономної роботи, на сервері — каналом і вартістю обчислень.
Тому вибір підходу фіксуємо до початку оптимізації моделі: перевести готову мережу з сервера на телефон заднім числом майже завжди дорожче, ніж одразу закласти потрібний бюджет за розміром і затримкою.
Етапи впровадження: від аудиту моделі до передачі
Робота починається не з коду, а з аудиту моделі: дивимося архітектуру, вхідні та вихідні тензори, залежності від серверних операторів, які на пристрої не підтримані.
На цьому кроці фіксуємо, що доведеться переписати під мобільний інференс, а що переноситься як є — це знімає половину сюрпризів на етапі інтеграції.
- Аудит моделі та вимог. Розбираємо граф, заміряємо еталонну якість і час інференсу на сервері, фіксуємо цільові показники на пристрої: затримку відповіді, споживання пам'яті, поведінку без мережі.
- Схема інтеграції. Визначаємо, де обчислюється модель — на пристрої, на сервері чи гібридно, як застосунок отримує та оновлює ваги, що відбувається при нестачі пам'яті або відкликанні дозволів.
- Конвертація. Переводимо модель у мобільний формат, прибираємо непідтримувані оператори, перевіряємо, що виходи збігаються з еталоном у межах допустимого відхилення.
- Оптимізація. Квантування ваг, злиття операторів, обрізання зайвих гілок — женемося за розміром артефакту та часом відгуку, не втрачаючи якість за agreed-порогом.
- Інтеграція в застосунок. Вбудовуємо інференс у наявний код, виносимо його в окремий потік, щоб інтерфейс не блокувався, налаштовуємо завантаження та кеш ваг.
- Перевірка. Проганяємо набір тестів на реальних пристроях різних класів, звіряємо метрики з серверним еталоном, перевіряємо сценарії без мережі та при низькому заряді.
- Передача. Віддаємо зібрані артефакти, конфігурації, інструкції щодо оновлення моделі та розбір відомих обмежень — щоб команда могла розвивати рішення без нас.
Кожен етап закінчується артефактом, який можна перевірити: звіт з аудиту, схема, сконвертована модель, заміри до та після оптимізації. Так на будь-якому кроці видно, що зроблено і який результат отримано.
Що замовник отримує на руки
Передаємо не «працюючий застосунок», а комплект, за яким ваша команда зможе супроводжувати й розвивати модель без нас. Кожен артефакт закриває конкретний ризик: втрачений контекст, невідтворюване складання, неясні права на дані.
- Конфігурації складання та інференсу — версіоновані файли з параметрами квантизації, розміром вхідного тензора та порогами спрацювання. Дозволяють перезібрати модель один в один і порівняти поведінку на пристрої з еталоном.
- Схеми архітектури та потоків даних — від кадру камери або сигналу датчика до видачі результату: де вважається препроцесинг, де інференс, де постпроцесинг. За ними новий інженер входить у проєкт за дні, а не тижні.
- Політики доступу та розмежування ролей — хто з ваших співробітників може вивантажувати ваги, змінювати конфігурацію та публікувати складання. Окремо описуємо, як відкликаються доступи при виході людини.
- Регламент оновлення моделі — покроковий порядок: навчання, валідація на відкладеній вибірці, перевірка на пристрої, розкатка на частку користувачів, відкат. З критеріями, за яких реліз блокується автоматично.
- Документація щодо даних — походження датасету, розмітка, обмеження вибірки, відомі класи помилок. Без цього наступна ітерація навчання впирається в ті самі граблі.
- Інструкція з відкату — як повернути попередню версію моделі на пристрої та що відбувається з накопиченими локальними даними при відкаті.
- Чек-ліст приймання — метрики якості на цільовому парку пристроїв, а не лише на сервері, та перелік сценаріїв, які перевіряються перед кожним релізом.
Усе це передається у вашому репозиторії та у вашій системі управління доступом — не в закритому контурі підрядника. Опишіть задачу, і ми повернемося з оцінкою та планом: які артефакти потрібні саме вам, а які надлишкові для вашого масштабу.
Кейс: як скоротили час відгуку та прибрали відмови
Замовник — сервіс доставки — прийшов із класичною проблемою: модель розпізнавання документів працювала на сервері, і кожен скан йшов у мережу.
За середнього часу відгуку 4-6 секунд на слабкому каналі користувачі кидали операцію, а при втраті мережі застосунок показував помилку й втрачав уже зроблений знімок.
Частка невдалих спроб сягала 18%, і це був не «повільний інтерфейс», а прямий відтік: кур'єр не міг закрити замовлення й телефонував у підтримку.
Що змінили
Перенесли інференс на пристрій: модель зібрали під мобільні прискорювачі через PyTorch Mobile, обрізали граф і перевели ваги у формат, який читається без розпакування в пам'ять цілком.
Ключове — не сам перенос, а те, що навколо нього: черга задач із пріоритетами, локальний кеш останніх результатів і коректний фолбек, коли модель не впевнена у відповіді.
Тоді ж розвели два сценарії: якщо мережа є — важкі випадки йдуть на сервер, якщо немає — застосунок працює автономно й синхронізується пізніше.
Метрики до і після
| Показник | До | Після |
|---|---|---|
| Час відгуку на слабкому каналі | 4-6 с | 0,4-0,8 с |
| Частка невдалих спроб | 18% | 2% |
| Відмови при втраті мережі | регулярні | клас усунено |
| Розмір застосунку | — | +9 МБ до встановлення |
Окремо варто сказати про відмови при втраті мережі: раніше це був необроблений сценарій, тепер операція завершується локально, а результат досилається при відновленні зв'язку. Підтримка перестала отримувати звернення «не відправився скан» — їх просто не стало як класу.
Чим відрізняється локальний інференс від серверного?
Локальний інференс обчислює модель на пристрої користувача, серверний — на вашій інфраструктурі, і різниця проявляється одразу в чотирьох площинах.
Затримка: локальний режим не залежить від якості мережі — відповідь надходить за час обчислення на пристрої, тоді як серверний додає до обробки передавання даних туди й назад, а на слабкому каналі саме це передавання стає вузьким місцем.
Трафік: за локального інференсу на сервер надходять лише агреговані результати або телеметрія, а не самі дані; за серверного через канал проходить кожен кадр, фрагмент тексту чи сигнал, і обсяг зростає лінійно з кількістю активних користувачів.
Приватність — ключова відмінність. Локальний інференс обробляє персональні дані, зображення та голос усередині пристрою, назовні нічого не виходить: це знімає цілий клас ризиків під час роботи з чутливою інформацією та спрощує відповідність вимогам до обробки даних.
Серверний режим потребує захищеного передавання, зберігання та розмежування доступу — контролювати це складніше, ніж взагалі не виносити дані за периметр.
Оновлення моделі влаштовано дзеркально. На сервері ви викочуєте нову версію в одному місці, і всі клієнти одразу працюють із нею — але це ж означає, що застосунок залежить від доступності вашого сервісу.
Локально модель постачається всередині застосунку або підвантажується окремим артефактом, тому оновлення потребує релізу в магазинах або механізму доставки ваг із перевіркою цілісності та відкатом на попередню версію.
На практиці режими часто комбінують: критичне до затримки та приватності обчислюють на пристрої, а важкі або рідко викликувані моделі залишають на сервері. Вибір диктує профіль задачі, а не мода на технологію.
Технічні сумніви перед стартом
Перед стартом майже завжди виринають ті самі питання: чи працюватиме модель на парку пристроїв, чи не роздується застосунок, як оновлювати ваги без релізу в сторі. Нижче — короткі відповіді на кожне, щоб зняти невизначеність до оцінки.
Сумісність: модель, зібрана під PyTorch Mobile, піде на старих пристроях?
Ми збираємо модель під цільову гілку рантайму й перевіряємо на реальному парку: мінімальна підтримувана версія ОС, слабкі пристрої, різні набори інструкцій. Важкі оператори, яких немає в мобільному рантаймі, замінюємо на підтримувані еквіваленти або виносимо на сервер.
На виході — матриця сумісності: які пристрої та версії ОС покриті, де деградація точності чи швидкості.
Розмір моделі: застосунок не стане занадто важким?
Квантування ваг, обрізання незначущих зв'язків і розділення моделі на базову та підвантажувану частини дають кратне скорочення розміру артефакту. Базові шари кладемо в збірку, важкі — довантажуємо на вимогу.
Підсумковий приріст інсталяційного пакета тримаємо в межах, які не впливають на конверсію встановлень.
Оновлення: як змінювати модель без релізу в магазині застосунків?
Ваги та конфігурацію виносимо в окремий артефакт з версіонуванням і підписом. Застосунок перевіряє версію, довантажує оновлення й перемикається на нього, зберігаючи попереднє для відкату.
Так модель оновлюється незалежно від збірки, а невдале оновлення відкочується без участі користувача.
Налагодження на пристроях: як ловити проблеми, які не видно на емуляторі?
Збираємо профіль виконання на реальних пристроях: час інференсу, споживання пам'яті, нагрівання, частка відмов за типами пристроїв. Логи та метрики йдуть у загальну систему спостережуваності, тому регресію видно до релізу. Окремо перевіряємо поведінку при нестачі пам'яті та у фоні.
Підтримка пристроїв: що з новими моделями та версіями ОС?
Тримаємо рантайм і модель в актуальній гілці, тестовий парк поповнюємо новими пристроями в міру виходу. Регресійні прогони на кожному релізі показують, де поведінка змінилася. Це дозволяє додавати пристрої без переписування логіки.
Обговоримо ваше завдання
Щоб оцінка була предметною, а не «плюс-мінус», нам потрібен контекст задачі. Розкажіть, що вже є і до якого результату йдете, — далі ми поставимо уточнювальні запитання і повернемося з планом робіт і термінами за етапами.
Що допомагає нам швидко й точно оцінити проєкт:
- Мета та сценарій використання. Яку задачу вирішує модель на пристрої: розпізнавання, класифікація, детекція, обробка сигналу — і що вважається успішним результатом для користувача.
- Дані. Що є зараз: обсяг, розмітка, формати, джерела. Якщо даних мало або вони нерозмічені — це окремий етап, який закладаємо в план заздалегідь.
- Поточний код і стек. Чи є прототип на PyTorch, у якому стані пайплайн навчання, що вже переносилося на пристрій.
- Цільові платформи. iOS, Android чи обидві; які обмеження за розміром застосунку, часом відгуку та автономністю критичні.
- Інфраструктура. Де навчаєте і зберігаєте моделі, як зараз випускаєте оновлення, чи є вимоги до приватності даних на пристрої.
- Терміни та пріоритети. Що важливіше — швидкий пілот на одному сценарії чи одразу продуктова інтеграція в застосунок.
За цими ввідними ми оцінюємо обсяг робіт, ризики щодо якості моделі та щодо продуктивності на пристрої, а також реалістичний графік.
Повертаємося з розбивкою за етапами: підготовка даних, навчання і валідація, конвертація та оптимізація під мобільні платформи, інтеграція в застосунок, заміри на реальних пристроях.
Опишіть задачу у вільній формі — навіть якщо частина даних поки відсутня. Ми уточнимо те, чого бракує, і запропонуємо план, від якого можна відштовхуватися.







