Suslik
Молодец, пока не смотрел, но ещё обязательно посмотрю. Такие труды всегда вызывают уважение.
Есть несколько вопросов:
- чем принципиально - твой движок отличается от скажем box2d?
- как считаешь какой на данный момент 2d физ. двиг лучший? =)
- насколько портируем код, т.е. можно ли будет скажем сделать C# версию, флэш версию, java, arm и т.д. - как это произошло с box2d. Насколько это будет гиморно?
- какова лицензия у твоего творения и планируешь ли ты его развивать далее?
Suslik
Не думаешь портировать на CUDA? Думаю, такая возможность есть.
При этом лучше всего обсчитывать каждый объект в отдельном треде и все будет пучком.
MaximYarilo
спасибо
>- чем принципиально - твой движок отличается от скажем box2d?
я не в курсе, на сколько сейчас развит бокс2д, но, что-то мне подсказывает, что в нём нет, по крайней мере такого чёткого и быстрого CollisionDetection для произвольных Convex тел.
Box2d, насколько я помню, имеет plain C интерфейс. Моё творение - рай для орхетектурных остронафтов.
>- как считаешь какой на данный момент 2d физ. двиг лучший? =)
Вообще, на мой взгляд, с 2д физикой сложилась занятная картина - так как она значительно проще 3д, никто из особо серьёзных ребят за неё просто не берётся. Ну есть chipmunk, Box2d, да и ещё пара, на пальцах посчитать можно. Но все они выполняют свои функции примерно одинаково хорошо, и здесь решает, ИМО, уже не качество симуляции, а удобство интерфейса и поддержка.
>- насколько портируем код, т.е. можно ли будет скажем сделать C# версию, флэш версию, java, arm и т.д. - как это произошло с box2d. Насколько это будет гиморно?
Да нормально он портируем. Если мне кто-нибудь заплатит, с радостью портирую хоть на брейнфак :)
>- какова лицензия у твоего творения и планируешь ли ты его развивать далее?
Ещё раз повторяю - "моё творение" - это прежде всего SuslikX 3d. 2d версия поставляется просто как довесок, и, ввиду простоты, до человечески удобоваримого уровня думаю довести сначала именно её. В принципе, того что сейчас есть в 2д SDK, уже достаточно потестено и вполне пригодно для использования в реальных игрушках. Лицензия - скачивай SDK и юзай на здоровье, желательно сообщи об этом мне :)
О. Федор
>Не думаешь портировать на CUDA? Думаю, такая возможность есть.
Я знаю CUDA не достаточно хорошо, чтобы писать на нём оптимальный код.
>При этом лучше всего обсчитывать каждый объект в отдельном треде и все будет пучком.
К сожалению, объекты в симуляции отнюдь не независимы. В Collision Detection было бы разумно сделать одна пара объектов - один тред. В Solver-стадии - один джойнт - один тред. Но неизбежны мороки вроде несоответствия количество джойнтов и количества тредов, некогерентные доступы к памяти, нехватка регистров. В общем, моё мнение - переписать код с C++ на CUDA - это несравнимо более тяжёлый труд, чем, скажем, на delphi, из-за принципиально разных и более сложных парадигм программирования.
Suslik
>Я знаю CUDA не достаточно хорошо, чтобы писать на нём оптимальный код.
Не отчаивайся, тут ты не одинок, думаю в мире мало кто (включая присутствующих) вообще понимает возможности CUDA.
>К сожалению, объекты в симуляции отнюдь не независимы.
Это не так страшно.
>В Collision Detection было бы разумно сделать одна пара объектов - один тред. В Solver-стадии - один джойнт - один тред. Но неизбежны мороки вроде несоответствия количество джойнтов и количества тредов, некогерентные доступы к памяти, нехватка регистров.
На этот случай вообще-то существует __syncthreads().
Если же ты оформишь Collision Detection в одну __global__ функцию, а Solver-стади в другую __global__ функцию, то количество тредов ты можешь произвольно определить для каждой из этих функций.
>В общем, моё мнение - переписать код с C++ на CUDA - это несравнимо более тяжёлый труд, чем, скажем, на delphi, из-за принципиально разных и более сложных парадигм программирования.
В общем, да, но трудности писания на CUDA сильно преувеличены. На самом деле тут ты можешь работать с привычными структурами и классами почти как и в C++. Только на память нужно больше внимания уделять.
О. Федор
Думаю, мне слишком дорога архитектура, которая сейачас есть. У меня везде кастомные менеджеры памяти, достаточно нетривиальные шаблонные конструкции для избежания виртуальных вызовов. Так что даже не знаю, стоит ли пытаться переписать всё это на языке с чуждыми мне парадигмами. Может быть, стоит подождать CUDA-компилятора С++?
CUDA уже сейчас практически С++. Во всяком случае наиболее ценное от С++ там есть. Нет указателей на функции, нет виртуальных функций, нет статических переменных (на девайсе, на хосте все есть), но без этого всего можно обойтись. Шаблоны во всяком случае есть.
Что мне нравится в CUDA, так это возможность естественной интеграции физики и графики.
У меня есть подозрение, что нвидиа специально замалчивает все возможности CUDA, чтоб через полгода заставить народ раскошелиться на новые карты, на которых якобы впервые идет С++-like CUDA, хотя уверен, изменений будет на самом деле совсем мало, потому что уже сейчас CUDA С++-like.
О. Федор
>нет виртуальных функций
точка. не представляю, как переделать свою архитектуру на полное отсутствие вирт. функций.
Suslik
Читай внимательно. Виртуальные функции отсутствуют на девайсе, на хосте их можно использовать.
ммм
насчет переписывания физдвигла под куду
насколько я понимаю ( а я практически вообще не знаком с кудой ), там идет выигрыш в скорости за счет огромного количества сопроцессоров, получаеца как бы офигенно многоядерный проц.
именно поэтому практически нереально писать нормальный ригидбоди с констрейнтами на куде ( можно только какую-нить какашку с хаками ), потому что "группы", или "острова" должны обсчитываца целиком в _ПОСЛЕДОВАТЕЛЬНОМ_ солвере, не параллельном, а это значит - использование одного треда. АФАИК, в качестве единицы обработки инфы сильнее все-таки ядро ЦПУ нежели сопроцессор на видюхе. это хорошо, когда максимальная группа - это два бокса стоящих друг на друге, т.е. в худшем случае 12 соединений (4 контактных на нижний бокс - земля и 8 в худшем случае на нижний бокс-верхний бокс ) и таких групп штук 60. Но если игрок захочет взять все эти боксы и свалить в кучу? жертвовать точностью? ( разбиение единой группы на подгруппы для сепаративного решения галимит всю суть ЛЦП-солверов ) жертвовать перформансом? ( ваще никатит )
целесообразно было бы действительно вынести в отдельные треды КД для пар тел, т.е. каждую пару тел постоянно трейсит фиксированный тред, но получили мы коллижн-инфо, ичо дальше? гонять по шине? фейл.
так вот, труъ физика а не мегохаки на видюхе обсчитываца не будет даже частично ( ввиду фидбека ), до тех пор по крайней мере, пока на видюхе не будет юнита в десятки раз мощнее проца именно в единственном числе, или же пока скорость шины не поднимут настолько, што трансфер данных ГПУ - ЦПУ не будет болезненным, особенно в обьемах физического фидбека.
это все исключительно мое представление о положении вещей на данный момент, и если что-то я неправильно думаю, очень буду рад если меня кто-то поправит.
P/S: все вышесказанное относица в большей степени к ригид-боди, потому что именно они требуют последовательного решения, не параллельного ( в силу сходимости первого ). флюиды, как на сетках эйлера, так и на лагранжевых частицах уже вовсю переносяца на гпу, ибо решать их вполне возможно параллельно. да и фидбек для ригидбоди с гпу можно перегонять в сильно упрощенном виде.
XperienS
Непрерывно качать данные с CPU на GPU и обратно - большой грех!
Нужно ориентироваться на то, что данные должны постоянно лежать на GPU.
Незнаю как суслик построил свой двиг, но лично я в своей софтине взаимозависимости разрешаю с помощью итераций. Т.е. будущее состояние объекта рассчитывается по состоянию всей системы в предыдущий момент времени. Это конечно в два раза увеличивает необходимую память, но упрощает расчет.
О. Федор
вот щас не совсем понял.
дан стек из 25 кубиков к примеру. нужно одномоментно рассчитать силы которые будут его держать. типичная задачка для физдвижка.
неизвеснто ничо, ни состояние t-1, ни состояние t+1. ( да даже если б и было известно, то што )
учитывая то, что мы решаем лцп, есть два подхода ( ну или не лцп, а последовательные импулься, что в принципе одно и то же ):
- параллельный вариант ( пример - итеративный солвер Якоби ): решаем систему, используя на текущей итерации (i) данные только с предыдущей итерации (i - 1);
- последовательный вариант ( каноническая реализация - Гаусс-Зейдель ): решаем систему, используя на текущей итерации (i) данные как с предыдущей итерации (i-1), так и с текущей (i), которые уже были посчитаны;
второй подход - сходица в разы быстрее чем первый, и более того, первый может не сойтись вообще, за доказательствами - в гугль :) поскольку системы большие, то мы не можем позволить себе юзать параллельный солвер как минимум из-за того что придеца нехило поднять планку максимальных итераций на группу. ну и то что он может не сойтись и привести систему к взрыву - это уже так, детали.
более того, несмотря на то, что метод Якоби и параллельный, все равно для каждой последующей итерации нужно сначала посчитать предыдущую, так что все равно не факт что даже заюзав его на ГПУ мы получим выгоду, а не полный провал в плане производительности.
а насчет трансфера данных -грех, шина медленна. но нам как минимум нужно хотябы звук проиграть при колижене с нормальной силой больше некоторого порогового значения, а это уже трансфер. так что мое мнение - ригид боди пока на цпу.
btw, софтина твоя што делает? считает ригид боди на гпу? со связями? со стеками? если тебе это удалось - то респект тебе гигантский, и охота пример и детальное обьяснение :)
XperienS
>btw, софтина твоя што делает?
+++ подписываюсь. Что там Фёдор после навье-стокса писал? :)
Кстати, Экспо, я бы не был так категоричен про отуствие возможности распараллеливания LCP солвера. Вот зацени, есть у нас стек 25 сфер. Все сразу мы их решить, ясен пень, не можем, потому что два треда не могут одновременно модифицировать скорости одного и того же тела. А что если взять и разделить все джойнты на две группы : каждый чётный контакт и нечётный? Тогда мы можем сначала решить всю первую группу контактов, а потом - вторую, без доступа к одним и тем же данным. В принципе, задача такого разбиения на группы сводится к тому, чтобы раскрасить вершины контактного графа так, чтобы никакие две вершины одинакового цвета не соединяло ребро. Насколько я помню, эта задача - NP-полная и человеческого решения не имеет. Хаки приветствуются :)
Suslik
это будет параллельный солвер
в последовательном, мы делаем так, считаем контакт 1 (тела 1 и 2), модифицируем данные тел 1-2. далее считаем контакт 2 (тела 2 и 3), юзая уже посчитанные скорости и силы тела 2, модифицируем данные, далее контакт 3 и т.д. и т.п. это все одна итерация.
если же считать только данные с предыдущей итерацие, то такой метод может прокатить, да. но не факт что овчинка стоит выделки. да и сходимость..
P/S:
пример со стеком может быть запутанным, если посмотреть на это немного с другой упрощенной точки зрения тех же интеграторов
возьмем явный интегратор эйлера:
x(t) = v(t-1)*dt;
v(t) = a(t-1)*dt;
update(a);
и semi-implicit ньютона-штормера-верле:
update(a);
v(t) = a(t) * dt;
x(t) = v(t) * dt;
разница впринципе видна невооруженным взглядом, что второй вариант будет гораздо точнее. примерно то же самое мы наблюдаем в параллельных vs последовательных солверах.
XperienS
>это будет параллельный солвер
Ты, наверно, не так понял. Решая контакты последовательно, имеем следующую картину:
- Решаем первый джойнт между первым и вторым шаром
модифицируем скорости между первым и вторым шаром
- Решаем контакт между вторым и третьим шаром
модифицируем скорости второго и третьего шара
- Решаем контакт между третьим и четвёрым шаром
модифицируем скорости третьего и четвёртого шара
Согласись, ничего особо не изменится, если мы решим обойти контакты в другом порядке:
- Решаем первый джойнт между первым и вторым шаром
модифицируем скорости между первым и вторым шаром
- Решаем контакт между третьим и четвёрым шаром
модифицируем скорости третьего и четвёртого шара
- Решаем контакт между вторым и третьим шаром
модифицируем скорости второго и третьего шара
Можем заметить следующее : решение первых двух джойнтов в таком порядке совершенно независимо, и их можно выполнять параллельно. Потом, во второй фазе, решить третий. То есть мы разбиваем последовательный солвер на независимые операции и делаем их параллельно - от этого солвер не перестанет быть последовательным :)
Suslik
> - Решаем контакт между третьим и четвёрым шаром
> модифицируем скорости третьего и четвёртого шара
для этого нужно знать результаты солвинга между вторым и третьим, а для того в свою очередь между первым и вторым. иначе получиеца что мы юзаем состояние обьекта номер 3 исключительно с предыдущей итерации. хотя, может быть я все еще не так понимаю.
правка: решать можно и в таком порядке, в каком ты предложил, это даже иногда рекомендуеца и называеца permutations, однакож в отдельные треды все равно этого вынести нельзя, ибо для решения i требуюца данные i-1, а для i-1 - i-2, так что вырвать вот так просто не получица, в этом-то вся проблема.
Тема в архиве.