Как вы могли бы распараллелить симуляцию 2D boids

16

Как вы могли бы запрограммировать симуляцию 2D boids таким образом, чтобы он мог использовать вычислительную мощность из разных источников (кластеров, GPU).

пример boids

В приведенном выше примере неокрашенные частицы перемещаются, пока не сгруппируются (желтые) и не перестанут двигаться.

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

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

Можно ли будет использовать квад-деревья для дальнейшей оптимизации? Любые другие предложения?

Sycren
источник
Вы спрашиваете об оптимизации или как распараллелить? Это разные вещи.
Bummzack
@bummzack Как распараллелить, я только что добавил дополнительное объяснение, это помогает?
Sycren

Ответы:

7

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

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

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

Ларс Виклунд
источник
хорошая статья, но обычная часть этого вопроса, похоже, очень похожа на ответ @Fxlll.
Ali1S232
Я бы сказал, что фактическая часть статьи состоит в том, как она решает крайние случаи, вводя протокол связи, то есть сложная часть, разделение на четыре части довольно очевидно и само по себе не решает проблему крайних случаев.
Майк Земдер
4

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

Если скорость ваших boids равна 1, и они заботятся только о своих соседях, то скорость информации равна 3, то есть boid, который находится на расстоянии двух квадратов от вас, может находиться в пределах диапазона, о котором вы заботитесь, в пределах одного кадра:

1 квадратное движение за бой во взаимодействии (1 + 1) плюс расстояние, на которое вы можете заметить вещи (1), равно 3.

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

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

Если вы хотите запустить массивного параллельного сима, вы разбиваетесь на сетки 10x10, но перекрываете по 5 квадратов на каждом ребре. Всякий раз, когда кто-то из вас оказывается в пределах информационного расстояния от границы локального чанка, вы должны обновить соседа, и как только они пересекают границу, они не принадлежат вам. Если сосед говорит, что бид, которым он управляет, переместился в ваш чанк, вы должны взять на себя его ИИ.

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

Ричард Фабиан
источник
Представьте, что мир - это сетка 1 000 000 x 1 000 000, и в мире есть 10 000 000 бидов, и каждый бид может перемещаться ровно на один квадрат за ход. Можете ли вы объяснить, как проверить, есть ли бое в соседнем соседстве?
Ali1S232
Я предполагаю, что мы могли бы разделить это на 2000 500x500 квадратов или больше. каждый квадрат содержит список boids, а также список соседей. Если boid выходит из квадрата, он удаляется из списка boids и добавляется в другой квадрат. Проблема с этим методом, которую я вижу, заключается в том, что вы добавляете что-то с флокированием, которое больше, чем квадрат. решение quadtree должно быть динамичным, но я не уверен, насколько это будет дорого
Sycren
@Gajet: вам нужно только проверить boids в вашем чанке или соседних управляемых границах. Помните, что граница гарантирована дизайном, чтобы учесть, как далеко может двигаться любая сущность, плюс расстояние, которое могут видеть сущности. @Sycren: стекаются, хотя нам кажется, что это крупная сущность, но это всего лишь небольшой эффект. Стая рыб не следует за школой, они следуют за своими наблюдаемыми соседями.
Ричард Фабиан
2

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

  1. Переместить все бои на одну единицу. (который может быть легко обработан с использованием нескольких потоков)
  2. Назначение каждого boid группе *. Это означает, что используя алгоритм O (n), вы должны выбрать, какие boids наиболее вероятно могут столкнуться. Это также может быть обработано с использованием нескольких потоков.
  3. В конце вы должны проверить, не столкнулись ли два боида в одной группе.

* Для создания групп вы можете использовать шаблон ниже:

введите описание изображения здесь

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

--редактировать--

есть другая идея о сегментации, которая описана в статье @LarsViklund sugested, таким образом, гораздо меньше двойных проверок и нет необходимости увеличивать / уменьшать количество потоков между шагами:

введите описание изображения здесь

Обратите внимание, что некоторые области все еще являются частью двух групп. а ширина зоны покрытия обеих групп точно 2*maximum speed. В вашем случае, если boids перемещается на один пиксель за шаг симуляции, вам нужно всего лишь разделить область шириной в 2 пикселя между двумя группами. и есть небольшая территория, которая входит в 4 группы. но в целом этот метод проще реализовать и намного быстрее, если он реализован правильно. и, кстати, нет обратного хода таким образом, если какой-то объект может двигаться, он может двигаться, больше не требуется проверка.

Ali1S232
источник
Звучит как хорошая идея, но перед тем, как перейти к шагу 1, мне нужно выполнить обнаружение столкновений, чтобы увидеть, могут ли они двигаться, не так ли?
Sycren
Вы можете переместить их, а затем проверить, произошло ли какое-либо столкновение в обратном направлении этого движения (для этого точного boid), если не позволить продолжению симуляции.
Ali1S232
Спасибо, это имеет больше смысла. Помимо четырех деревьев, можете ли вы придумать какой-либо другой способ разделения рабочей нагрузки?
Сыкрен
Как вы можете видеть, мои сегментации не являются полностью четырехугольным деревом, у него есть еще одна дополнительная группа для повышения точности, стиль четырехугольного дерева намного проще в управлении. В зависимости от размера мира вы можете добавить больше групп, что означает меньше проверок в каждом цикле. это компромисс между потреблением памяти и скоростью вычислений. и это не обязательно должен быть один поток для каждой группы. Вы можете иметь несколько потоков для расчета более чем одной группы. Вы также можете разделить группы расчетов между двумя или более потоками.
Ali1S232
@Gajet, если я правильно понимаю вашу картину, было бы много двойных вычислений, так как перекрывающиеся области групп очень велики. Учитывая, что вопрос задают для моделирования до нескольких миллионов точек, это было бы огромной тратой.
Майк Земдер
2

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

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

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

Я рекомендую вам попробовать AD. Это проще всего понять и реализовать. ФД очень похож. Вот симуляция n-тела nVidia с использованием CUDA с использованием FD, которая должна дать вам общее представление о том, как мозаичное построение и сокращение могут помочь значительно превзойти производительность последовательного интерфейса.

Реализации SD, как правило, оптимизируют методы и требуют определенной степени хореографии для реализации. Они почти всегда быстрее и лучше масштабируются.

Это потому, что AD / FD требует построения «списка соседей» для каждого boid. Если каждому бойду необходимо знать положение своих соседей, связь между ними будет O ( n ²). Вы можете использовать списки соседей Verlet, чтобы уменьшить размер области, которую проверяет каждый boid, что позволяет вам перестраивать список каждые несколько шагов вместо каждого шага, но это все равно O ( n ²). В SD каждая ячейка содержит список соседей, тогда как в AD / FD у каждого boid есть список соседей. Таким образом, вместо того, чтобы каждый бид общался друг с другом, каждая клетка общалась друг с другом. Это сокращение в общении, откуда происходит увеличение скорости.

К сожалению, проблема Boids немного саботирует SD. Отслеживание ячейки каждым процессором является наиболее выгодным, когда боиды несколько равномерно распределены по всему региону. Но вы хотите, чтобы boids собирались вместе! Если ваша стая ведет себя должным образом, подавляющее большинство ваших процессоров будут отсчитывать время, обмениваясь пустыми списками, и небольшая группа ячеек в итоге выполнит те же вычисления, что и AD или FD.

Чтобы справиться с этим, вы можете либо математически настроить размер ячеек (который является постоянным), чтобы минимизировать количество пустых ячеек в любой момент времени, либо использовать алгоритм Барнса-Хата для четырех деревьев. Алгоритм ЧД невероятно мощный. Как это ни парадоксально, это очень сложно реализовать на параллельных архитектурах. Это связано с тем, что дерево BH нерегулярно, поэтому параллельные потоки будут проходить по нему с сильно изменяющимися скоростями, что приведет к расхождению потоков. Salmon и Dubinski представили ортогональные рекурсивные алгоритмы деления пополам для равномерного распределения квадродеревьев между процессорами, которые должны быть повторены итеративно для большинства параллельных архитектур.

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

плохая шутка
источник
1

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

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

Здесь есть три проблемы:

  • 1) форма подобласти:

Можно выбрать прямоугольники, но они показывают небольшое отношение площади / периметра по сравнению с вихрями. Чем больше граница, тем больше частиц уйдет. Несмотря на то, что циклы демонстрируют наилучшее соотношение A / p, их нельзя использовать для тесселяции, поэтому вам следует испытать раздражение по поводу некоторой (возможно, полурегулярной) тесселяции с хорошим средним отношением A / p. Очевидно, что вычисление индекса кисточки по координате ячейки должно быть простым, поэтому подумайте об этом, прежде чем попробовать очень экзотическую тасселяцию.

  • 2) протокол связи:

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

  • 3) Распределение подзоны:

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

FXIII
источник
@Fxlll Я не уверен, что вы подразумеваете под тороидальной системой, она не в форме пончика. Вы имеете в виду, что если частица уходит с правой стороны, она снова появляется слева? Если это так, то это не так, если частица попадает в правую сторону, она пытается двигаться в другом направлении.
Sycren
@Sycren хорошо, в этом случае вы должны подумать о тесселяции и особой обработке области на краю
FxIII
-1

Попробуйте мою симуляцию для подсказок https://github.com/wahabjawed/Boids-Simulation

Я разработал это на XNA

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