TDC2013 Otimizando-C

Post on 18-Dec-2014

126 views 0 download

description

Apresentação no TDC2013 - Florianópolis da trilha Mobile e Embedded (25/05/2013). Apresenta algumas dicas, técnicas e sugestões de como melhorar o processamento e uso de memória no código.

Transcript of TDC2013 Otimizando-C

Globalcode – Open4education

Otimizando-C

Globalcode – Open4education

Sumário

whoami

Otimização?! WTF!?

#define X const

Aritmética

Condições

Laços

Globalcode – Open4education

Sumário (2)

Alocação

Parâmetros

rand()

Fronteira final

Bora otimizar então! #sqn

Globalcode – Open4education

whoami

Osmar da Cunha FilhoFormado em Engenharia de Computação (UNIVALI)

Pós-graduado em Desenvolvimento de Produtos Eletrônicos (IFSC)

Coordenador de desenvolvimento de Hardware (Specto)

Professor nos cursos de Ciências da Computação (IES) e Engenharia Civil (IES)

Globalcode – Open4education

Otimização!? WTF!?Otimizar

v.t.d. Ocasionar circunstâncias mais proveitosas para; retirar o que há de melhor em; aprimorar, melhorar: otimizar o desenvolvimento do produto; otimizar as condições de trabalho.

Dar a (algo, uma máquina, uma empresa) um rendimento ótimo, criando-lhe as condições mais favoráveis ou tirando (dele ou dela) o melhor partido possível; tornar (algo) ótimo ou ideal.

Estatística. Instituir o maior valor de uma grandeza.

Informática. Aperfeiçoar um programa para que o mesmo seja melhor utilizado ou funcione mais rapidamente.

Fonte: http://www.dicio.com.br/otimizar/

Globalcode – Open4education

Otimização!? WTF!?

Melhorar performance

Diminuir consumo de recursosTempo

ProcessamentoEspaço

Memória

Globalcode – Open4education

Otimização!? WTF!?

TradeoffProcessamento

Memória

Legibilidade

Complexidade

Globalcode – Open4education

#define X const

Macros (#define) são resolvidas em tempo de compilação

Consts NEM SEMPRE são resolvidas em tempo de compilação

Alguns compiladores as traduzem para #defines

#defines são substituídas à medida que o código vai sendo lido pelo compilador

Consts geram código e consomem memória de programa

Globalcode – Open4education

AritméticaMultiplicação/Divisão

Potência de dois2, 4, 8, 16, 32, 64, 128, 256

21, 22, 23, 24, 25, 26, 27, 28

Multiplicações/Divisões por potências de dois são rotações de bits

Rotações de bits são operações lógicas!

Operações lógicas são mais rápidas que aritméticas porque não possuem sinal!

Globalcode – Open4education

AritméticaMultiplicação/Divisão

Multiplicaçãox << 1

x << 2

x << 3

x << 4

Divisãox >> 1

x >> 2

x >> 3

x >> 4

x * 21

x * 22

x * 23

x * 24

x / 21

x / 22

x / 23

x / 24

Globalcode – Open4education

CondiçõesCurto-circuito

Curto-circuito ou avaliação preguiçosa (lazy evaluation)

Sempre em um if de múltiplas condições simultâneas, colocar a condição mais fácil de ser testada antes, de forma que as condições seguintes nem cheguem a ser testadas

A ideia é sair o quanto antes

Globalcode – Open4education

CondiçõesCurto-circuito

if ( a < 0 && funcaoQueCalcula() > 10)

if ( !b && j > 10)

Globalcode – Open4education

CondiçõesEliminar “senão”

Pode ser menos custoso executar uma operação e desfazê-la com próprio if

Elimina algumas instruções referentes ao um salto condicional

Globalcode – Open4education

CondiçõesEliminar “senão”// Exemplo antesif (condicao) { executaCasoSe();}else { executaCasoSenao();}

// Exemplo depoisexecutaCasoSenao();if (condicao) { desfazCasoSenao(); executaCasoSe()}

// Exemplo antesif (condicao) { variavel = 0;}else { variavel++;}

// Exemplo depoisvariavel++;if (condicao) { variavel = 0;

}

Globalcode – Open4education

LaçosLoop jamming

Loop jamming

Agrupar códigos que irão repetir em um laço só

Principalmente se forem repetidas pela mesma quantidade de vezes

Globalcode – Open4education

LaçosLoop jamming// Exemplo antesfor ( i = 0; i < 100; i++ ){ fazAlgo();}

for ( i = 0; i < 100; i++ ){ fazOutraCoisa();}

// Exemplo depoisfor (i = 0; i < 100; i++ ){ fazAlgo(); fazOutraCoisa();}

Globalcode – Open4education

Laços++ X --

Em vez de contadores progressivos até o limite máximo, utilizar contadores regressivos terminando em zero

Algumas arquiteturas possuem instruções que testam condição de zero após decrementar

Globalcode – Open4education

Laços++ X --// Incremementandofor ( i = 0; i < 100 ; i++)

// O laco tem que comparar com um valor != 0i – 100 == 0 ?i++ e continua

// Decrementandofor ( i = 100; i-- ; )

// O laco tem que testar uma flag de zero da ULAi == 0 ?i-- e continua

Globalcode – Open4education

Para não chamar a mesma função inúmeras vezes, passando como parâmetro um contador, criar uma função com o contador internamente

LaçosContador como parâmetro

// Calcula passando parametro i (antes)for (i = 0; i < 100; i++) { calcula(x,i); }

// Modificando a funcao para calcular dentro do laco (depois)void calcula (x) { for(i = 0; i < 100; i++) { //calcula no laço }}

Globalcode – Open4education

LaçosFim

O laço precisa mesmo ir até o final?

Ele pode sair antes e retornar o valor?

Por exemplo em uma pesquisa de elementos!

for (i = 0 ; i < 100 ; i++ ) { if (arrayExemplo[i] == 100 ) { encontrado = i; break; }}

Globalcode – Open4education

LaçosLoop unrolling

Desenrolar laços de poucas repetições

O compilador não precisa definir a estrutura para repetição nem calcular índices

// Antesfor ( i = 0 ; i < 3; i++ ) { arrayExemplo[i] = 2*i;}

// DepoisarrayExemplo[0] = 0;arrayExemplo[1] = 2;arrayExemplo[2] = 4;

Globalcode – Open4education

LaçosIterativo X Recursivo

Preferir algoritmos iterativos a recursivosPode causar estouro de pilha

Aumenta a passagem de parâmetros

Cuidado ao chamar funções no tratamento de interrupções!

Globalcode – Open4education

AlocaçãoLocal X Global

O compilador pode alocar variáveis locais diretamente em registrador ou na pilha

Variáveis globais vão para a memória (RAM) e por isso pode ser necessário mais bytes de endereço para acessá-la

Globalcode – Open4education

AlocaçãoTipos de dados - Tamanho

Utilizar o tipo mais adequado ao problemachar, int, long?

float, double?

Operações com ponto flutuante demoram mais que operações em tipos inteiros

Consultar a unidade de ponto flutuante (FPU)!

Globalcode – Open4education

AlocaçãoTamanho

Na dúvida, use a bitagem da arquitetura!

Em PCs x86, int é mais rápido que char e shortChar e short precisam ser reduzidos!

Int é padrão da arquitetura (seja ela 32 ou 64 bits)!

Em microcontroladores 8 bits, char é mais rápidoUnsigned char é mais rápido ainda

Globalcode – Open4education

Alocaçãosigned X unsigned

Tipos sem sinal são mais rápidosunsigned char, unsigned int, unsigned long

Tipos com sinal passam por circuitos a mais na ULA para estender o sinal

Número sem sinal: bit mais significativo é zero

Número com sinal: bit mais significativo é um

Globalcode – Open4education

(Extensão de sinal)

Complemento de dois

-1281000 0000

-641100 0000

+640011 1111

+1270111 1111

2551111 1111

1270111 1111

630011 1111

310001 1111

Globalcode – Open4education

AlocaçãoInicialização X Atribuição

É preferível inicializar já com o valor do que apenas declarar e inicializar depois

Ao inicializar na declaração, não há dois distintos momentos (alocação e atribuição), ao alocar o compilador já atribui o valor!

Globalcode – Open4education

AlocaçãoInicialização X Atribuição// InicializacaoTipo variavel = valor;

// Declaracao e atribuicaoTipo variavel;...variavel = valor;

Globalcode – Open4education

AlocaçãoArrays X Ponteiros

Em vez de usar arrays e índices, utilizar ponteiros!

Utilizando arrays, para acessar o índice nLer o endereço base do array

Ler n

Somar endereço base com n

Acessar o endereço calculado

Globalcode – Open4education

AlocaçãoArrays X Ponteiros

Usando ponteiros:Apontar o ponteiro para o início do array

Somar o índice ao ponteiroAritmética de ponteiros! :D

Recalcular os índices deixa de ser repetida a cada iteração

Para varrer listas (uso comum), o ponteiro é incrementado em somente uma unidade (INC)

Globalcode – Open4education

AlocaçãoArrays X Ponteiros// Antesint arrayTeste[100];

for (i = 0; i < 100; i++){ arrayTeste[i] = 0;}

// Depoisint arrayTeste[100];int *ponteiroArray;

ponteiroArray = &arrayTeste[0];

for (i = 0; i < 100; i++) { *ponteiroArray = 0; ponteiroArray++;}

Globalcode – Open4education

AlocaçãoArrays multidimensionais

Localidade de referênciaValor ou local de armazenamento frequentemente acessado

Localidade de referência espacialLocais de armazenamento próximos

Arrays multidmensionais serão alocados em uma memória unidimensional

Globalcode – Open4education

AlocaçãoArrays multidimensionais

Atenção à ordem dos índices!

Acessar: arrayTeste [ i ][ j ]

arrayTeste [ i ] [ j + 1]é melhor que:

arrayTeste [ i + 1 ] [ j ]

Globalcode – Open4education

AlocaçãoAlinhamento (padding)

// Cabe em 20 bytes:struct exemplo { int a; char b; int c; char d; int e;}

// Cabe em 16 bytes:struct exemplo { int a; int c; int e; char b; char d;}

Alinhar o tipo a potências de 2!

Globalcode – Open4education

AlocaçãoCampos de bits (bitfields)

Para otimizar uso de memória para armazenar um valor booleano, pode-se utilizar campos de bits

struct campoDeBits { unsigned bit0: 1; unsigned bit1: 1; unsigned bit2: 1; unsigned bit3: 1; unsigned bit4: 1; unsigned bit5: 1; unsigned bit6: 1; unsigned bit7: 1;}

Globalcode – Open4education

AlocaçãoCampos de bits (bitfields)

Alguns cuidados com os campos de bits:Os bits não são endereçáveis diretamente (pelo operador &), somente pela struct (no exemplo, campoDeBits.bit0)

Custa mais processamento ler um bit do que um unsigned char

Exige operações de teste bit a bit

Globalcode – Open4education

Parâmetros

Dependendo da arquitetura, os primeiros parâmetros (4 para x86) são passados por registradores

Os parâmetros seguintes são passados pela pilha

Ou seja, além do quarto parâmetro, custa ainda mais acessar os parâmetros

Operações de acesso à pilha

Globalcode – Open4education

Parâmetros

É preferível passar structs por referência em vez de por valor

Assim não há a cópia da struct toda para registradores/pilha

Globalcode – Open4education

Parâmetros

Diminuir a quantidade de parâmetros utilizando variáveis globais

Muitas funções precisando de um mesmo dado

Evita estouros de pilha!

Globalcode – Open4education

Parâmetros

Utilizar referência em vez de ponteirosReferências nunca são NULL

Código mais limpo (sem inúmeros *)

Globalcode – Open4education

rand()F**K OPTIMIZING

Quando não se quer que o compilador otimize uma variável, basta declará-la como volatile

volatile unsigned char variavel;

Útil em casos que a variável é compartilhadaInterrupções

Timers

Threads

Globalcode – Open4education

rand()Isso está otimiza(n)do?

Conferir o código gerado

Assembly listing

Arquivos intermediários de compilação.MAP

.LST

.S

Globalcode – Open4education

Fronteira final!?

Otimização pelo compilador

Análise de algoritmo (big-O)

Buscar outros algoritmos

Otimizar em Assembly.

Globalcode – Open4education

Bora otimizar, então! #sqn

Não adianta otimizar o que ESTÁ ERRADO!

Primeiro preocupar-se com a corretude

Garantir a legibilidade do código

É tão necessário transformar tudo em ponteiros em #defines?

Globalcode – Open4education

Bora otimizar, então! #sqn

Donald Knuthpremature optimization is the root of all evil

Tio BenWith great powers come great responsabilities

Globalcode – Open4education

Perguntas?

Dúvidas?

Reclamações?

Sugestões?

Questões existenciais?

Globalcode – Open4education

Osmar da Cunha Filho

@oooosmar (4 letras “o”)

Globalcode – Open4education

Obrigado!

:D