Pixi.js: считали gl-матрицу?

Созданный на 30 июн. 2017  ·  39Комментарии  ·  Источник: pixijs/pixi.js

Это может быть ересью, но я поделюсь идеей и позволю людям кричать о кровавом убийстве ... рассматривали ли мы когда-нибудь возможность стандартизации матриц, точек, основанных на массивах, а не на объектах? WebGL ожидает массивы в большинстве своих apis вершин / текстур / и т. Д. Существует также множество существующих модулей экосистемы, которые стандартизируются на простых старых или собственных массивах (например, https://github.com/toji/gl-matrix). Gl-matrix была бы хороша, учитывая, что многие браузеры имеют аппаратную поддержку SIMD за флагами. , и скоро будут доступны (на самом деле, gl-matrix внутренне поддерживает это сейчас.)

Я понимаю, что это будет серьезным сдвигом парадигмы для pixi и полностью нарушит обратную совместимость ... тем не менее, я хотел выбросить это там и посмотреть, что люди думают, и насколько / мало они ненавидят эту идею;)

Самый полезный комментарий

@GoodBoyDigital Думаю, ты прав. прибегая к моему другу миссис. гугл, наткнулся на это:

https://stackoverflow.com/questions/15823021/when-to-use-float32array-instead-of-array-in-javascript

ответ с наивысшей оценкой (сейчас 44 голоса) кажется разумным и актуальным.

Все 39 Комментарий

1) SIMD сдох. https://github.com/rwaldron/tc39-notes/blob/a66df6740eec3358d5e24f81817db99d6ee41401/es8/2017-03/mar-21.md#10if -simdjs-status-update

2) Простые 6 полей «a, b, c, d, tx, ty» работают намного лучше, чем матрица Float32Array (9). Не могу дать ссылки на тесты, но я и @GoodBoyDigital уже пытались его интегрировать.

3) JS выполняет двойную точность, что критично для приложений, работающих с большими координатами. "projection x transform" для графики и спрайтов лучше использовать на стороне JS.

Я использую Float32Array (9) в версии 5, которая в моих тестах jsperf была похожей, если не такой же, и избавляет нас от необходимости выполнять операции toArray и транспонировать.

https://github.com/pixijs/pixi.js/blob/455c059e8d155c1d9a05fc2ece2c02b3bdf8bf84/plugins/core/src/math/Matrix.js

gl-matrix полезен, потому что у него есть SIMD (который, как сказал Иван, является мертвой спецификацией), но также имеет недостатки в их реализации. Мы хотим, чтобы матрица 3x3 ( Float32Array(9) ) воздействовала на графический процессор, но выполняла операции, как если бы это была 2D-матрица, чтобы сэкономить время вычислений. gl-matrix не имеет для этого хорошего механизма.

Версия v5 использует хранилище, которое мы можем загрузить непосредственно в графический процессор, а также работать только с 2D-частями, которые нам небезразличны. Это также настраивает нас на возможность использования SharedArrayBuffers и других оптимизаций, которые могут позволить нам больше поработать над веб-рабочими. Посмотрим, как далеко мы сможем с этим продвинуться.

@englercj Боюсь, нам придется использовать Math.fround во многих местах, чтобы быть последовательными. Попробуйте perf Float64Array.

Я мог бы попробовать сделать его Float64Array, но тогда нам все равно нужно уменьшить его до одинарной точности для загрузки. Также имейте в виду, что в настоящее время мы используем float32 при загрузке в графический процессор . Итак, мы выполняем вычисления в двойном размере, а затем усекаем его до одиночного. Это может быть более точным, чем делать все за один раз, но я хотел бы попытаться согласоваться с типом данных, который мы загружаем. К сожалению, это означает одинарную точность до GL 4.0, а WebGL 2 - это только GL ES 3.0 :(

Загрузка матрицы никогда не была нашим узким местом, в этих местах мы используем "uniform3fv", это непростая операция, за ней следует drawCall и, в большинстве случаев, загрузка большого буфера. Приложение Heavy pixi выполняет всего около 400 вызовов отрисовки за кадр,

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

Кроме того, обозначения «a, b, c, d, tx, ty» легче писать и читать, чем «0,1,3,4,6,7». Его также используют для позвоночника, к тому же у них есть очень сложные трансформации. Если мы перейдем к матрицам, потом будет не так просто проверить наш код. Некоторым людям сложно представить матричные операции, но я их легко читаю.

UPD. Я также думаю, что это поможет нам больше, чем преобразование матриц: https://github.com/gameofbombs/gobi/blob/master/src/core/math/FlatTransform2d.ts , это "Flat" преобразование, содержит все необходимые поля для расчета матрицы.

UPD2. Но для трехмерных преобразований лучше использовать Float32Array (16), и я не буду возражать против этого.

Я отдаю свой голос тому, кто дает лучшие результаты. Последний раз, когда я проверял это с использованием объектов над массивами, было быстрее. Хотя я не уверен на 100%, что это все еще правда, все могло измениться!

Для 3D я предпочитаю стиль gl-матрицы, в основном потому, что на GPU много загружается! В случае с Pixi это не так. Большинство манипуляций происходит в js land (например, дозатор спрайтов).

https://jsperf.com/obj-vs-array-view-access/1

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

Изменить: похоже, что результат Array был случайностью, я не могу его воспроизвести?

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

Это очень интересно. Кажется нелогичным, что объекты будут быстрее, чем чисто числовой массив, потому что базовая виртуальная машина должна иметь возможность выполнять ряд оптимизаций, зная, что семантика объекта может быть в значительной степени удалена. Мне любопытно, есть ли у вас идеи, почему объекты могут быть быстрее?

Соответствующие результаты моего компьютера (i7, Windows 10):

Хром 59:

image

Firefox 54.0.1 (32-разрядная версия):

image

Microsoft Edge 40.15063.0.0:

image

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

В любом случае член Float32Array всегда имеет одинаковую скорость или быстрее, чем объект во всех браузерах. Вот почему я переключил его, это та же скорость, что и раньше (или быстрее), но теперь мы избегаем транспонирования и заполнения массива для загрузки.

Можете ли вы сделать то же самое с Float64, пожалуйста? :)

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

Кроме того, мы нечасто используем инвертирование. updateTransform () - наша проблема.

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

Как Float64Array обеспечивает более высокое качество кода? Я понимаю, что мы получаем больше точности, но я не уверен, что понимаю, почему это так важно, учитывая, что мы все равно сводимся к одинарной точности.

Кроме того, мы не часто используем инвертирование. updateTransform () - наша проблема.

Это эталонный тест чтения / записи хранилища данных, операция, выполняемая с промежуточными значениями, не имеет значения.

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

Я также с этим согласен. Учтите, что "стандартизация" на основе матриц, точек и векторов на основе массивов на самом деле может быть больше для улучшения качества кода, чем для производительности ... Я бы рассмотрел возможность повторного использования популярных библиотек js-матриц / векторов и большей совместимости с популярными модулями рендеринга. к большой победе в области качества кода.

Это тестирование чтения / записи хранилища данных,
операция, выполняемая над значениями между ними, не имеет значения.

Думаю, вы оба правы. Это общий тест чтения / записи хранилища данных. Но у Ивана действительно хорошая мысль; если updateTransform() - это ошеломляющая операция, было бы интересно увидеть это.

Меня вообще беспокоят микротесты; с этими статическими наборами данных мне интересно, не воспользуемся ли мы непреднамеренно оптимизацией компилятора в javascript vms в этих тестах. выполнение тестов в реальном мире было бы намного более поучительным (за счет того, что для настройки требовалось больше работы).

Я также с этим согласен. Учтите, что "стандартизация" на основе матриц, точек и векторов на основе массивов на самом деле может быть больше для улучшения качества кода, чем для производительности ... Я бы рассмотрел возможность повторного использования популярных библиотек js-матриц / векторов и большей совместимости с популярными модулями рендеринга. к большой победе в области качества кода.

Я за матрицу двойной точности "(a, b), (c, d), (tx, ty)" с преобразованием в float32array для загрузки и поддержкой "posX, posY, pivotX, pivotY, scaleX, scaleY, shearX, shearY, rotZ ". Я все равно буду использовать его в своей вилке, но я также предпочитаю не иметь дело с матричными массивами в master pixi. Это мой стандарт.

Я также сомневаюсь, что можно заставить людей использовать один или два стандарта для математики vec в js.

Как Float64Array обеспечивает более высокое качество кода? Я понимаю, что мы получаем больше точности, но я не уверен, что понимаю, почему это так важно, учитывая, что мы все равно сводимся к одинарной точности.

Мы умножаем преобразование камеры на преобразование спрайта (для прокрутки) в updateTransform. Результат умещается на экране только в том случае, если он маленький, поэтому числа в конце будут маленькими, но и положение спрайта, и положение камеры могут быть большими. Решения на стороне пользователя:

1) вычислить все на его стороне. PIXI имеет дело только с относительно небольшими координатами.
2) разделите мир на куски с большими координатами, спрайт имеет относительно маленькие координаты, однако это не сработает для субпиксельной камеры => камере также нужны большие и маленькие координаты.

В случае большого проекта можно заставить пользователя делать это на его стороне, но для маленьких это еще одна головная боль.

Я также сомневаюсь, что можно заставить людей использовать один или два стандарта для математики vec в js.

Я не понимаю, что вы имеете в виду, вы можете уточнить?

Я не понимаю, что вы имеете в виду, вы можете уточнить?

Я не могу, это для меня слишком.

У нас есть люди с разным опытом как в низкоуровневой оптимизации. и языковые конструкции, DSL-ы. Нам нужен стандарт, который удовлетворит всех нас на каком-то уровне.

За последние два года я сделал две вилки pixi (для v3 и v4) с разными преобразованиями, я имею дело с pixi-spine, у которого есть собственное расширенное преобразование, и я делаю третью вилку. С точки зрения "ивана прошлого" лучше всего использовать массив, потому что он имеет простейшую форму и есть "gl-матрица".

Я согласен с @ivanpopelyshev в том, что поддержка 64-

Возможно, мы сохраним его как Float64Array, а при загрузке скопируем его в Float32Array. Это, по крайней мере, позволяет нам использовать типизированный массив в качестве резервного хранилища, которое должно быть проще копировать в / из веб-работника.

Тогда Float64Array, мне просто нужно не забыть использовать (0,1), (3,4), (6,7) как X, Y, перевести

Все интересное, ребята, я хотел бы, чтобы мы протестировали наше предлагаемое решение в реальном сценарии pixi - что-то вроде bunnymark.

По моему опыту в этой области, когда я и @ivanpopelyshev в последний раз перешли на gl-матрицу для bunny mark, мы обнаружили, что она работает значительно медленнее (как третья медленнее!)

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

Pixi - СКОРОСТЬ: P Давайте обязательно протестируем, прежде чем полностью переходить к какому-либо решению.

Нам все еще нужен тест Float64Array. Эта реализация для меня приемлема, но лично я буду использовать в своей вилке старую матрицу. Также не забудьте добавить свойства только для совместимости.

Еще одна вещь: @mreinstein , один из стандартов, который я помню, это PaperScript, специальный язык для paper.js, который добавляет точечные операции непосредственно в язык. Если бы в JS было больше синтаксического сахара, мы бы тоже использовали что-то подобное.

Могу ли я чем-нибудь помочь с обновленным bunnymark? Я счастлив уделить этому немного времени.

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

Кое-что отметить по поводу тестирования производительности ... Chrome v8 недавно (в v59) выпустил несколько довольно существенных изменений в v8, которые называются турбовентиляторными. Предположительно, у него есть несколько значительных улучшений производительности.

https://v8project.blogspot.com/2017/05/launching-ignition-and-turbofan.html

Может быть интересно запустить обновленную версию Bunnymark на версии до появления турбовентиляторного двигателя и сейчас, черт возьми.

@GoodBoyDigital Я обновил стенд, включив в него Float64Array, и он постоянно быстрее читает / записывает в массив, чем объект. Если в pixi он становится медленнее, то что-то еще меняется, потому что чтение / запись в резервное хранилище Float64Array выполняется быстрее, чем объект.

https://jsperf.com/obj-vs-array-view-access/1
image

Только на Edge скорость объекта соответствует / превышает Float64Array, и это действительно близко.

Я протестировал это в своем окружении и получил аналогичные результаты ... какого черта ?! Почему чтение / запись массива Float64 будет значительно быстрее, чем эквивалентные операции с массивом Float32? Единственное, что приходит в голову, может быть, 64-битные числа с плавающей запятой выравниваются по границам слов? Я в недоумении.

Спасибо за предложение @mreinstein ! Если бы вы могли помочь нам с некоторыми тестами производительности, которые, безусловно, усыпили бы всю дискуссию холодными неопровержимыми фактами!

Лучше всего разветвить pixi, а затем заменить преобразования классом gl-matrix или @englercj . В этом случае нам действительно нужно только заставить работать пакет спрайтов, а не весь движок!

Затем, когда у нас будет настроенная версия, мы можем протестировать производительность здесь: https://pixijs.github.io/bunny-mark/
Мы можем возиться с различными типами массивов.

@englercj это классный чувак! Приятно видеть эти результаты точно. Приближается ли версия v5 к состоянию, в котором мы можем дать кроличью отметку крутость?

@mreinstein просто догадка, я думаю, это может быть связано с преобразованием из 64 бит в> 32 бит
поскольку число в js является 64-битным, верно?

@GoodBoyDigital Думаю, ты прав. прибегая к моему другу миссис. гугл, наткнулся на это:

https://stackoverflow.com/questions/15823021/when-to-use-float32array-instead-of-array-in-javascript

ответ с наивысшей оценкой (сейчас 44 голоса) кажется разумным и актуальным.

Если бы вы могли помочь нам с тестами производительности

Хорошо, рада помочь с этим. :)

Лучше всего использовать вилку pixi

@GoodBoyDigital @englercj какая ветвь лучше всего подходит для разветвления на данный момент?

затем замените преобразования классом матриц gl-matrix или
В этом случае нам действительно нужно только заставить работать пакет спрайтов, а не весь движок!

Не могли бы вы подробнее рассказать об этом? Я не хочу преобразовывать весь движок в gl-матрицу только для запуска перфокарта ... Я не вижу каких-либо пакетов спрайтов в https://github.com/pixijs/bunny-mark Кажется, есть PIXI.Container в качестве корневого элемента, к которому добавляются кролики. Вы хотите сказать, что я должен начать с pixi.container, pixi.sprite и двигаться оттуда вверх по дереву зависимостей, чтобы найти все места, где требуется замена материала преобразования? Я не говорю, что не согласен, просто хочу убедиться, что у меня есть правильная стратегия, позволяющая свести к минимуму ненужную работу.

updateTransform имеет внутри две матричные операции:

  1. композиция из позиции, поворота, масштаба, поворота - не может быть улучшена.
  2. умножение на родительскую матрицу - можно улучшить.

Я предлагаю создать матричный класс со старыми реквизитами «a, b, c, d, tx, ty», поддерживаемыми Float64Array, и переписать updateTransform. Кроме того, @mreinstein сделал достаточно вещей, чтобы быть в ядре, я предлагаю добавить его, чтобы у него был доступ к веткам и построению фермы.

так что у него есть доступ к веткам и постройке фермы.

У всех есть доступ к этому, все это делает fork + PR.

Мне любопытно, какие результаты вы, ребята, получите в bunny mark ... когда я пробую различные ветки (dev, release, другие) из Chrome со стандартными 100k bunnies, я постоянно получаю 10-16 кадров в секунду. Выполнение анализа производительности кода, работающего более 8,75 с:

screen shot 2017-07-02 at 11 58 03 am

Почти все время тратится на вызовы javascript.

screen shot 2017-07-02 at 11 57 50 am

Из этого времени, потраченного на javascript, львиная доля времени фактически тратится на Sprite.calculateVertices() . В 4 раза больше, чем тратится в TransformStatic.updateTransform()

В firefox я получаю примерно вдвое большую частоту кадров, но разбивка по затраченному времени аналогична; calculateVertices() занимает большую часть времени в обоих браузерах. Ожидается ли это? Получаете ли вы аналогичные результаты в своих забегах на кроликах?

Это ожидается от кроликов. А матричные операции, о которых мы говорим, выполняются в двух местах: upateTransform () для умножения и flush () ОДИН РАЗ ЗА ВЫЗОВ. В больших масштабах это не имеет значения.

Я запутался. :( Как я могу определить производительность этого теста? У меня создалось впечатление, что он в основном основан на достигнутом чистом fps. Если это правда, то моя частота кадров _существенно_ снижается из-за вычислений вершин. Глядя на первую диаграмму, которую я вставил выше, рендеринг составляет крошечную долю от общего времени кадра. Обновления вершин и преобразований превышают общее время кадра.

Если это неверно, а частота кадров в секунду не является показателем производительности моей сборки pixi, какие критерии я использую для измерения данной сборки?

Его можно регулировать как на CPU, так и на стороне GPU (не показано),

Если у вас FPS намного меньше 60, но "холостой ход" велик - его GPU.

Если холостой ход невелик, то это его ЦП.

CalculVertices имеет внутри матричную операцию - просто умножение четырех углов на матрицу.

Небольшая идея для вилки TS: добавить преобразование, встраивающее свойства для типов матриц. Жаль, что для TS еще нет таких преобразований :(

Я думаю, что это можно сделать и для babel, если мы найдем способ аннотировать матричные переменные.

Я больше не могу понять, что происходит.

Alt text

Следует иметь в виду: цель этого теста, в первую очередь, заключалась в том, чтобы увидеть, приведет ли использование объектов к gl-матрице к огромному снижению производительности, как предполагалось. Несмотря на различия в результатах наших тестов, мы, кажется, постоянно показываем, что производительность объекта не хуже, чем в большинстве случаев с массивами.

Я также хочу не делать здесь выводов о производительности Pixi в целом, потому что я профилировал метку кролика. В Chrome> 50% общего времени программы тратится на Sprite.calculateVertices() (40% -ное отклонение), за которым следует TransformStatic.updateTransform() (11% -ое отклонение) Firefox, похоже, работает в два раза быстрее, но соотношение времени, потраченного на эти 2 функции, все еще соответствует.

Я не хочу заходить слишком далеко от темы, но скажу, что, выполняя это профилирование bunnymark, я начинаю думать, что наше использование геттеров / сеттеров es5 может иметь какое-то отношение к перфорации в chrome: https: //jsperf.com/es5-getters-setters-versus-getter-setter-methods/10

Кто-нибудь из вас здесь болтается на слабину? Я думаю, что было бы проще общаться в полу-реальном времени, чем передавать здесь сообщения.

Что вы пишете по электронной почте

Судя по тому, что говорит @englercj, по- видимому, мы этого не делаем. Закрытие.

Небольшое обновление: у меня матрица 3x3 вместо 3x2 в https://github.com/pixijs/pixi-projection/blob/master/src/Matrix2d.ts на основе Float64Array.

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги