Хабрахабр

GPU, гексагональные ускорители и линейная алгебра

Все эти слова гораздо сильнее связана с мобильной разработкой, чем кажется на первый взгляд: гексагональные ускорители уже помогают обучать нейронные сети на мобильных устройствах; алгебра и матан пригодится, чтобы устроиться работать в Apple; а GPU-программирование не только позволяет ускорять приложения, но и учит видеть суть вещей.

А еще о том, как идеи перетекают в мобильную разработку из GameDev, чем отличаются парадигмы, почему в Android нет нативного размытия — да много еще чего, продуктивный вышел выпуск AppsCast. Во всяком случае, так говорит руководитель мобильной разработки Prisma Андрей Володин. Под катом поговорим про доклад Андрея на AppsConf без спойлеров.

Каждый выпуск – новый гость.
AppsCast — подкаст, посвященный конференции для мобильных разработчиков AppsConf. Ведут подкаст члены программного комитета AppsConf Алексей Кудрявцев и Даниил Попов. Каждый гость – спикер конференции, с которым мы обсуждаем его доклад и говорим на связанные с ним темы.

Андрей, расскажи, пожалуйста, о своем опыте. Алексей Кудрявцев: Всем привет!

Наше флагманское приложение — Prisma. Андрей Володин: Мы в Prisma разрабатываем продукты, которые в основном, связаны с обработкой фото и видео. Сейчас мы делаем еще одно приложение Lensa для Facetune-подобного функционала.

На мне вся core-часть, пишу GPU пайплайны для всех этих приложений. Я руковожу мобильной разработкой, но я играющий тренер. Короче, чтобы убивать серверные вычисления и всё такое. Разрабатываю core-фреймворки, чтобы алгоритмы и нейронки, которые, разработала R&D-команда, запускались на мобильных устройствах, работали в realtime.

Алексей Кудрявцев: Звучит не как обычная iOS-разработка.

Андрей Володин: Да, у меня такая специфика — я каждый день пишу на Swift, но при этом очень далек от того, что принято считать iOS-разработкой.

Даниил Попов: Ты упомянул GPU пайплайны, это вообще о чем?

Например, в Lensa есть инструмент боке, который размывает фон с помощью нейронки, есть инструмент для ретуши, который делает человека красивее. Андрей Володин: Когда делаешь фоторедакторы, тоже нужно настроить архитектуру и декомпозировать логику, потому что в приложении есть разные инструменты. Причем желательно не передавать данные между процессором и видеокартой каждый раз, а заранее выстраивать набор операций, выполнять их за один прогон, и показывать пользователю итоговый результат. Нужно, чтобы все это работало эффективнее на GPU.

Потом она все это делает очень быстро и эффективно, а ты забираешь результат за один раз, а не после каждого инструмента. GPU пайплайны — это «маленькие комочки», из которых собираются инструкции для видеокарты. Я занимаюсь тем, чтобы наши GPU пайплайны были максимально быстрыми, эффективными и вообще в принципе существовали.

Обычный iOS-разработчик начинает с клепания и формочек, потом ходит куда-то по API и счастлив. Алексей Кудрявцев: Расскажи, как ты к этому пришел? Как так получилось, что занимаешься совсем другим?

До того, как у меня появилась работа, я делал игры под iOS. Андрей Володин: По большей части это стечение обстоятельств. Так получилось, что мы нашли друг друга с компанией Prisma. Мне это всегда было интересно, но я понимал, что в России особо негде развиваться в этом направлении. Им нужен был iOS-разработчик, который умеет писать на Swift и при этом знает GPU, в частности, Metal, который тогда только вышел, а я точно подходил под это описание.

Если сейчас что-то пойдет не так, то мне уже во всех этих Viper и MVVM — я даже не знаю, как это расшифровывается — придется разбираться с самого начала. Откликнулся на вакансию, у нас случилась синергия, и вот уже третий год я все дальше и дальше углубляюсь в эту штуку.

Чем занимается GPU Engineer

Даниил Попов: В твоем профиле на AppsConf написано GPU Engineer. Чем GPU Engineer занимается большую часть рабочего дня, кроме распития кофе?

Процессор выполняет операции как бы последовательно. Андрей Володин: Тут надо упомянуть, чем принципиально отличается процессор от GPU. GPU работает ровно противоположным образом. Даже многопоточность, которая у нас есть, часто фейковая: процессор останавливается и переключается, чтобы сделать маленькие кусочки разных задач, и выполняет их по чуть-чуть слайсами. Есть n процессоров, которые по-настоящему работают параллельно, причем есть параллельность и между процессами, и параллельность внутри GPU.

Это не всегда тривиальная задача, потому что бывают очень эффективные алгоритмы, полностью завязанные на последовательное выполнение инструкций. Моя основная работа, кроме банальных вещей типа оптимизации работы с памятью и организации переиспользования кода, в том, что я портирую алгоритмы, которые написаны для CPU на видеокарты так, чтобы они параллелились. Так мы можем получить ускорение в 100 раз, чуть-чуть пожертвовав качеством. Моя работа — придумать, например, аппроксимацию для такого алгоритма, которая делает, может быть, не то же самое в точности, но визуально результат не отличишь.

Кстати, мы скоро сделаем крупный Open Source релиз. Еще я занимаюсь портированием нейронок. Его парадигма немного отличается от Core ML. Еще до того, как появился Core ML, у нас был свой аналог, и мы наконец созрели, чтобы выложить его в Open Source. Я, в том числе, разрабатываю его core-часть.

В общем, я делаю все вокруг Computer Vision алгоритмов и вычислений.

Алексей Кудрявцев: Интересный анонс.

Андрей Володин: Это не секрет, мы не будем анонсировать его с какой-то помпой, просто можно будет посмотреть пример фреймворков, которые используются внутри Prisma.

Зачем оптимизировать под GPU

Алексей Кудрявцев: Расскажи, пожалуйста, зачем вообще алгоритмы оптимизировать под GPU. Может показаться, что достаточно добавить ядер в процессор или алгоритм оптимизировать. Почему именно GPU?

Например, у нас есть нейронки, которые на центральном процессоре Samsung S10 будут выполняться 30 с, а на GPU  будет 1 кадр, то есть 1/60 с. Андрей Володин: Работа на GPU может колоссально ускорить алгоритмы. Нет вечного экрана загрузки, можно видеть результат работы алгоритма на видеопотоке, или крутить слайдер и тут же видеть эффекты. Это невероятно меняет пользовательский опыт.

У использования GPU есть прозрачная цель — ускорить работу. Дело вовсе не в том, что мы слишком клевые, чтобы писать на CPU, поэтому перепишем все на GPU.

Алексей Кудрявцев: GPU хорошо параллельно обрабатывает операции подобные друг другу. У вас как раз такие операции и поэтому удается добиться таких успехов?

Это не всегда тривиально. Андрей Володин: Да, главная сложность не в том, чтобы закодить, а в том, чтобы создать такие алгоритмы, которые хорошо перекладываются на GPU. Например, пишешь все в одно property, а это явный признак, что это будет плохо параллелитmся. Бывает, ты придумал, как все клево сделать, но для этого нужно слишком много точек синхронизации. Наша задача — аппроксимировать алгоритмы так, чтобы они хорошо параллелились. Если много писать в одно место, то всем потокам нужно будет для этого синхронизироваться.

Алексей Кудрявцев: Для меня, как для мобильного разработчика, это звучит, как rocket science.

Для меня rocket science — это VIPER. Андрей Володин: На самом деле, это не так сложно.

Третий чип

Даниил Попов: Кажется, на прошлой конференции Google I/O анонсировали железяку под TensorFlow и прочие штуки. Когда уже наконец в мобилках появится третий чип, TPU или как его назовут, который тоже будет делать всю ML-магию на устройстве?

Это уже есть у Huawei, мы даже писали софт для их гексагональных ускорителей, чтобы на P20 быстро гонялись сегментационные нейронки. Андрей Володин: У нас есть эта самая штука, она подключается по USB, и на ней можно гонять нейронки от Google.

Например, в последнем iPhone XS есть сопроцессор, которые называется NPU (Neural Processing Unit), но пока что к нему есть доступ только у Apple. Надо сказать, что в iPhone они на самом деле уже есть. Некоторые модели Core ML используют NPU и за счет этого работают быстрее, чем голый Metal. Этот сопроцессор уже сейчас разделывает GPU в iPhone.

Сначала нужно сконвертировать входные данные в формат Core ML, он их обработает, потом вернет в своем формате — нужно конвертировать обратно, и только потом показывать пользователю. Это существенно, учитывая, что помимо самой low inference нейронки, Core ML требует много дополнительных действий. Мы пишем overhead free пайплайны, которые от начала и до конца работают на GPU, при этом Core ML модели бывают быстрее именно за счет этого хардварного процесса. Это все занимает довольно много времени.

Скорее всего, на WWDC в июне покажут фреймворк для работы с NPU.

То есть, как ты сказал, устройства уже есть, просто разработчики пока не могут их использовать по полной. Моя гипотеза, что компании пока сами не понимают, как сделать это аккуратно в виде фреймворка. Или просто пока не хотят отдавать, чтобы иметь рыночное преимущество.

Алексей Кудрявцев: Со сканером отпечатков пальцев такая же штука была в IPhone, насколько я помню.

Можно использовать его верхнеуровнево, но нельзя получить сам отпечаток. Андрей Володин: Он и сейчас не то, чтобы супер-доступный. Это все равно не то, что полный доступ к самому сканеру. Можно просто попросить Apple разрешить пользователю им воспользоваться.

Гексагональные ускорители

Даниил Попов: Ты упомянул термин гексагональные ускорители. Думаю, не все знают, что это.

Надо сказать, она довольно мудреная. Андрей Володин: Это просто особенность архитектуры железяк, которые использует Huawei. Huawei их выпустили, а потом нашли проблему, теперь в некоторых телефонах мертвым грузом лежат специальные чипы. Мало кто знает, но в некоторых Huawei эти процессоры есть, но не используются, потому что в них есть хардварный баг. В свежих версиях уже все работает.

Чип устроен так, что умеет обрабатывать какую-то операцию параллельно сразу на нескольких потоках данных. В программировании есть парадигма SIMD (Single Instruction, Multiple Data), когда одни и те же инструкции выполняются параллельно на разных данных. В частности, гексагональный значит, что на 6 элементах параллельно.

В чем отличие? Алексей Кудрявцев: Я думал, что GPU как раз так и работает: векторизует задачу и на разных данных выполняет одну и ту же операцию.

Несмотря на то, что программирование для GPU довольно низкоуровневое, относительно работы с сопроцессорами оно довольно высокоуровневое. Андрей Володин : GPU более general purpose. На iOS код все равно потом компилируется с помощью LLVM в машинные инструкции. Для программирования на GPU используется С-подобный язык. Поэтому там увеличение производительности гораздо заметнее, потому что они заточены для конкретных операций. А эти штуки для сопроцессоров чаще всего пишутся прямо хардкорно — на ассемблере, на машинных инструкциях. На них нельзя посчитать вообще все что угодно, а можно посчитать только то, для чего они изначально предназначены.

Алексей Кудрявцев: А для чего они обычно разработаны?

В них есть заранее зашитая функциональность, которая супер-быстро работает. Андрей Володин: Сейчас в основном для самых распространенных операций в нейронных сетях: convolution — свертка или какие-то промежуточные активации. Так они гораздо быстрее на некоторых задачах, чем GPU, но во всех остальных просто не применимы.

Продавались специальные дорогие железяки, но потом процессоры подросли, и теперь мы записываем и обрабатываем подкасты прямо на ноутбуках. Алексей Кудрявцев: Похоже на DSP-процессоры, которые в свое время использовались для аудио, и на них все плагины и эффекты очень быстро работали.

Андрей Володин: Да, примерно то же самое.

GPU не только для графики

Даниил Попов: Я правильно понимаю, что сейчас на GPU можно обрабатывать данные, которые не связаны с графикой напрямую? Получается, что GPU теряет свое изначальное предназначение.

Я об этом довольно часто рассказываю на конференциях. Андрей Володин: Именно так. Это технология, которая делает проще GPGPU (General-purpose computing on graphics processing units). Первыми стали NVidia, которые представили CUDA. На ней можно писать на надмножестве С++ алгоритмы, которые параллелизуются на GPU.

Например, умельцы на OpenGL или на еще более старых DirectX просто записывали в текстуру данные — каждый пиксель интерпретировали как данные: в первый пиксель первые 4 байта, во второй — вторые 4 байта. Но люди делали это и раньше. Это было очень костыльно и сложно. Обрабатывали текстуры, потом обратно данные из текстуры извлекали и интерпретировали. Можно скормить в GPU любой буфер, описать свои структуры, даже иерархию структур, в которой они будут ссылаться друг на друга, что-то посчитать и вернуть на процессор. Сейчас видеокарты поддерживают general purpose логику.

Даниил Попов: То есть можно сказать, что GPU теперь Data PU.

Андрей Володин: Да графики на GPU порой обрабатывается меньше, чем общих вычислений.

Алексей Кудрявцев: Архитектура CPU и GPU разная по сути, а считать можно и там, и там.

Нельзя сказать, что GPU всегда быстрее. Андрей Володин : Действительно, в чем-то CPU бывает быстрее, в чем-то GPU.

Даниил Попов: Насколько я помню, если задача посчитать что-то очень разное, то на CPU это может быть гораздо быстрее.

Всегда есть накладные расходы на передачу данных с CPU на GPU и обратно. Андрей Володин: Зависит еще и от объема данных. Но посчитать тысячу элементов на CPU может быть быстрее, чем просто скопировать их на видеокарту. Если считаешь, например, миллион элементов, то использовать GPU обычно оправдано. Поэтому всегда надо выбирать под задачу.

Core ML умеет в runtime, по заверениям Apple, выбирать, где быстрее посчитать: на процессоре или на видеокарте. Кстати, Core ML делает это. Не знаю, работает ли это в реальности, но они заявляют, что да.

Хардкорные знания GPU Engineer для мобильного разработчика

Алексей Кудрявцев: Давайте вернемся к мобильной разработке. Ты GPU Engineer, у тебя куча хардкорных знаний. Как эти знания можно применить мобильному разработчику? Например, что ты видишь в UIKit, чего не видят другие?

Применить можно много где. Андрей Володин: Подробно об этом я буду рассказывать на AppsConf. Наблюдая падение производительности при рендеринге каких-то вьюшек я могу понять причину, потому что знаю, как внутри написан рендеринг. Когда я вижу, например, как устроен API UIKit, я могу сразу понять, зачем и почему это сделано. Все это надо уместить в 1/60 секунды, иначе будет тормозить. Я понимаю: чтобы отобразить эффекты, которые на самом деле делает Гауссово размытие поверх фрейм-буфера, нужно сначала закэшировать всю текстуру, применить к ней тяжелую операцию размытия, вернуть результат, закончить рендеринг остальных вьюх, и только потом показать на экран.

Именно поэтому я хочу поделиться дизайн-приемами, которые мы часто используем в GameDev, и своими инсайтами о том, как я смотрю на проблемы и пытаюсь их решить. Для меня абсолютно очевидно, почему это долго, но для моих коллег это бывает непонятно. Это будет эксперимент, но думаю, что должно быть интересно.

Почему в Android нет нативного размытия

Даниил Попов: Ты упомянул размытие, и у меня возник вопрос, который волнует, думаю, всех Android-разработчиков: почему в iOS есть нативный блюр, а в Android его нет.

На платформах Apple используется Tiled Shading архитектура рендеринга. Андрей Володин: Думаю, что это из-за архитектуры. Это позволяет оптимизировать работу алгоритма, потому что основной прирост производительности при использовании GPU дает эффективное использование кэша. При этом подходе рендерится не весь кадр, а маленькие тайлы — квадратики, части экрана. Например, на iPhone 7 Plus разрешение 1920*1080, это примерно 2 млн пикселей. На iOS фрейм часто рендерится так, что вообще не занимает память. 20 Мб на то, чтобы просто хранить фрейм-буфер системы. Умножаем на 4 байта на канал, получается в районе 20 Мегабайт на кадр.

Так очень сильно возрастает число обращений к кэшу, потому что, чтобы сделать размытие, нужно прочитать уже нарисованные пиксели и на них посчитать Гауссовское распределение. Подход Tiled Shading позволяет разбивать этот буфер на маленькие кусочки и рендерить его по чуть-чуть. Но если читать маленькие кусочки, то кэш-рейт будет очень высокий, и производительность тоже будет высокая. Если читать по всему кадру, то кэш-рейт будет очень низкий, потому что каждый поток будет читать разные места.

Хотя, может быть, это и продуктовое решение. Мне кажется, отсутствие нативного размытия в Android связано именно с особенностями архитектуры.

Это сильно сложнее, чем в iOS один флажок поставить. Даниил Попов: В Android для этого есть RenderScript, но там нужно руками смешивать, отрисовывать, подкладывать.

Андрей Володин: Скорее всего, еще и производительность ниже.

Даниил Попов: Да, чтобы удовлетворить дизайнерские хотелки, нам приходится даунскейлить картинку, блюрить ее, а потом апскейлить обратно, чтобы хоть как-то сэкономить.

Гауссовское распределение — это размыленный кружок. Андрей Володин: Кстати, с помощью этого можно делать разные трюки. Часто в качестве оптимизации можно даунскейлить картинку и немножко сузить сигму, и когда ты вернешь изначальный масштаб, разницы не будет, потому что сигма напрямую зависит от размера картинки. Сигма Гаусса зависит от количества пикселей, которое ты хочешь им собрать. Этот трюк мы часто используем внутри, чтобы ускорять размытие.

Даниил Попов: Тем не менее, RenderScript в Android не позволяет сделать радиус больше 30.

Опять же я понимаю, что 30 пикселей собрать с помощью GPU на каждом потоке очень дорого. Андрей Володин: На самом деле, радиус 30 — это очень много.

Чем похожи мобильная разработка и GameDev

Алексей Кудрявцев: В тезисах к своему докладу ты говоришь, что у мобильной разработки и у GameDev много общего. Расскажи немного, чего именно?

Современные пошли в сторону Entity Component System, об этом тоже будет в докладе. Андрей Володин: Архитектура UIKit очень напоминает игровые движки, причем старые. Но это придумали в GameDev, впервые Component System использовался в игре Thief в 98 году. В UIKit это тоже приходит, появляются статьи, в которых пишут, как можно проектировать вьюхи на компонентах.

И там, и там используется Scene graph — дерево сцены, когда у каждой ноды есть под-ноды, их рендер происходит с помощью аккумулирования аффинных преобразований, которые конкретно на iOS называются CGAffineTransform. Фундаментально, например, Cocos2d, над которым я долгое время работал, и идеи, которые использовали в первой реализации, очень похожи. Анимация везде сделана примерно одинаково. Это просто матрицы 4*4, которые перемножаются, чтобы изменить систему координат.

Просто мы интерполируем какие-то значения — будь то цвета или позиции между кадрами. И в игровых движках, и в UIKit все построено на интерполяции по времени. Оптимизации все такие же: в GameDev принято не делать лишней работы, так и UIKit используется setNeedsLayout, layoutIfNeeded.

Об этом и расскажу на AppsConf. Эти параллели я провожу для себя постоянно — между тем, что я когда-то делал, и между тем, что я вижу во фреймворке Apple.

Как думаешь, вдохновлялись разработчики работой друг друга или просто архитектурно получилось? Даниил Попов: Действительно, API Cocos2d похож на iOS (для UI).

Cocos2d появился в 2008-2009 годах, тогда UIKit не был тем UIKit, который мы знаем сейчас. Андрей Володин: Думаю, что чем-то вдохновлялись. Мне так кажется, что какие-то приемы там специально повторялись, чтобы людям было комфортнее работать, чтобы они могли проводить параллели.

SpriteKit по сути полная копия всех идей, которые появились в Cocos2d. Забавно, что качельки качнулись: изначально core-команда Cocos2d немного позаимствовала идеи Apple, а потом Apple полностью скопировал Cocos2d, вплоть до всех архитектурных решений. В этом смысле Apple забрал свой должок.

Там те же setNeedsLayout, layoutIfNeeded есть, аффинные преобразования. Алексей Кудрявцев: Мне кажется, те же приемы, что в UIKit в 2009, были еще на MacOS, который существует с древних времен.

Андрей Володин: Безусловно, но GameDev существует еще дольше, чем MacOS.

Алексей Кудрявцев: Не поспоришь!

Именно в GameDev люди впервые поняли, что наследование — это плохо. Андрей Володин: Поэтому я не сравниваю Cocos2d с фреймворками Apple, а скорее рассматриваю в принципе парадигмы, которые зародились в GameDev. Мобильная разработка, как индустрия, дошла до этого только сейчас. Когда весь мир восторгался ООП, в GameDev уже начали задумываться, что наследование приносит проблемы, и придумали компоненты.

Алексей Кудрявцев: Кажется, еще Алан Кэй давным-давно понял, что наследование — это плохо.

А сейчас есть Protocol-Oriented Programming в Swift, функциональщина, и всё придумывают что-то новое. Андрей Володин : Да, но в целом, согласитесь, что еще несколько лет назад все говорили, что ООП — это круто. В GameDev эти настроения появились уже довольно давно.

Он сказал, что не придумывал наследование, а только посылку сообщений, и вообще его поняли неправильно. Алексей Кудрявцев: Сделаю ремарку: Алан Кэй тот самый человек, который придумал ООП.

Отличия мобильной разработки и GameDev

Алексей Кудрявцев: Расскажи теперь про отличия: чем GameDev и мобильная разработка кардинально отличаются, и что из GameDev нам никак не применить?

Мы пытаемся писать код по принципу «пока не попросят, не встану». Андрей Володин: Мне кажется, фундаментальное отличие в том, что продуктовая разработка максимально ленивая. Даже рендеринг в продуктовой разработке ленивый: перерисовывается не весь кадр, а только те части, которые изменились. Пока коллбэк не сработает, мы ничего не будем делать.

Для каждого кадра делается всё: 30 или 60 раз в секунду перерисовывается вся сцена с нуля, каждый кадр, каждый объект обновляется, каждый кадр симулируется физика. GameDev-разработка в этом смысле беспощадна. Начинаешь жить внутри одного фрейма — у меня этому посвящена целая часть доклада. Происходит куча всего, и это очень сильно меняет парадигму. Поэтому начинаешь исхитряться, делать максимальное количество предварительных вычислений, параллелизации, пока GPU рендерит кадр, готовить на CPU следующий. Нужно все-все-все уместить в 1/60 или 1/30 секунды. Именно поэтому батарейка от игр разряжается гораздо быстрее, чем от обычных приложений.

Алексей Кудрявцев: А почему в играх нельзя все тоже сделать лениво?

Какие-то игры определенно могли бы выиграть от этого, например, Тетрис, в котором мало динамики и меняются только некоторые части. Андрей Володин: Концепция игр плохо позволяет. Даже когда персонаж просто стоит, он, например, покачивается — происходят какие-то анимации, есть какая-то логика, просчитывается физика. Но в целом игра — очень комплексная вещь. От экономии может получиться больше вреда, потому что каждый кадр настолько меняется, что переиспользовать фрагменты становится практически невозможно.

Например, GPU лучше работает с типом float, а не с double, из-за этого гораздо ниже точность. К тому же есть хардварные ограничения. На CPU точность высокая, потому что там все рендерится в двойной точности, можно использовать красивые шрифты и аккуратные кривые, но на GPU все равно будет некоторая аппроксимация. Поэтому, например, если перерисовывать только часть экрана, могут возникнуть заметные артефакты.

Совокупность этих факторов приводит к тому, что каждый кадр требует тяжелых вычислений, обновления всех объектов — фактически отрисовки с чистого листа.

Классическая разработка гораздо ближе к GameDev, чем вы думаете

Даниил Попов: Хочу обсудить провокационное утверждение из твоего будущего доклада, что «классическая разработка гораздо ближе к GameDev, чем вы думаете». Мне сразу вспомнилась серия статей о костылях в играх, которые были призваны ускорить разработку, когда поджимали сроки. По этим статьям создается впечатление, что GameDev — это костыль на костыле ради оптимизаций. В обычной разработке сейчас все помешаны на архитектуре, красивом коде. Не могу соотнести это с GameDev.

Но конкретно этот тезис про другое. Андрей Володин: Конечно, enterprise-компании так не делают, но в инди GameDev так примерно и есть. Я часто замечаю, что разработчики пользуются многими концепциями, которые используются в GameDev, но даже не понимают этого.

Немногие могут четко сказать, что это просто перемножение матриц 4*4. Например, аффинные преобразования. Чаще CGAffineTransform — это непрозрачная структура данных, в которой что-то хранится и непонятно каким образом приводит к тому, что вьюшка скейлится.

В докладе я попробую показать другую сторону того, чем мы пользуемся каждый день, но при этом, может быть, не до конца понимаем.

О пользе математики

Алексей Кудрявцев: Как мобильному разработчику прийти к этому пониманию? Как разобраться, что под капотом у рендеринга в UIKit, как устроены внутри аффинные преобразования, и не пугаться лишний раз? Я понимаю, что это матрица, но какая конкретно цифра за что отвечает, не могу сказать. Где почерпнуть информацию, чтобы не бояться и понимать?

Андрей Володин: Самый очевидный совет — начать делать pet project.

iOS GPU программирование принципиально не отличается от того, что есть в десктопной среде. Главное, что по этому поводу стоит сказать: все концепции мобильной GPU разработки абсолютно похожи на те, что есть и на десктопе. Идеологически они прямо одинаковые. Поэтому если для iOS наблюдается недостаток материала по теме, то всегда можно почитать что-то для NVidia или AMD-решений и вдохновиться ими. API немножко отличается, но обычно понятно, как переложить существующие практики с десктопного программирования на мобильное.

Как именно начать понимать, и куда лучше посмотреть, что лучше почитать, чтобы на UIKit это можно было переложить? Алексей Кудрявцев: Когда используешь API, например, игровой движок Cocos2d или Unity, все рано ничего не понимаешь — просто дергаешь какие-то методы.

Я не очень объективен, потому что приложил к этому руку, но мне кажется, что там довольно хороший код, который можно почитать и вдохновиться. Андрей Володин: Cocos2d — Open Source проект и неплохо написан. Он написан на не очень современном objective-C, но ко многим сложным местам есть подробные комментарии.

Знаете, есть популярные API, которые делают VHS-эффект. Но когда я говорю о pet project, я говорю больше не о высокоуровневых проектах типа сделать игру, а о том, чтобы написать API, который делает, например, глитч-эффект. Это относительно простая задача, которую можно сделать за выходные. И не на процессоре, а на GPU. Когда я первый раз это делал, узнавал удивительные вещи: «Вот как работает контрастность и saturation в Instagram, или пресеты lightroom!» Оказывается, это просто шейдеры, которые перемножают 4 числа или возводят в степень — и все. Но это не так просто, если ни разу этого не пробовал.

Прямо срывает башню от того, насколько это просто.

Пользуешься этим каждый день и воспринимаешь как данность — работает, но не понимаешь, как. Потом начинаешь заниматься этим сам, и становится одновременно прикольно от того, что ты делаешь что-то якобы сложное, но и забавно, что в реальности это так просто, что даже смешно.

Например, в Cocos2d какие-то шейдеры — буквально 5 строчек кода, а ты сидишь и смотришь на них, как баран на ворота, и просто не понимаешь, что там написано. Даниил Попов: Все равно мне кажется, что нужен какой-то математический базис. Наверное, так просто в язык шейдеров не погрузиться, не зная математики, базовых концепций и т.д.

Без базовых знаний линейной алгебры будет тяжело, сначала придется разобраться. Андрей Володин: Про математику согласен. Но при этом, если у вас в университете был курс линейной алгебры, и вы хотя бы примерно представляете на уровне первого курса, что такое скалярное произведение и его геометрический смысл, что такое векторное произведение и его геометрический смысл, что такое собственный вектор, нормаль, матрица, как работает матричное умножение, то будет довольно просто разобраться.

Наверное, сейчас многие с трудом вспоминают, как работает перемножение матриц. Даниил Попов: Часто студенты компьютерных специальностей ноют, что им не нужна физика и математика.

Я был таким же, высокомерно ныл, зачем мне функциональный анализ и тому подобное. Андрей Володин: Для меня это больная тема. На собеседовании было такое огромное количество математики, что я потом благодарил себя за то, что ходил на пары. Но у меня есть ценный жизненный опыт, когда я проходил собеседование в Apple, в команду ARKit. Если бы не бэкграунд, который я получил в университете, то никогда бы не ответил на эти вопросы, и никогда бы не понял, как это работает.

В эпоху машинного обучения вам это точно пригодится». Сейчас, когда я сам преподаю в университете или приезжаю на день открытых дверей, всегда говорю: «Друзья, вы успеете насидеться в своих IDE, пожалуйста, ходите на линал, на матан и вообще разберитесь, что это такое.

Даниил Попов: Самое главное — собеседование прошел?

Андрей Володин: Да, конечно, и только благодаря тому, что у меня был математический бэкграунд.

Алексей Кудрявцев: Теперь вы знаете, зачем учить матан, и куда вы можете после этого устроиться.

Даже когда создаешь Project Template в Xcode, там уже все перемножается, есть векторные произведения, что-то транспонируется. Андрей Володин: Например, без понимания аффинных преобразований и знания, что такое нормаль, в VR далеко не уехать. Если не понимать концепции, то даже простые штуки сделать не получится.

Даниил Попов: На этой моральной ноте предлагаю потихонечку заканчивать.

Напутствие

Алексей Кудрявцев: Дай какое-нибудь напутствие тем, кто хочет ближе познакомиться с GameDev и GPU.

Это не что-то классическое, что точно пригодится на рынке труда, и просто людям, как личностям. Андрей Володин: Не всем это нужно. Здесь много места для челленджей. Но мне кажется, если вы немножко забрели в тупик и не знаете, куда продолжать саморазвитие, уже прошарили все, что можно, исследовали все возможные подходы в UI: модуляризацию, ускорение запуска, runtime Objective-C — в общем, во всем уже разобрались, то это хорошее новое поле. Хотя я каждый день это делаю, мне иногда приходится открывать учебники: посидишь, вспомнишь — ага, X на Y, понял!

Если хочется бросить вызов, напрячь мозг, сделать что-то новое, то GameDev и GPU-программирование — это для вас.

Если вы тоже мечтали в детстве делать компьютерные игры, самое время начать. Приходите послушать Андрея Володина на конференции для мобильных разработчиков AppsConf 22 и 23 апреля в Москве в Инфопространстве.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»