Русский
Русский
English
Статистика
Реклама

Wasm

Перевод Wasm или не Wasm?

16.07.2020 16:05:50 | Автор: admin
Мы, в компании Linkurious, занимаемся работой над Linkurious Enterprise. Это веб-платформа, которая, используя возможности графов и средства их визуализации, призвана помогать компаниям и органам власти, расположенным по всему миру, бороться с финансовыми преступлениями.

Одна из главных возможностей Linkurious Enterprise это простой в освоении и использовании интерфейс визуализации графов, рассчитанный на неспециалистов.



В 2015 году, разочарованные возможностями существующих JavaScript-библиотек для визуализации графов, мы приступили к разработке собственной библиотеки Ogma.

Ogma это JS-библиотека, отличающаяся высоким уровнем производительности в плане рендеринга и выполнения вычислений, которая нацелена на визуализацию сетевых структур. Возможно, вы видели, как сетевые структуры визуализируются с помощью других JavaScript-инструментов, вроде D3.js или Sigma.js. Нам возможностей этих инструментов не хватало. Нам было важно, чтобы используемое нами решение обладало бы некоторыми специфическими возможностями, чтобы оно соответствовало бы определённым требованиям к производительности. Ни того, ни другого в сторонних библиотеках мы не нашли. Поэтому мы и решили разработать собственную библиотеку с нуля.

Задача



Визуализация сетевой структуры

Библиотека Ogma проектировалась в расчёте на использование самых современных алгоритмов. Все её составные части, от передового движка рендеринга, основанного на WebGL, до используемых в её недрах веб-воркеров, были нацелены на то, чтобы обеспечить наилучшую среди существующих решений производительность в деле визуализации сетевых структур. Мы стремились сделать так, чтобы библиотека отличалась бы хорошей интерактивностью при выполнении длительных задач, и чтобы реализованные в ней ведущие алгоритмы визуализации графов работали бы быстро и стабильно.

Технология WebAssembly (Wasm), с момента первого сообщения о ней, обещала веб-разработчикам уровень производительности, выгодно отличающийся от того, который был им доступен ранее. При этом самим разработчикам не нужно было прилагать чрезмерные усилия для использования новой технологии. Им достаточно было просто писать код на некоем известном им высокопроизводительном языке, который, после компиляции, можно было бы запускать в браузере.

После того, как технология Wasm немного развилась, мы, прежде чем внедрять её, решили её испытать, и провести некоторые тесты производительности. В общем, прежде чем без оглядки прыгать в быстрый поезд Wasm, мы решили подстраховаться.

Нас в Wasm привлекало то, что эта технология вполне могла решить стоящие перед нами задачи, используя ресурсы памяти и процессора эффективнее, чем JavaScript.

Наше исследование


Наше исследование началось с поиска алгоритма, направленного на работу с графами, который легко было бы портировать на разные языки с использованием похожих структур данных.

Мы выбрали алгоритм n-body. Он часто используется в качестве базы для сравнения силовых алгоритмов визуализации графов. Выполняемые в соответствии с этим алгоритмом расчёты являются самой ресурсоёмкой частью систем визуализации. Если эту часть работы подобных систем удалось бы выполнить эффективнее, чем прежде, это весьма позитивно сказалось бы на всех силовых алгоритмах визуализации графов, реализованных в Ogma.

Бенчмарк


Есть ложь, грубая ложь и бенчмарки.

Макс Де Марзи

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

В нашем случае бенчмарк был нацелен на решение единственной, чётко определённой задачи, на исследование производительности реализации алгоритма n-body.

Это чёткий и хорошо описанный алгоритм, используемый уважаемыми организациями для измерения производительности языков программирования.

Как и при проведении любых честных испытаний, мы заранее определили некоторые правила, касающиеся различных исследуемых нами языков:

  • В различных реализациях алгоритма должны использоваться схожие структуры кода.
  • Запрещено использование нескольких процессов или нескольких потоков.
  • Запрещено использование SIMD.
  • Испытанию подвергаются только стабильные версии компиляторов. Запрещено использование релизов наподобие nightly, beta, alpha, pre-alpha.
  • Для каждого языка используются только самые свежие версии компиляторов.

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

Конкуренты JS


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


Алгоритм n-body был реализован на этих трёх языках. Производительность различных реализаций сравнивалась с производительностью базовой реализации на JavaScript.

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

Испытания выполнялись с использованием следующих программных и аппаратных средств:

  • NodeJS 12.9.1
  • Chrome 79.0.3945.130 (Официальная сборка) (64-bit)
  • clang 10.0.0 для версии алгоритма, реализованного на языке C
  • emcc 1.39.6 фронтенд для вызова компилятора Emscripten из командной строки, альтернатива gcc/clang, а так же линковщик
  • cargo 1.40.0
  • wasm-pack 0.8.1
  • AssemblyScript 0.9.0
  • MacOS 10.15.2
  • Macbook Pro 2017 Retina
  • Intel Dual Core i5 2,3 GHz, 8GB DDR3, 256GB SSD

Как видите, для тестов мы выбрали не самый быстрый компьютер, но тестируем мы Wasm, то есть код, который будет выполняться в контексте браузера. А браузер, всё равно, обычно не имеет доступа ко всем имеющимся в системе процессорным ядрам и ко всей оперативной памяти.

Чтобы было интереснее, мы создали несколько версий каждой реализации алгоритма. В одной точки в системе n-body имели 64-битное числовое представление координат, в другой 32-битное.

Ещё стоит отметить то, что мы использовали двойную реализацию алгоритма на Rust. Сначала, без использования каких-либо Wasm-инструментов, была написана исходная, небезопасная Rust-реализация. Позже, с использованием wasm-pack, была создана дополнительная, безопасная Rust-реализация. Ожидалось, что эту реализацию алгоритма будет легче интегрировать с JS, и то, что она сможет лучше управлять памятью в Wasm.

Тестирование


Мы проводили эксперименты в двух основных средах. Это Node.js и браузер (Chrome).

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

На основе исходного кода, написанного на AssemblyScript, было создано следующее:

  • Базовая JS-реализация алгоритма.
  • Wasm-модуль.
  • Asm.js-модуль.

Интересно отметить тот факт, что asm.js-модуль был не полностью совместим с asm.js. Мы попытались добавить в верхнюю часть модуля директиву use asm, но браузер не принял эту оптимизацию. Позже мы обнаружили, что использованный нами компилятор binaryen, на самом деле, и не стремился сделать код полностью совместимым с asm.js. Он, вместо этого, был ориентирован на формирование некоей эффективной JS-версии Wasm.

Сначала мы провели испытания в Node.js.


Запуск кода в среде Node.js

Потом измерили производительность того же кода в браузере.


Запуск кода в браузере

Мы сразу обратили внимание на то, что asm.js-вариант кода работает медленнее других вариантов. Но эти графики не позволяют достаточно чётко сравнить результаты различных вариантов кода с базовой JS-реализацией алгоритма. Поэтому мы, чтобы лучше во всём разобраться, построили ещё несколько диаграмм.


Отличия других реализаций алгоритма от JS-реализации (вариант бенчмарка с 64-битными координатами точек)


Отличия других реализаций алгоритма от JS-реализации (вариант бенчмарка с 32-битными координатами точек)

Варианты бенчмарка с 64-битными и 32-битными координатами точек заметно различаются. Это может привести нас к мысли о том, что в JS числа могут быть и такими, и такими. Дело в том, что числа в JS, в реализации алгоритма, принятой за базу сравнения, всегда являются 64-битными, а вот компиляторы, преобразующие код с других языков в Wasm, работают с такими числами по-разному.

В частности, огромнейшее влияние это оказывает на asm.js-вариант теста. Его вариант с 32-битными координатами точек очень сильно уступает в производительности как базовой JS-реализации, так и asm.js-варианту, в котором используются 64-битные числа.

На предыдущих диаграммах сложно понять то, как производительность других вариантов кода соотносится с JS-вариантом. Всё дело в том, что показатели AssemblyScript слишком сильно отличаются от остальных. Для того чтобы в этом разобраться, мы построили другие диаграмму, убрав результаты asm.js.


Отличия других реализаций алгоритма от JS-реализации (вариант бенчмарка с 64-битными координатами точек, без asm.js)


Отличия других реализаций алгоритма от JS-реализации (вариант бенчмарка с 32-битными координатами точек, без asm.js)

Разные представления чисел, похоже, повлияли и на другие варианты теста. Но повлияли по-разному. Так, C-вариант, в котором использовались 32-битные числа (float), стал медленнее, чем C-вариант, в котором применялись 64-битные числа (double). А оба Rust-варианта теста с 32-битными числами (f32) стали быстрее их разновидности с 64-битными числами (f64).

Некачественные реализации алгоритма?


Анализ вышеприведённых данных может навести на следующую мысль. Так как все протестированные Wasm-сборки весьма близки по производительности к JavaScript-реализации, возможно ли, что Wasm-реализации лишь отражают особенности производительности нативных реализаций алгоритма?


Сравнение нативных реализаций алгоритма с JavaScript-реализацией

Нативные версии реализаций алгоритма всегда быстрее JavaScript-реализации.

Мы, кроме того, заметили, что Wasm-сборки работают медленнее, чем нативные варианты кода, используемого для создания таких сборок. Разница в производительности составляет 20-50%. Мы выяснили это на сокращённом варианте бенчмарка с 1000 итераций.


C-реализация и соответствующая Wasm-сборка


Rust-реализация и соответствующая Wasm-сборка


Rust-реализация, при создании которой использовался wasm-pack, и соответствующая Wasm-сборка

При измерении времени выполнения нативного кода в расчёт бралось и время, необходимое на загрузку программы, а в случае с Wasm-вариантами это время не учитывалось.

Итоги


В среднем, прирост производительности двух Rust-реализаций алгоритма, в сравнении с его базовой JS-реализацией, составил 20%. Это, вероятно, хорошо для имиджа Rust, но это слишком маленький прирост производительности в сравнении с затраченными на его получение усилиями.

Какие выводы мы можем сделать из этих испытаний? А вот какие: вдумчивое написание JS-кода позволяет получать достаточно высокую производительность и не требует перехода на другие языки программирования.

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

В порядке эксперимента, для написания реализации силового алгоритма визуализации графа, мы поменяли JavaScript на TypeScript. В результате мы улучшили качество кодовой базы, но не производительность. Мы специально замеряли производительность, и оказалась, что она, после перехода, незначительно, на 5%, выросла. Вероятно, причина тут в рефакторинге кода.

Если вам близки вопросы JavaScript-разработки и производительности, то вам, возможно, будет интересно посмотреть это выступление, в котором озвучены результаты, сходные с теми, которые получили мы.

Как вы подходите к разработке тяжёлых частей веб-проектов?

Подробнее..

Перевод Что не так с WebAssembly?

29.01.2021 18:07:40 | Автор: admin
Современные браузеры могут намного больше, чем рендеринг веб-страниц. Это стало одной из причин появления WebAssembly. Эта технология создана в попытке вывести скорость решения сложных задач на новый уровень, построить мост между JavaScript и машинным кодом.

WebAssembly, в теории, может позволить кому угодно писать низкоуровневый код, выполняющийся в браузере, в безопасном виртуальном окружении. И, что ещё интереснее, технология WASM (сокращение от WebAssembly) была спроектирована как цель компиляции для других языков, позволяя коду, который обычно выполняют в серверной среде (например коду, написанному на C или на C++), компилироваться в соответствующий формат и выполняться в браузере.



У WASM был огромный потенциал и невероятные перспективы. Что же пошло не так? Почему WASM, через 3 года после релиза, ещё не используется в каждом веб-проекте? Есть ли у WASM будущее в веб-разработке? Поищем ответы на эти вопросы.

В чём заключается цель создания WASM?


Технологию WASM создавали с прицелом на выполнение высокооптимизированных вычислений в веб-среде, а так же в расчёте на то, что WASM ликвидирует монопольное положение JavaScript в сфере браузерных вычислений.

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

Какая от этого может быть польза?

Хотя JavaScript это замечательный язык, его разрабатывали, не обращая особого внимания на производительность. И если в веб-среде можно было бы, вместе с JavaScript, применять другие языки, рассчитанные на высокопроизводительные вычисления, это позволило бы пользоваться в браузере всем тем полезным, что есть в JavaScript и в этих языках. Но как это сделать? С помощью некоей промежуточной технологии, некоего моста, которым и стала технология WASM.

Какими же создатели WASM видели способы использования этой технологии?


Технология WASM не создавалась как нечто, позволяющее оптимизировать веб-сайты. Она была рассчитана на то, чтобы перевести браузеры (и серверные среды вроде Node.js) на новый уровень производительности при решении некоторых задач. Например таких:

  • Редактирование видео.
  • Разработка игр.
  • Создание приложений виртуальной реальности.
  • Редактирование и потоковая передача музыки.
  • Эмуляция различных платформ.
  • Шифрование.
  • VPN.
  • Распознавание изображений

В целом технология WASM ориентирована на всё, что требует написания больших объёмов кода и высокой производительности.

Кто и для чего реально использует WASM?


Здесь можно найти опенсорсный список проектов, в которых используется WASM.

Но если вам не хочется открывать ещё одну вкладку браузера вот некоторые наиболее известные проекты из этого списка:

  • TensorFlow.js. Не знали, что WASM используется в TensorFlow.js? Но, на самом деле, так оно и есть. TensorFlow, одна из основных библиотек, давшая JS-разработчикам возможность пользоваться технологиями искусственного интеллекта и машинного обучения, уже давно обзавелась поддержкой WASM-бэкенда. Работа над WASM-реализацией всё новых и новых моделей с тех пор не прекращается. Какая от этого выгода? Разработчики библиотеки заявляют о том, что производительность моделей благодаря WASM выросла, в сравнении с их JS-реализацией, в среднем, в 10 раз.
  • Unity. Это ещё один известнейший проект. Один из ведущих движков для разработки игр может экспортировать проекты в виде, подходящем для веба. С 2018 года это делается путём компиляции кода в формат WebAssembly. Это отличный пример того, какую мощь даёт технология WASM тем, кто правильно её применяет. Разработчикам игр не нужно заботиться о создании веб-проектов, или даже о написании JavaScript-кода. Их основная задача писать код игр, а всё остальное задача компилятора.
  • Веб-приложение AutoCAD. И здесь используется именно WASM. Правда, веб-приложение Autodesk было переведено на новую технологию лишь частично старая кодовая база, написанная на C++, была скомпилирована в формат WASM. Это важный шаг, демонстрирующий возможности WASM в деле повторного использования кода, написанного для платформы, ничего общего не имеющей с вебом, на языке, совершенно не совместимом с браузерами. Теперь этот код спокойно работает в браузерной среде.
  • Google Earth. Вы, возможно, по крайней мере слышали об использовании WASM в этом проекте. Он существует уже более 15 лет, раньше этот проект был представлен настольным приложением. А теперь, благодаря WASM, часть старого кода была перенесена в веб-среду (это очень похоже на то, что было сделано компанией Autodesk). Это ещё один отличный пример того, чего можно достичь, пользуясь этой технологией.
  • Blazor. Это среда, использующая возможности ASP.NET для создания интерактивных интерфейсов, работающих в браузере. Благодаря невероятным возможностям WASM .NET-код исполняется прямо в браузере. В результате в руках разработчиков, привыкших писать серверный C#-код, оказывается инструмент для описания веб-интерфейсов.
  • Yew. Думали ли вы когда-нибудь о том, чтобы использовать в своих веб-приложениях Rust? Теперь это, благодаря проекту Yew, совершенно реально. При этом Rust можно применять не только для создания интерфейсов. Yew даёт в распоряжение разработчика среду, поддерживающую многопоточность. Этот проект, правда, пока не готов к продакшн-использованию, но если вы любитель Rust и хотите пользоваться Yew, но нуждаетесь в помощи, вы всегда можете обратиться за советом к дружелюбной команде этого проекта.

В вышеупомянутом списке более 100 проектов. То, что за некоторыми из них стоят Microsoft, Unity и Google, недвусмысленно указывает на потенциал WebAssembly.

Почему технология WASM не получила достаточно серьёзного распространения?


После чтения вышеприведённого списка проектов, в которых используется WebAssembly, вполне уместно задаться парой вопросов. Во-первых поинтересоваться тем, что не так с WASM, а во вторых тем, почему эта технология не получила достаточно серьёзного распространения.

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

Бесспорно то, что технология WebAssembly обладает огромным потенциалом, она позволяет делать удивительные вещи и переносить в веб существующие проекты, написанные на языках, не предназначенных для браузеров. Правда, в связи с этим возникает вопрос о том, знают ли об этом разработчики.

Вот вы, например, до чтения этой статьи, уделяли ли некоторое время тому, чтобы найти примеры реального применения WASM? Знаете ли вы о том, как написать WASM-вариант Hello, World!? Возникала ли у вас необходимость переноса приложения, написанного для настольной системы, в браузер?

Думаю, что ещё одна ключевая проблема WASM заключается в том, что эта технология нацелена не на веб-разработчиков. Она рассчитана абсолютно на всех, кто хочет перенести некий код в веб-среду. Веб-разработчикам технология WASM не нужна. Они уже знают о том, как пользоваться JavaScript. А учитывая то, сколько сил отнимает даже создание простой WASM-версии Hello, World! (вот пример), я вполне понимаю то, что они особо не стремятся освоить эту технологию.

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

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

Станет ли технология WASM чем-то вроде нового стандартного языка для разработки веб-проектов?


WASM нужно пройти долгий путь прежде чем соответствующие подсистемы можно будет легко реализовывать в веб-проектах, не говоря уже о том, чтобы полностью перекладывать на WASM реализацию логики приложения.

Стоит помнить о том, что разработчики-то, на самом деле, не пишут WASM-код. Вместо этого ожидается, что они будут писать на C, на Go, или на каком-то другом языке, а потом то, что они написали, будет работать в браузере.

Учитывая это я не думаю, что WASM вскоре заменит JavaScript. Правда, число тех, кто пользуется WASM, будет расти, так как тенденция перемещения всего в облачные среды помогает изменить то отношение к требовательным проектам, о котором я говорил выше.

Веб-разработчик вы или нет вы не сможете поспорить с тем, что благодаря тому, как устроена веб-разработка, можно, затратив сравнительно небольшие усилия, взаимодействовать с миллионами пользователей. При этом у веб-разработчика есть весьма гибкие средства, позволяющие менять и обновлять клиентское программное обеспечение. Эта модель скоро станет более привлекательной для компаний, который сейчас имеют полностью нативные (то есть настольные или мобильные) продукты. Время идёт, а индустрия разработки ПО продолжает движение в сторону облачных технологий.

На самом деле, у технологии WASM есть возможность продлить срок годности навыков разработчиков, которые занимаются сейчас тем, что не связано с вебом. Она позволяет таким разработчикам продолжить пользоваться тем, к чему они привыкли, разрабатывая проекты для новой платформы.

Итоги


Технологию WebAssembly создавали люди, ведомые великой целью: устранить разрыв между вебом и всем остальным миром программного обеспечения. Правда, в этой области ещё очень и очень многое предстоит сделать. Но сильные стороны WASM уже вполне хорошо видны в тех проектах, где эта технология используется. Одно только то, что WASM поддерживают 4 ведущих браузера, говорит о том, что эта технология набирает популярность в сфере разработки ПО.

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

А что думаете об этом вы? Полагаете ли вы, что WASM через некоторое время превратиться в ключевую технологию веб-платформы? Видите ли вы формат WASM чем-то таким, что станет, лет через десять-двадцать, стандартным форматом, в который компилируется код, написанный на разных языках программирования? Или, может, вам кажется, что проект WASM попросту провалится, и что в сообществе разработчиков не иссякнут разговоры о противостоянии нативных и браузерных приложений?

Подробнее..

Эффект параллакса в браузере с помощью TensorFlow.js WASM Three.js

29.06.2020 08:16:31 | Автор: admin
Помните как Apple представила iOS7 c эффектом параллакса? Сегодня я обьясню как я сделал это прямо в браузере.
image

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



Наверно всем известно что есть библиотека Tensorflow для нейронных сетей, она работает под языком Python и Javascript. Процесс свертки в нейронных сетях это достаточно тяжеловесное вычисление, которое хорошо параллелится и существуют версии не только для CPU, но и на CUDA под Python и WebGL/WebGPU под Javascript. Забавно, но если у вас не NVidia, то оффициальная сборка Tensorflow на языке Javascript будет на ПК будет работать быстрее, так как нет официальной сборки с поддержкой OpenGL. Но к счастью для всех TF 2.0 имеет модульную архитектуру, которая позволяет думать только о самой сути, а не языке, на котором это выполняется. Так же существуют конвертеры 1.0 -> 2.0, которые я пока сам особо не пробовал.



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

В браузере на данный момент существует 5 бэкендов: cpu, wasm, webgl, wasm-simd, webgpu. Первый СPU слишком медленный и его сейчас не стоит брать ни в каких случаях, последний два слишком инновационны и находятся на стадии пропосалов и работают под флагами, так что поддержка у конечных клиентов нулевая. Поэтому я выбирал из двух: WebGL и WASM.



По существующим бенчмаркам можно увидеть, что что для маленьких моделей WASM работает порой быстрее чем WebGL. Кроме этого, параллакс может использоваться с 3д сценами и запуская WASM бэкенд на них, я понял что WASM работает гораздо лучше, так как дискретные видеокарты ноутбуков, не вывозят одновременно нейросети и 3д сцены. Для этого я взял простую сцену с 75-ю гловами в .glb. Ссылка кликабельная и там WASM.



Если вы перешли по ссылке, вы наверно заметили, что браузер спросил разрешение на доступ к видеокамере. Возникает вопрос: что будет, если пользователь нажал нет? Разумно было бы ничего не грузить в таком случае и фоллбэчить на управление мышью\гироскопом. Я не нашел ESM версию tfjs-core и tfjs-converter, так что вместо динамического импорта, я остановился на довольно криповой конструкции с бибилиотекой fetchInject, где порядок загрузки модулей имеет значение.
криповая конструкция
Забавно то, что порядок расположения имеет значение и нельзя их оборачивать в один массив (Promise.All), так как это приведет к довольно не приятной ошибке, которая исчезает после первой загрузки и дальше не воспроизводится, так как скрипты попадают в кэш.
fetchInject([  'https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface@0.0.5/dist/blazeface.min.js'], fetchInject([  'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter@2.0.1/dist/tf-converter.min.js',  'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@2.0.1/dist/tfjs-backend-wasm.wasm'], fetchInject([  'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core@2.0.1/dist/tf-core.min.js']))).then(() => {  tf.wasm.setWasmPath('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@2.0.1/dist/tf-backend-wasm.min.js');  //some other code}



Для того что бы найти положение взгляда, я беру среднее между двумя глазами. И легко понять что растояние до головы, будет пропорционально растоянию между глазами на видео, в силу подобия сторон треугольника. Данные о положении глаз, которые приходят из модели довольно зашумленные, поэтому прежде чем производить рачеты, я их сгладил с помощью скользящей средней EMA (Exponential Moving Average)

pos = (1 - smooth) * pos + smooth * nextPos;

Или записав по другому

pos *= 1 - smooth;pos += nextPos * smooth;


Таким образом мы получаем координаты x, y, z, в некой сферической системе координат с центром в камере. Причем x и y ограничены углом обзора камеры, а z это примерное растояние от головы до нее. На малых углах поворота $sin(\alpha) \approx \alpha$, так что x и y можно считать за углы.

pushUpdate({  x: (eyes[0] + eyes[2]) / video.width - 1,  y: 1 - (eyes[1] + eyes[3]) / video.width,  z: defautDist / dist});


Фотограмметрия



Довольно забавный дата сет с публикации SIGGRAPH 2020 Immersive light field video with a layered mesh representation. Они делали картинки специально для того что бы можно было двигать камеру в некотором диапазоне, что идеально ложится под идею параллакса. Пример с параллаксом.



3д сцена тут создается послойно, и на каждый слой наложена текстура. Не менее забавно выглядит дейвайс, с помощью которого они создавали фотограмметрию. Они купили 47 дешевых экш камер Yi 4K за 10к рублей каждая, и разместили их на полусферу в форме икосаэдра в котором треугольная сетка утроена. После этого все разместили на штатив и камеры синхронизировали для сьемки.



Ссылки:


Подробнее..
Категории: Javascript , Webgl , 3d , Tensorflow , Webassembly , Tfjs , Wasm , Three.js

2048 WASM или игра на Rust за 2 дня

22.01.2021 18:12:57 | Автор: admin

Данная статья представляет из-себя эксперимент с Rust'ом с последующей его компиляцией в WASM. Было интересно пощупать данные технологии на чем-то сложнее, чем вычисление факториала, поэтому выбор пал на всем известную игру 2048.




Описание игры


Оригинальная игра представляет из себя клеточное поле 4 на 4. Каждая клетка может быть либо пустой, либо занята плиткой
с числом, являющегося степенью двойки. Стартовое состояние поля имеет 2 заполненные клетки.




Игрок может совершать ход в одном из 4 направлений: влево, вправо, вверх и вниз, что сдвигает все плитки до упора в выбранном
направлении. После каждого хода появляется новая плитка. Новая плитка будет содержать двойку с вероятностью 90% или четверку
с вероятностью 10%.


Походим из стартового состояния, показанного выше, вправо:




Плитка на втором ряду уперлась в правую границу, также появилась двойка на первом ряду, третьем столбце.


Если плитка упирается в другую плитку, содержащее такое же число, они соединяются в одну плитку следующей степени двойки.


Походим из предыдущего состояния вверх:




Двойки последнего столбца первой и второй строк объединилсь в одну, а кроме этого на третьем ряду появилась четверка.


Цель игры: дойти до плитки с числом 2048.


Подготовка


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


На данной странице представлен список фронтовых фреймворков для Rust.
Самый популярный вариант Yew выглядит интересно, особенно при наличии опыта с React'ом, документация и примеры присутствуют,
так что выбор пал на него.


Инструкцию по созданию проекта можно найти здесь и выполняется она тривиально:


cargo new --lib rust-2048 && cd rust-2048

Дальше, в Cargo.toml прописываем зависимости:


[dependencies]yew = "0.17"wasm-bindgen = "0.2.67"

В примере предоставлен код для создания простого счетчика, который нужно поместить в src/lib.rs:


use wasm_bindgen::prelude::*;use yew::prelude::*;struct Model {    link: ComponentLink<Self>,    value: i64,}enum Msg {    AddOne,}impl Component for Model {    type Message = Msg;    type Properties = ();    fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {        Self {            link,            value: 0,        }    }    fn update(&mut self, msg: Self::Message) -> ShouldRender {        match msg {            Msg::AddOne => self.value += 1        }        true    }    fn change(&mut self, _props: Self::Properties) -> ShouldRender {        // Should only return "true" if new properties are different to        // previously received properties.        // This component has no properties so we will always return "false".        false    }    fn view(&self) -> Html {        html! {            <div>                <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>                <p>{ self.value }</p>            </div>        }    }}#[wasm_bindgen(start)]pub fn run_app() {    App::<Model>::new().mount_to_body();}

Создаем директорию для статичных файлов:


mkdir static

Внутри которой создаем index.html со следующим содержимым:


<!DOCTYPE html><html lang="en">  <head>    <meta charset="utf-8" />    <title>Yew Sample App</title>    <script type="module">      import init from "./wasm.js";      init();    </script>  </head>  <body></body></html>

Собираем проект при помощи wasm-pack (устанавливается через cargo install wasm-pack):


wasm-pack build --target web --out-name wasm --out-dir ./static

У меня при сборке появилась следующая ошибка:


Error: crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your Cargo.toml file:[lib]crate-type = ["cdylib", "rlib"]

Окей, так и сделаем. Открываем Cargo.toml и прописываем в конце:


[lib]crate-type = ["cdylib", "rlib"]

Теперь можем запустить любой сервер статики и проверить результат (в примере предлагают установить miniserve, я же воспользуюсь стандартным питоновским модулем):


cd staticpython -m SimpleHTTPServer

Открываем http://127.0.0.1:8000 и видим рабочий счетчик. Отлично, теперь можно приступать к самой игре.


Основа


Коммит: https://github.com/dev-family/wasm-2048/commit/6bc015fbc88c1633f4605944fd920b2780e261c1


Здесь я описал основные сущности игры и реализовал перемещение плиток без объединений. Также были добавлены
вспомогательные структуры и методы для удобства.


Рассмотрим логику движения плиток на примере данного поля:


2, 4, 0, 00, 0, 0, 00, 0, 0, 00, 0, 0, 0

Предположим, что был совершен ход вправо. Ожидается следующий результат:


0, 0, 2, 40, 0, 0, 00, 0, 0, 00, 0, 0, 0

Такого поведения можно добиться, если идти от конца выбранного направления и сдвигать все плитки по выбранному направлению.
Проитерирую вручную для лучшего понимания:


  1. Выбрано направление вправо => идем справа влево.

         /-------- пустая клетка, пропускаем2, 4, 0, 00, 0, 0, 00, 0, 0, 00, 0, 0, 0

2.


      /-------- пустая клетка, пропускаем2, 4, 0, 00, 0, 0, 00, 0, 0, 00, 0, 0, 0

3.


    /-------- начинаем сдвигать вправо2, 4, 0, 00, 0, 0, 00, 0, 0, 00, 0, 0, 0

4.


       /-------- продолжаем2, 0, 4, 00, 0, 0, 00, 0, 0, 00, 0, 0, 0

5.


         /-------- дошли до конца, возвращаемся на следующую позицию от которой начали передвижение2, 0, 0, 40, 0, 0, 00, 0, 0, 00, 0, 0, 0

6.


 /-------- двигаем вправо2, 0, 0, 40, 0, 0, 00, 0, 0, 00, 0, 0, 0

7.


    /-------- продолжаем0, 2, 0, 40, 0, 0, 00, 0, 0, 00, 0, 0, 0

8.


       /-------- остонавливаемся и переходим к следующей строке0, 0, 2, 40, 0, 0, 00, 0, 0, 00, 0, 0, 0

Также стоит заметить, что в случае горизонтальных ходов строки двигаются независимо друг от друга, а в случае вертикальных столбцы.


В коде данный алгоритм реализован методами Direction#build_traversal (построение пути обхода поля),
Grid#traverse_from (продвижение конкретной клетки по направлению) и Grid#move_in публичный метод, использующий предыдущие два.


Объединения


Коммит: https://github.com/dev-family/wasm-2048/commit/7e08b5af6008e6f9d716d7c9a41b0810e869df9e


У объединения плиток есть одна особенность: плитки не объединяются больше одного раза,
т.е. в случае наезжающих друг на друга 4 одинаковых плит, результатом будет являться 2 плитки
следующей степени. Из этого следует, что у плиток должно появиться некое состояние, которое нужно
сбрасывать перед каждым ходом.


Плюс, пришлось изменить структуру TestCase, т.к. правильное поведение можно протестировать только за несколько ходов.


Добавление новых плиток


Коммит: https://github.com/dev-family/wasm-2048/commit/6082409412f6c19943c453c5d706d57bbcef538b


Для рандома используется пакет rand, который работает и в WASM среде
путем добавления wasm-bindgen feature.


Для того, чтобы не ломать предыдущие тесты, которые не рассчитаны на добавление новых случайных
плиток в структуру Grid было добавлено новое флаговое поле enable_new_tiles.


Поскольку новые плитки добавлять нужно только в случае валидного хода (т.е. за ход произошло хоть одно изменение поля),
сигнатура traverse_from меняется. Теперь метод возращает булево значение, которое показывает, было ли движение.


UI


Коммит: https://github.com/dev-family/wasm-2048/commit/356e0889a84d7fc2582662e76238f94fc69bfed7


UI часть реализуется довольно просто, особенно для знакомых с React и/или JSX. Прочитать про html! макрос из Yew можно здесь,
а про компоненты в общем здесь. Мне очень напомнило React в пре-хуковых времен.


Документации по работе с клавиатурой не нашлось, да и в принципе сервисы никак не документированы, нужно читать исходники, смотреть примеры.


Анимации


Коммит: https://github.com/dev-family/wasm-2048/commit/e258748ab114ec5f930dbeb77d674bdbc5e63b1a.


Чтобы интерфейс смотрелся более живым, необходимо добавить анимации.


Они реализованы поверх обычных CSS transitions. Мы учим плитки запоминать их предыдущую позицию и при рендере отображаем плитку сразу в старой позиции, а на следующем тике в новой.

Подробнее..
Категории: Rust , Gamedev , Разработка игр , Wasm , 2048

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru