2015-02-25 4 views
1

Я пишу программу GPGPU с использованием шейдеров GLSL и пытаюсь придумать несколько оптимизаций для алгоритма обнаружения столкновений N-тела. Один выполняет «быструю» проверку, чтобы определить, находятся ли два объекта в одном и том же шаре. Идея состоит в том, чтобы быстро дисквалифицировать множество возможностей, поэтому мне нужно выполнить более точный тест столкновения на нескольких объектах. Если быстрая проверка решила, что есть вероятность, что они могут столкнуться, выполняется точная проверка.Вычислительная стоимость математических операций в GLSL

Объекты - круги (или сферы). Я знаю положение их центра и их радиус. Быстрая проверка будет ли их квадрат (или куб), ограничивающей коробки перекрываются:

//make sure A is to the right of and above B 
//code for that 

if(A_minX > B_maxX) return false; //they definitely don't collide 
if(A_minY > B_maxY) return false; //they definitely don't collide 

if(length(A_position - B_position) <= A_radius + B_radius){ 
    //they definitely do collide 
    return true; 
} 

Мой вопрос, является ли накладные расходы выполнения этой быстрой проверки (убедившись, что А и В находятся в правильном порядке, то проверки, является ли их перекрывающиеся перекрытия) будет быстрее, чем позвонить length() и сравнить это с их объединенными радиусами.

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

+0

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

+0

Любая идея, насколько быстрее? Есть статья в википедии, описывающая сложность различных операций, но она очень универсальна: https://en.wikipedia.org/wiki/Computational_complexity_of_mathematics_operations Я не знаю, какие конкретные алгоритмы используются в GLSL. Я предполагаю, что вычисление квадратного корня является дорогостоящим, но, похоже, алгоритм аппроксимации довольно быстрый. – Justin

ответ

0

Пока мы находимся на тему расходов, вам не нужны две ветви. Вместо этого вы можете проверить результаты тестирования компонентов. Таким образом, это может быть свернуто в один тест с использованием any (greaterThan (A_min, B_max)). Хороший компилятор, вероятно, это выяснит, но это поможет, если вы рассмотрите параллелизм данных самостоятельно.

Затраты все относительно. 15 лет назад арифметическая работа, необходимая для выполнения того, что делала length (...), была такой, что вы могли бы сделать поиск текстуры кубама за меньшее время - на более новом оборудовании вы были бы безумны, чтобы сделать это, потому что вычисление быстрее, чем память.

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

+0

Спасибо за подсказку о расхождении нитей. Компиляторы и параллельная обработка - это темы, которые я никогда не встречал в школе.Поэтому, вероятно, лучший способ оптимизации в моем случае - попробовать этот «оптимизированный» способ, а затем попробовать версию, которая каждый раз вызывает «length()», и посмотреть, какая из них работает быстрее? – Justin

+0

@ Justin: Это не темы, охватываемые большинством программ для студентов, насколько я знаю, так что это понятно. Особенно расходятся большинство обсуждений параллельного исполнения, вероятно, будут ограничены опасностями данных и синхронизацией, если вы специально не изучаете графические процессоры. Да, вы могли бы, вероятно, проверить это (запустите тест тысячи раз, пока не появится измеримая разница), чтобы получить некоторое представление о стоимости, но интуитивно я не думаю, что будет так много, если будет какая-либо разница. Как я вижу, ветвление дороже, чем 'length (...)' в этом случае. –

+0

@Justin: Но если у вас была ситуация, когда вы могли бы разработать условие ветви, которое по своей сути было лучше, чем 50/50 шансов на успех, это может быть победа. Например, если 90% вашего набора данных не дают какого-либо теста, это действительно хорошая возможность использовать ветвление для повышения производительности. –

0

Вы можете избежать использования квадратных корней (которые неявно необходимы для функции length()) путем сравнения квадратов значений.

тест может выглядеть следующим образом:

vec3 vDiff = A_position - B_position; 
float radSum = A_radius + B_radius; 
if (dot(vDiff, vDiff) < radSum * radSum) { 
    return true; 
} 

Это уменьшает его обратно в один тест, но до сих пор использует только простые и эффективные операции.

+0

Теперь есть умная оптимизация. Благодаря! – Justin

Смежные вопросы