Многопоточный доменный дизайн C # - PullRequest
0 голосов
/ 07 апреля 2010

Допустим, у меня есть модель предметной области, которую я пытаюсь сделать совместимой с многопоточностью. Домен-прототип - это игровой домен, состоящий из объектов Space, SpaceObject и Location. У SpaceObject есть метод Move, а Asteroid и Ship расширяют этот объект определенными свойствами для этого объекта (у Ship есть имя, а у Asteroid есть цвет)

Допустим, я хочу, чтобы метод Move для каждого объекта выполнялся в отдельном потоке. Это было бы глупо, потому что с 10000 объектами у меня было бы 10000 потоков. Как лучше всего разделить рабочую нагрузку между ядрами / потоками?

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

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

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

Кто-нибудь знает, что здесь делать?

Спецификация реакции на Deltreme:

Вы абсолютно правы, и ваш метод будет работать в большинстве случаев. НО, Потоки должны обновить местоположение космического объекта в классе Space.

Допустим, у меня есть 2 космических объекта рядом друг с другом, они движутся в направлении друг друга. 1 Объект находится в потоке A, другой находится в потоке B. Как только я обновляю объекты, потоки должны записать в пространство вместе, чтобы записать новые значения в плитку (отдельную часть пространства). Этот индивидуальный вызов не может быть выполнен одновременно в разных потоках, потому что объект Space может разорваться ...

То, что могло бы произойти, - это столкновение, и я мог бы написать Событие, которое происходит, если их 2 корабля при 1 плитке. Это не проблема.

Я думаю, что в случае 10000 кораблей ЦП будет в основном переключаться между потоками, а не запускать их все вместе. Так что в интересах исполнения я хочу, чтобы "все" было одновременно

Ответы [ 3 ]

1 голос
/ 07 апреля 2010

Вы можете использовать System.Threading.ThreadPool или будущую параллельную библиотеку задач для автоматического управления количеством потоков в соответствии с количеством доступных ядер.

Один из возможных подходов к проблеме параллелизма заключается в блокировке только других объектов SpaceObject, с которыми может взаимодействовать ваш текущий объект SpaceObject. Это обеспечит адекватную производительность в большинстве случаев, но в худшем случае обработка больших взаимодействий будет выполняться одним потоком. Сколько вам нужно заблокировать, в конечном итоге зависит от ваших параметров симуляции. Если объекты не могут полностью пройти друг через друга в течение одного тика, вы можете просто проверить наличие перекрывающихся объектов. Для быстро движущихся объектов вам необходимо обнаружить пересекающиеся векторы движения.

0 голосов
/ 07 апреля 2010

Как говорит Hirvox, ThreadPool - хороший выбор. Я бы избегал думать с точки зрения потока для каждого SpaceObject, а скорее думать о нем как о большой очереди SpaceObject-ов, которые должны обновлять свою позицию на некотором интервале, а затем использовать потоки для выполнения перемещения Move при перемещении по очереди объекты; это хорошо подходит для ThreadPool. Это может быть не фактическая очередь, а отсортированный словарь, но вы поняли.

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

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

0 голосов
/ 07 апреля 2010

Я предполагаю, что вы создаете моментальные снимки: в Ситуации A каждый SpaceObject расположен в некотором Местоположении, и после того, как каждый SpaceObject Переместился в другое Местоположение, вы попадаете в Ситуацию B.

При наличии 10000 объектов переход между ситуацией A и B составляет 10000 вызовов Move. Move () звучит как довольно быстрый метод, т.е. используя текущее местоположение и направление для создания нового местоположения.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...