Logo Hardware.com.br
GBastos
GBastos Super Participante Registrado
777 Mensagens 4 Curtidas

C - Comparar tempo de processamento de trocas e comparações

#1 Por GBastos 21/07/2006 - 17:27
E aí, pessoal!

Estou às voltas com minha monografia de final de curso que é otimização de shell sort utilizando algoritmos genéticos.
A questão é que para comparar a performance do que irei desenvolver com outros já existentes é necessária alguma medida de comparação o mais exata possível. Assim, resolvi que a medida seria o número de trocas e comparações efetuadas no vetor.
O problema é: todo mundo sabe que uma comparação de elementos é bem mais rápida que uma troca, mas quanto mais rápida? E o quanto essa relação muda de uma arquitetura para outra (processadores com tamanhos de cache diferentes, quantidade de memória, etc?)?
Assim, estou querendo desenvolver um programinha em C que efetue alguns bilhões de comparações e trocas de elementos e calcule proporcionalmente quanto cada um gasta de tempo de processamento. Como um exemplo, um professor meu disse que uma vez, empiricamente (pra não dizer no chute big_green.png ), tinha usado a proporção de 3:1 e acabou verificando que é algo muito próximo disso.

Mas, resumindo, como meu C está um pouco enferrujado, gostaria de dicas do pessoal mais experiente em C sobre como implementar essa comparação, artigos abordando essa questão (tentei pesquisar no google, mas não achei nada) ou qualquer coisa que possa ajudar.

Abraço!
jqueiroz
jqueiroz Cyber Highlander Registrado
104K Mensagens 5.7K Curtidas
#2 Por jqueiroz
21/07/2006 - 18:59
Assim de cabeça, lembro de haver uma opção chamada "profiling". No tempo em que eu estava fazendo a minha monografia, isso era acionado com a opção "-g" do GCC.

Com isso, o programa ao ser executado gerava um arquivo registrando cada passagem por cada função/procedimento. Esse arquivo depois podia ser analisado, e gerar estatísticas do tipo "percentual do tempo gasto na função processa_risco()". A idéia disso seria identificar as rotinas mais lentas, ou que eram mais chamadas, e assim poder concentrar o esforço onde ele seria mais efetivo...

Talvez sirva pra você; boa sorte.
"chmod 777 nunca ajudou ninguém" (c) 2002-2021 JQueiroz/FGdH
Conheça o Blog do Zekke
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas
#3 Por peczenyj
21/07/2006 - 22:50
-g gera os simbolos necessários pra vc conseguir debugar usando o gdb ou ddd. sera q vc não quer usar, na verdade

   -fprofile-values
If combined with -fprofile-arcs, it adds code so that some data
about values of expressions in the program is gathered.

With -fbranch-probabilities, it reads back the data gathered from
profiling values of expressions and adds REG_VALUE_PROFILE notes to
instructions for their later usage in optimizations.
GBastos
GBastos Super Participante Registrado
777 Mensagens 4 Curtidas
#4 Por GBastos
22/07/2006 - 04:28
Interessante, não sabia dessa característica de profile do GCC, valeu. Mas ele gera somente percentual ou tempo e clocks também?
De qualquer forma, essa otimização terá que ser feita em diversas arquiteturas e ambientes, então vou ter que desenvolver um programa que faça essa análise. Ou seja, posso usar o GCC pra validar o que eu fizer em minha máquina (o que é uma grande ajuda), mas vai ter que rodar em outros ambientes.
Assim, eu queria saber como avaliar? Para avaliar comparações basta botar uma comparação que nunca ocorra como if 1 > 2 ou seria necessário uso de variáveis mesmo (if x > y)? E para troca, bastaria um x = y independente do conteúdo das variáveis?
E o que acham melhor avaliar? Clocks ou tempo? Comecei a trabalhar com tempo mas encontrei alguns problemas: Como trabalhar com grandes repetições (bilhões a trilhões)? Usando vários for aninhados ou apenas um ou dois com unsigned long? Fiz um código bem simples pra testar isso, mas o tempo calculado não é real..
Ever tried. Ever failed. No matter. Try again. Fail again. Fail better.
GBastos
GBastos Super Participante Registrado
777 Mensagens 4 Curtidas
#5 Por GBastos
23/07/2006 - 09:57
O programa que fiz:


unsigned long i, quant;
int x, y;
time_t inicio, fim, tempo_comp[10], tempo_troca[10];
quant = 7000000;
while(x < 10)
{
inicio = time(NULL);
i = 0;
while (i < quant)
{
if (quant < i) quant = i;
i++;
}
fim = time(NULL);
tempo_comp[x] = fim - inicio;
inicio = time(NULL);
i = 0;
while (i < quant)
{
x = y;
i++;
}
fim = time(NULL);
tempo_troca[x] = fim - inicio;
x++;
quant = quant * 2;
}


A questão é que o tempo gasto não condiz com o esperado. Enquanto a relação esperada era de 3 para 1 (pelo menos de acordo com meu orientador, segundo ele com base em alguns trabalhos com algoritmos genéticos), está menos de 2 para 1.

Os tempos estão saindo:

Quantidade - Temp. Comparações - Temp. Trocas
280.000.000 4 6
560.000.000 9 12
1.120.000.000 17 25
2.240.000.000 33 55
4.480.000.000 71 105
8.960.000.000 133 199


O que pode explicar isso? O fato de que so estou avaliado o processador e não a memória? Ou algum erro no código?
Ever tried. Ever failed. No matter. Try again. Fail again. Fail better.
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas
#7 Por peczenyj
26/07/2006 - 00:51
fiz a minha versão pra entender o que vc está tentando fazer. a principio os valores são muito semelhantes. Acho que vc deveria tentar fazer uma estatistica desses dados. leve em conta q a CPU pode fazer alguma coisa durante a execução do programa q atrapalhe um pouco. Outra coisa q vc deve pensar é que tipo de otimização o seu compilador faz. As CPUs atuais são dotadas de 'previsão de desvio', pro seu exemplo pode funcionar de um jeito, pro seu programa pode funcionar de outro.

#include<time.h>
#include<stdio.h>
#define TAXA 2
#define MAX 7000000
#define QTD 10
int main(){
unsigned long int i,j,x,max;
time_t inicio, meio, fim;

printf("Qtde\tComp.\tTroca\n&quot;
for(i=0,max=MAX;i<QTD;i++,max *= TAXA){

inicio = time(NULL);

for(j=0;j < max;j++)
if(max < j) x = max;

meio = time(NULL);

for(j=0;j < max;j++)
x = max;

fim = time(NULL);

printf("%lu\t%ld\t%ld\n",max,((int)meio - inicio),((int)fim-meio));
}

return 0;
}


resultados:

$ gcc -Wall teste.c

$ ./a.exe
Qtde Comp. Troca
7000000 0 0
14000000 0 0
28000000 0 0
56000000 0 1
112000000 0 1
224000000 1 1
448000000 2 2
896000000 4 5
1792000000 9 7
3584000000 18 14

$ gcc -Wall -O4 teste.c

$ ./a.exe
Qtde Comp. Troca
7000000 0 0
14000000 0 0
28000000 0 0
56000000 0 0
112000000 1 0
224000000 0 0
448000000 1 1
896000000 1 2
1792000000 3 3
3584000000 6 6

Perceba que usando o fator maximo de optimização, eu obtenho tempos bem menores. leve em conta a arquitetura e o seu compilador. eu obtive resultados diferentes usando o gcc e o g++ , possivelmente com o i++ da intel, bem optimizado, vire um avião (o g++ não gera codigo bem optimizado e sim codigo bem portavel).

Pense também em fazer em Fortran, se pegar um bom compilador nativo podes ter algumas surpresas! Eu fiz um programa para calculo numérico em Fortran 77 que dava um banho na versão C (4 vezes mais rapido no pior caso). Se bem que o ideial é vc fazer um programa que funcione, em uma linguagem que vc tenha razoavel domínio, com bons algoritmos, em um computador com muita ram e processador com Ghz de clock.

De repente o seu problema pode ser paralelizavel (!!) ai vc pode bolar alguma coisa. Precisarás de um Cluster para isso - na internet tem tutoriais para montar, não é dificil só precisa de varias maquinas e placas de rede bem rapidas.

No mais, vc tem que fazer uma analise algoritmica do seu problema. É um algoritmo de N^2 ? N^1/3 ? 2*N?

boa sorte
tetim
tetim Membro Senior Registrado
366 Mensagens 1 Curtida
#10 Por tetim
26/07/2006 - 12:08
peczenyj
Sim. E usando windows 2000 :mrgreen:


Hmmm.... legal big_green.png

Fiz uns testes aqui, e os tempos também foram muito próximos
não de 3:1 e sim de ~ Temp_troca = Temp_cmp + Temp_cmp /3
E outra coisa interessante que eu percebi também foi que mudando
o tipo de quant(para int e unsigned long menor tempo ou long long foi
o maior tempo), o tempo também será alterado, imaginei que seria pelo
motivo de alocação de memória(unsigned int = unsigned long = 4Bytes e
long long = 8Bytes), por ser maior, o tempo de deslocamento também será.
Ah... devcpp e winXP deram esses tamanhos.

Apropósito, no primerio laço, não deveria ser apenas comparação?
E não comparação e troca?(foi o que fiz para dar o tempo acima)

E penso que esse calculo não está certo, pois independente não diria
de SO, mas de poder de processamento e memória, o tempo de comparação deveria ser relativamente proporcional maior que tempo de
troca, e isso não está acontecendo.

O mesmo código do peczenyj, no winXp com devcpp

Qtde Comp. Troca
7000000 0 0
14000000 0 0
28000000 0 0
56000000 1 0
112000000 0 1
224000000 0 1
448000000 2 2
896000000 3 3
1792000000 7 7
3584000000 14 14


Me corrijam se falei besteira... hehe :?
"Conseguirão parar uma, duas ou até tres flores, mas nunca conseguirão segurar a força de uma primavera..."[Chê Guevara]
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas
#11 Por peczenyj
26/07/2006 - 12:57
Apropósito, no primerio laço, não deveria ser apenas comparação?
E não comparação e troca?(foi o que fiz para dar o tempo acima)


Aquele if dá sempre falso, nunca fará uma troca. Mas como eu disse dependendo do problema o compilador pode otimizar o codigo de uma certa maneira que nem sempre oferece o que precisamos mas... não acho que a diferença seja tão absurda assim. E se vc executar varias vezes vai ver que os valores alteram-se um pouco. o ideal seria fazer laços bem longos e ver como se compara com algo q leve minutos.

Seria mais interessante elaborar 2 programas, um usando comparações e o outro trocar e testa-los próximo das condições normais de uso (dentro do algoritmo genético). De repente às opções de optimização do compilador podem eliminar boa parte das diferenças. No mais é fazer um código legivel.
GBastos
GBastos Super Participante Registrado
777 Mensagens 4 Curtidas
#12 Por GBastos
27/07/2006 - 22:18
Obrigado a todos, suas opiniões me deram muitas idéias.
Eu pensei nessa idéia de fazer em outra linguagem para comparar. Fortran é uma boa, mas há anos não mexo.

tetim, foi mais ou menos essa a proporção que consegui também. Mas não parece correta.

Quanto ao if, é isso que o peczenyj falou mesmo, mas botei por não imaginar outra forma. Mas, agora que vc disse, talvez fosse melhor testar com x = (max < j) e x = (x = y), não? Pelo menos a estrutura dos dois procedimentos ficaria mais similar, portanto talvez mais fiel..
Achei também que poderia ser pelo fato da memória não ser muito requisitada, entao pensei em usar vetores muito grandes para forçar a paginaçao, mas não sei como fazer isso em C.

E, se vcs nao se incomodarem, posso até colocar estes tempos, só teria que saber qual a máquina de vcs.

peczenyj, na verdade o problema é otimização do shell sort, que tem performance média de N^3/2, limite superior N^2, e o algoritmo genético seria para conseguir uma sequência de incrementos com uma performance melhor que essa, quem sabe perto do N log N do quick sort. Então essa questão de avaliar a diferença de "peso" computacional entre comparações e trocas seria para passar essa informação ao algoritmo genético que levaria isso em conta quando fosse verificar a aptidão dos organismos.
Ever tried. Ever failed. No matter. Try again. Fail again. Fail better.
tetim
tetim Membro Senior Registrado
366 Mensagens 1 Curtida
#13 Por tetim
27/07/2006 - 23:49
A minha máquina é um Sempron 2400+ 1.66Ghz de clock real...
Com 1024MB de RAM DDR PC3200, porém trabalha a 333Mhz que é o FSB
do processador.
Eu acho que são as especificações que devem ser levadas em consideração né?
Se tiver mais alguma que precise, é só pedir.
"Conseguirão parar uma, duas ou até tres flores, mas nunca conseguirão segurar a força de uma primavera..."[Chê Guevara]
© 1999-2024 Hardware.com.br. Todos os direitos reservados.
Imagem do Modal