Я пытаюсь создать физический движок для пользовательского игрового движка. На данный момент все работает нормально, однако у меня возникают некоторые проблемы с производительностью, когда движку приходится иметь дело примерно с 4000 физическими телами. Я совершенно уверен, что это не вина движка рендеринга, поскольку он использует инстансный рендеринг для эффектов частиц (ведьма, который я сейчас тестирую) и может обрабатывать около 200 тысяч частиц, если они все статичны.
до сих пор, как только все столкновения были разрешены, я обновляю все физические тела в сцене, применяя силу гравитации и перемещая тела по их скорости.
функция выглядит так:
void mint::physics::PhysicsEngine::SymplecticEuler(mint::physics::PhysicsBody* body)
{
mint::graphics::Entity *entity = body->GetEntity();
// -- Symplectic Euler
glm::vec2 gravity = glm::vec2(0.0f, (1.0f / core::Timer::Instance()->DeltaTime()) * 9.81f) * body->GravityScale();
glm::vec2 dv = (body->Force() * body->GetMassData()->inv_mass + gravity * core::Timer::Instance()->DeltaTime());
body->Velocity(body->Velocity() + dv);
glm::vec2 dxy = glm::vec2(body->Velocity() * core::Timer::Instance()->DeltaTime());
entity->Translate(glm::vec3(dxy, 0.0f));
// -- END -- Symplectic Euler
// -- update the collider
body->UpdateCollider();
// -- END -- update the collider
}
эта функция будет запускаться один раз для каждого физического тела и вызывается в цикле for, например так
auto start = std::chrono::high_resolution_clock::now();
for (auto body : all_bodys)
{
//SymplecticEuler(body);
// -- using std::async
fEulerFutures.push_back(std::async(std::launch::async, SymplecticEuler, body));
//SymplecticEuler(body);
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> duration = end - start;
std::cout << "physics update took: " << duration.count() << std::endl;
я использую std::chrono, чтобы увидеть, как долго выполняется обновление, и у меня есть два разных способа реализовать это, один — просто вызвать SymplecticEuler(body)
, а другой — использовать std::async и будущее, которое возвращается из функции хранится в векторе-члене класса физического движка, который очищается после каждого обновления.
используя код синхронизации, который я написал, последовательный цикл занял 0,00014 с, а многопоточный цикл - 0,005 с. Я бы не ожидал, что многопоточный цикл займет больше времени, чем последовательный цикл, но это произошло, поэтому я предполагаю, что либо использую std::async неправильно, либо использую его в неправильном контексте. Программа, в которой я это запускаю, запускает простую симуляцию частиц с 300 частицами, так что пока ничего особенного.
Может кто-нибудь, дайте мне знать, правильно ли я использую std::async, потому что я все еще очень плохо знаком с концепцией многопоточности, или если я использую слишком много потоков, чтобы замедлить производительность движка, или я должен вместо этого использовать вычислительные шейдеры многопоточности (если использование вычислительных шейдеров улучшит производительность движка, пожалуйста, оставьте несколько ссылок на руководства по использованию вычислительных шейдеров в современном openGL с C++)
обе эти функции являются членами класса физического движка, а функция SymplecticEuler()
является статической функцией.
Спасибо
fEulerFutures.reserve(all_bodys.size())
? - person Ted Lyngmo   schedule 21.04.2020std::for_each(std::execution::par, all_bodys.begin(), all_bodys.end(), [](auto body) { SymplecticEuler(body); });
- person Ted Lyngmo   schedule 21.04.2020