Sobrecarga de computação em C# – Usando getters/setters vs.modificando matrizes diretamente e velocidades de conversão

StackOverflow https://stackoverflow.com/questions/3018536

Pergunta

Eu ia escrever um post prolixo, mas vou resumir aqui:

Estou tentando emular o estilo gráfico da velha escola do NES via XNA.Porém, meu FPS está LENTO, tentando modificar 65K pixels por quadro.Se eu apenas percorrer todos os 65K pixels e configurá-los para alguma cor arbitrária, obtenho 64FPS.O código que fiz para procurar quais cores devem ser colocadas e onde, obtenho 1FPS.

Acho que é por causa do meu código orientado a objetos.

No momento, tenho coisas divididas em cerca de seis classes, com getters/setters.Suponho que estou chamando pelo menos getters de 360 ​​mil por quadro, o que considero uma grande sobrecarga.Cada classe contém matrizes 1D ou 2D contendo enumerações personalizadas, bytes int, Color ou Vector2D.

E se eu combinasse todas as classes em apenas uma e acessasse diretamente o conteúdo de cada array?O código pareceria uma bagunça e abandonaria os conceitos de codificação orientada a objetos, mas a velocidade poderia ser muito mais rápida.

Também não estou preocupado com violações de acesso, pois qualquer tentativa de obter/definir os dados nas matrizes será feita em blocos.Por exemplo, toda gravação em arrays ocorrerá antes que qualquer dado seja acessado a partir deles.


Quanto ao casting, afirmei que estou usando enumerações personalizadas, int, Color e Vector2D, bytes. Quais tipos de dados são mais rápidos de usar e acessar no .net Framework, XNA, XBox, C#?Acho que o lançamento constante pode ser a causa da desaceleração aqui.

Além disso, em vez de usar matemática para descobrir em quais índices os dados devem ser colocados, usei tabelas de pesquisa pré-computadas para não precisar usar multiplicação, adição, subtração e divisão constantes por quadro.:)

Foi útil?

Solução

Há uma apresentação incrível do GDC 2008 que vale a pena ler se você for um desenvolvedor XNA.É chamado Compreendendo o desempenho do XNA Framework.

Para sua arquitetura atual - você não a descreveu bem o suficiente para dar uma resposta definitiva - você provavelmente está fazendo muitas "coisas" desnecessárias em um loop apertado.Se eu tivesse que adivinhar, sugeriria que seu método atual está sobrecarregando o cache - você precisa corrigir o layout dos dados.

No caso ideal, você deve ter uma grande variedade de pequenas quantidades possíveis tipos de valor (estruturas, não classes) e um loop fortemente embutido que envia dados para ele linearmente.

(Aparte:sobre o que é rápido:A matemática de números inteiros e de ponto flutuante é muito rápida - em geral, você não deve usar tabelas de pesquisa.As chamadas de função são muito rápidas - a tal ponto que copiar estruturas grandes ao passá-las será mais significativo.O JIT irá incorporar getters e setters simples - embora você não deva depender dele para incorporar qualquer outra coisa em loops muito apertados - como seu blitter.)

NO ENTANTO - mesmo que otimizado - sua arquitetura atual é uma droga.O que você está fazendo vai contra o funcionamento de uma GPU moderna.Você deve carregar seus sprites em sua GPU e deixá-la compor sua cena.

Se você quiser manipular seus sprites em nível de pixel (por exemplo:troca de paletes como você mencionou), então você deve usar pixel shaders.A CPU no 360 (e nos PCs) é rápida, mas a GPU é muito mais rápida quando você faz algo assim!

O Efeitos Sprite A amostra XNA é um bom lugar para começar.

Outras dicas

Você criou o perfil do seu código para determinar onde está a lentidão?Antes de reescrever seu aplicativo, você deve pelo menos saber quais partes precisam ser reescritas.

Suspeito fortemente que a sobrecarga dos acessadores e das conversões de dados seja trivial.É muito mais provável que seus algoritmos estejam fazendo um trabalho desnecessário, recalculando valores que eles poderiam armazenar em cache e outras coisas que podem ser resolvidas sem prejudicar o design do seu objeto.

Você está especificando uma cor para cada pixel ou algo assim?Se for esse o caso, acho que você deveria pensar um pouco mais sobre a arquitetura.Comece a usar sprites que irão acelerar as coisas.

EDITAR

Ok, acho que qual seria a sua solução: carregar vários sprites com cores diferentes (um sprite de alguns pixels) e reutilizá-los.É mais rápido apontar para o mesmo sprite do que atribuir uma cor diferente a cada pixel, pois o sprite já foi carregado na memória

Como acontece com qualquer problema de desempenho, você deve criar um perfil do aplicativo para identificar os gargalos, em vez de tentar adivinhar.Duvido seriamente que getters e setters estejam na raiz do seu problema.O compilador quase sempre incorpora esses tipos de funções.Também estou curioso para saber o que você tem contra a matemática.Multiplicar dois números inteiros, por exemplo, é uma das coisas mais rápidas que um computador pode fazer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top