Preciso de dicas de otimização [RESOLVIDO]

1. Preciso de dicas de otimização [RESOLVIDO]

Samuel Leonardo
SamL

(usa XUbuntu)

Enviado em 08/08/2018 - 05:07h




  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/08/2018 - 14:45h

Algumas ideias:

- Use inline ou macro, em lugar de função comum.

- Experimente passar os parâmetros por referência, em vez de por cópia de valor (pode piorar o desempenho, em vez de melhorar).

- Faça a verificação de colisões em paralelo, usando múltiplos threads.

- Diminua a quantidade de objetos a serem testados.


Você já usou alguma ferramenta de profiling, para saber exatamente onde está a demora?

Como você está armazenando os objetos a serem testados? Num vetor? Numa matriz? Numa árvore? Numa lista? Como está o laço que varre essa estrutura de dados?

3. MELHOR RESPOSTA

Fernando
phoemur

(usa Debian)

Enviado em 08/08/2018 - 21:34h

Colisões são ao mesmo tempo uma das coisas mais complicadas e com a performance mais crítica em um jogo.
Quando você começar a incluir simulação física, múltiplas formas, não apenas detectar a colisão mas aplicar as leis da física e matemática vetorial para calcular o movimento resultante depois das colisões, você vai perceber que talvez seja mais fácil utilizar um Engine já pronto. Uma coisa é fazer um jogo, outra coisa mais complicada é programar um engine do zero...

O que não quer dizer que não seja muito proveitoso saber como as coisas funcionam. Eu mesmo tenho aprendido muito fazendo joguinhos com SDL2 ultimamente. Lembro de ter comentado contigo sobre o meu joguinho breakout um tempo atrás.
Recomendo esse tutorial que já é até de certa forma famoso: http://lazyfoo.net/tutorials/SDL/index.php

Quanto à sua pergunta sobre otimização, assim de pronto eu teria 2 estratégias que podem fazer toda a diferença na sua performance:

Número 1:
Somente aquilo que se moveu pode colidir com alguma coisa. Já o que está parado pode sofrer uma colisão, mas nunca colidir ativamente com algo. De forma que você só precisa checar colisões dos objetos que se moveram contra os outros. Não precisa ser tudo contra tudo todas as vezes.

Desta forma você percebe que dá pra cortar a complexidade do seu algoritmo e fazer menos chamadas de função. Não precisa ser O(n^2). Será muito menos, por exemplo algo assim:


for A in apenas_objetos_que_se_moveram_neste_frame:
for B in todos_os_objetos_da_cena:
if A != B and bounding_box_collision(A, B):
handle_collision(A,B)




Número 2: https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects
Esse método do bounding box é um dos mais eficientes para checar colisões - mesmo não sendo o mais exato para todas as formas.
Contudo mesmo que o objeto tenha se movido, se ele estiver suficientemente longe do outro objeto uma colisão não ocorreu - seria impossível ocorrer.

Por exemplo, se um objeto está em um canto da tela e o outro no outro, ou seja, X vezes mais distantes que seu maior eixo, você pode inferir que uma colisão é impossível.

Você adiciona mais uma checagem na sua função de colisão, porém como a não-colisão é muito mais comum que a colisão em cada frame, você acaba obtendo um ganho de performance.


Tem muito mais coisas que você deve levar em consideração com colisões. É mais complicado do que parece.
Por exemplo, se a velocidade de um objeto for muito alta (um projétil por exemplo), esse objeto em um frame pode estar antes do anteparo em um frame e no outro frame já estar muito depois.
Dessa forma esse tipo de algoritmo de detecção que é baseada na verificação da penetração de um corpo (rigid body) no outro nem sempre vai funcionar.
Isso é o problema da penetração.
Existe uma técina chamada raycasting para resolver esse problema.


Enfim, o que eu lembro agora de cabeça é isso.

Abração.

______________________
https://github.com/phoemur

4. Re: Preciso de dicas de otimização

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/08/2018 - 08:25h

SamL escreveu:

Eu armazendo tudo numa única classe singleton, tipo, são ponteiros, dai eu armazeno os ponteiros num std::map<long int, Entity *> e daí antes de fazer a colisão eu pego todos os objetos que desejo saber se colidem e verifico a colisão, assim:
bool collision ()
{
for (std::string group: touchGroup)


Fazendo desse jeito, você faz com que cópias da string sejam colocadas na variável group a cada iteração. Creio que, tipicamente, a forma usando referências, que por sinal é mais usual, seria preferível, por evitar essa cópia.
for(const auto &group: touchGroup) 


Por curiosidade, essas strings são longas, ou têm tamanhos curtos?

  {
//internamente getAllByGroup usa dois fors para juntar os Entity *
std::vector<Entity *> entities = Elements::getAllByGroup(group);//grupos são nomeados com std::string


Vamos ver aqui. group é string, então, como os seus dados estão num mapa de long para Entity *, a busca usando string terá de varrer todos os elementos do mapa, ou você tem algum outro mapeamento de string para long?

    for (Entity * entity: entities)
{
if (boundingbox(entity->getCollRect(), this->getCollRect()))
return true;
}
return false;
}
return false;
}


Uma dúvida: ao testar colisões, você checa o par de objetos A e B apenas uma vez, ou trata de modo distinto (intencionalmente ou sem querer) as combinações (A,B) e (B,A)?


(Em outra mensagem)

Eu vi aqui que estou alocando muito std::vector<Vect>, vou ver o que posso fazer para reaproveitar o que estiver já usado.


Isso pode ser um problema se esses vetores implicarem muitas cópias de valores de um lugar para outro. Além disso, você deve considerar se aloca o vetor de só vez (ou reserva espaço no momento da criação), porque sabe de antemão a quantidade de elementos que ele tem de ter, ou se essa quantidade é determinada ao longo do processo de preenchimentos dos elementos. Se a colocação de elementos no vetor e o posterior uso desses elementos for primariamente sequencial, pode ser que faça mais sentido usar listas. Se for híbrido, pode ser que std::deque seja mais indicado.

Às vezes, o simples fato de usar a estrutura de dados certa e da forma certa pode trazer grandes ganhos de desempenho.


5. Re: Preciso de dicas de otimização

Fernando
phoemur

(usa Debian)

Enviado em 10/08/2018 - 21:01h

Quantas colisões geralmente ocorrem no seu programa ?

Digo isso porque alguma coisa parece estar errada.
Por exemplo aqui nesse meu programinha http://github.com/phoemur/collision_model/

Existem 200 bolinhas checando colisões em cada frame, a 60 FPS dá 12.000 checagens de colisões por segundo...
Não apenas a checagem da colisão mas também o cálculo vetorial da trajetória resultante....
Não tem nenhuma otimização...

E mesmo assim não passa de 15% de uso de apenas um core da CPU... (aqui core i3 segunda geração)
Dá uma olhada pra vc ver.

*Obs.: eu utilizo uma forma bastante semelhante que os seus Entity*, uso um
static std::set<Ball*>
Só que ao invés de estar em um singleton, é um membro estático da própria classe, porém não faz muita diferença...


Acho que pra ter mais sugestões teria que disponibilizar o código.

Abração.

______________________
https://github.com/phoemur


6. Re: Preciso de dicas de otimização

Fernando
phoemur

(usa Debian)

Enviado em 10/08/2018 - 21:10h

Você já considerou trocar um vetor de estruturas por uma estrutura com vetores, assim diminuindo Cache Misses ?

Tipo assim: https://en.wikipedia.org/wiki/AOS_and_SOA#Example
______________________
https://github.com/phoemur






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts