Otimização não é difícil apenas pelo fato de que tornar um pedaço de código mais rápido seja uma tarefa complicada, mas também por nem sempre ser possível ter oque medir ou mesmo saber como medir.
Nessas duas últimas semanas passei por isso, estou trabalhando em um novo recurso do JIT do mono e tinha que medir qual era o ganho de performance possível. Meu primeiro problema foi encontrar um benchmark que representasse uso real e que fosse significativo o suficiente para os números não ficarem perdidos no meio de muito barulho.
Uma vez que encontrei qual era um bom programa para medir a performance, me deparei com outro problema, o tamanho do working set. CPUs modernas trabalham com até três níveis de caching antes de ir à memória principal. O custo de um acesso a memória pode chegar a uma centena de ciclos, o suficiente para calcular o produto de uma matriz 4×4 por um vetor. Logo não importa o quao significante for o benchmark, se o working set dele não for realístico, o teste é inválido pois tudo executara do cache, bem diferente no mundo real.
Ou seja, é necessário dimensionar e modelar o teste para cada ciclo não utilizar dados que sobraram em cache da execução anterior. Para isso é preciso conhecer o tamanho e a hierarquia de cache do seu processador, mesmo porque isso tem um impacto muito significativo na forma que o código deve ter.
Isso leva ao último desafio que tive de enfrentar, indeterminismo nos resultados do benchmark, a variância dos resultados era grande demais para ser apenas interferência externa, ela chegava a 30% para execuções de de algumas dúzias de segundos. A única diferença eram os endereços de alguns arrays usados extensivamente. Mais precisamente, a discrepância era no alinhamento dos elementos. Nos testes lentos eram múltiplos de 4, nos rápidos eram de 16. Novamente uma peculiaridade dos processadores modernos, que preferem os dados alinhados em endereços múltiplos de 8 ou 16.
Pode até parecer piada, mas o mesmo teste, depois de ajustado todos os detalhes aqui descritos, saiu de um ganho de 10% para 300%. Diferença essa que não é só resultado de um benchmark, mas aplicável ao uso real que esperamos que veja a tenha. Recurso esse que espero integrar ao mono muito em breve.
2 responses so far ↓
1 Henrick Daniel // Sep 29, 2008 at 3:43 pm
Sei como é dificil aqui no mds Ministerio do Desenvolvimento Social consequimos reduzir o tempo de geração de um arquivo de mais de 12 horas para menos de 10 minutos. E não foi facil e o pessoal não da muito valor
2 Henrick Daniel // Sep 29, 2008 at 3:44 pm
Já ia esquecendo parabéns pelo blog ta show!!!
Leave a Comment