Вопрос

Я работаю над игрой RTS на C++, ориентированной на портативное оборудование (Pandora).Для справки: Pandora имеет один процессор ARM с частотой ~600 МГц и работает под управлением Linux.Мы пытаемся создать хорошую систему передачи сообщений (как внутреннюю, так и внешнюю), и для меня это новая территория.

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

sendMessage("model-loader", "load-model", my_model.path, model_id );

Взамен модуль может ожидать какого-то сообщения, содержащего объект модели для конкретного model_id, который затем может быть передан в графическую систему.Обратите внимание, что эта функция sendMessage ни в коем случае не является окончательной.Это просто отражает мое нынешнее понимание систем передачи сообщений, что, вероятно, неверно :)

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

Другой вариант — полностью перейти на сетевой уровень.У этого есть несколько интересных преимуществ, например, возможность асинхронной передачи сообщений практически бесплатно.Кроме того, мы получаем возможность передавать сообщения на другие машины, используя те же вызовы, что и при передаче локально.Однако это решение сбивает меня с толку, вероятно, потому, что я не до конца его понимаю :) Нужен ли нам сокет для каждого объекта, который будет отправлять/получать сообщения?Если так, то это кажется чрезмерным.В данной игре будут тысячи объектов.Боюсь, что для такого недостаточно мощного устройства, как Pandora, такое злоупотребление сетью может стать нашим узким местом.Но я еще не проводил никаких тестов, так что это всего лишь предположение.

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

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

Это было полезно?

Решение

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

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

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

Если вы хотите действительно эффективную передачу сообщений, посмотрите на некоторые микроядра L4 с открытым исходным кодом. Эти ребята тратят много времени на быструю передачу сообщений.

Другие советы

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

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

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

Я согласен с рекомендацией Зана по возможности передавать сообщения в память.

Одна из причин заключается в том, что вы можете передавать сложные объекты C++ без необходимости их маршалинга и демаршалинга (сериализации и десериализации).

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top