PoC, más rapido if-else o switch?

Iniciado por engel lex, 7 Diciembre 2014, 23:35 PM

0 Miembros y 1 Visitante están viendo este tema.

engel lex

Los que me conocen por aquí, saben que me gusta discutir por tonterias como estas(y que me gusta hacer posts largos)... hace poco estaba hablando sobre un tema con mDrinky y discutíamos si el código compilado de if else es el mismo que switch o si switch era más rápido...

aquí mi prueba de concepto... switch es más rápido... muy ligeramente más rápido

leo un archivo (pi2.txt) y repito 100 veces con 1.000.000 de valores leidos, calculo promedio y repito por el otro metodo
Código (cpp) [Seleccionar]
#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;

int ifelse_op(int largo, char memoria[]);
int switch_op(int largo, char memoria[]);


int main(){
int a = 0;//control de ciclos
int ciclos = 100;//cantidad de muestras
/*tiempos*/
float promedio = 0;
float max = 0;
float min = (unsigned int)-1;//maximo u_int
float buff = 0;
/*********/

/*pasamos el archivo a ram, cuidado con archios grandes*/
ifstream archivo ("pi2.txt",ios::ate);//abrimos con apuntador al final
int largo =(int) archivo.tellg();//calculamos el largo por el apuntador

  archivo.seekg (0, ios::beg);//colocamos apuntador en el inicio
  char memoria[largo];//char-s tan largo como archivo
    archivo.read (memoria, largo);//botamos archivo completo a memoria
    archivo.close();//listo con el archivo

/*primer metodo if-else*/
for(a=0;a<ciclos;a++){
buff = ifelse_op(largo,memoria);
promedio += buff;//suma para promedio
max = max>buff?max:buff;//si maximo es menor que buff max=buff
min = min<buff?min:buff;//si minimo es mayor que buff min=buff
}
promedio/=ciclos;//promedia
cout << "promedio if-else: " << promedio/CLOCKS_PER_SEC << "s" << endl;
cout << "min if-else:" << min/CLOCKS_PER_SEC << "s - ";
cout << "max if-else:" << max/CLOCKS_PER_SEC << "s" <<endl;

/*se reinician las variables*/
promedio = 0;
max = 0;
min = (unsigned int)-1;
/****************************/
/*segundo metodo switch*/
for(a=0;a<ciclos;a++){
buff = switch_op(largo,memoria);
promedio += buff;
max = max>buff?max:buff;
min = min<buff?min:buff;
}
promedio/=ciclos;
cout << "promedio if-else: " << promedio/CLOCKS_PER_SEC << "s" << endl;
cout << "min if-else:" << min/CLOCKS_PER_SEC << "s - ";
cout << "max if-else:" << max/CLOCKS_PER_SEC << "s" <<endl;
return 0;
}

/*****************************************/
int ifelse_op(int largo, char memoria[]){
clock_t inicio_reloj = clock();//tiempo inicial
int control;//variable para control
int i;//control de ciclos
for(i=0;i<largo;i++){
//char valor = memoria[i];//trampa a mi favor mwahaha!!
if(memoria[i]=='1') control = 1;
else if(memoria[i]=='2')control = 2;
else if(memoria[i]=='3')control = 3;
else if(memoria[i]=='4')control = 4;
else if(memoria[i]=='5')control = 5;
else if(memoria[i]=='6')control = 6;
else if(memoria[i]=='7')control = 7;
else if(memoria[i]=='8')control = 8;
else if(memoria[i]=='9')control = 9;
else if(memoria[i]=='0')control = 0;
else control = 0;
}
return clock() - inicio_reloj;//retorna tiempo
}

int switch_op(int largo, char memoria[]){
clock_t inicio_reloj = clock();//tiempo inicial
int control;//variable para control
int i;//control de ciclos
for(i=0;i<largo;i++){
//char valor = memoria[i];
switch (memoria[i]){
case '1':control =  1;
case '2':control =  2;
case '3':control =  3;
case '4':control =  4;
case '5':control =  5;
case '6':control =  6;
case '7':control =  7;
case '8':control =  8;
case '9':control =  9;
case '0':control =  0;
default: control =  0;
}
}
return clock() - inicio_reloj;//retorna tiempo
}



con mi perolita los resultados son
promedio if-else: 0.0238996s
min if-else:0.023581s - max if-else:0.024229s
promedio if-else: 0.0180653s
min if-else:0.018014s - max if-else:0.018394s


con ligeras variaciones menores a +-0.0007 dando como resultado un switch 8% más rápido que el if :P

si alguien cree que mi metodología o código esta mal o me equivoqué avisen

el archivo pi2.txt es un archivo que tengo por ahí tiempo y lo uso para probar cosas, es una generacion de pi a 1.000.000 de decimales, sin cabeceras, ni texto y medio mocho... son casi 1.1mb, si lo quieren, aqui está

https://mega.co.nz/#!6xAmGIaA!FtCMe4bM5NVm-gcO2zW-myUWlBdLI3TqlweAhKaQ-0I


PD: codigo corregido...
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

ivancea96

#1
A mi me da lo mismo en la mayoría de los casos:

Citarpromedio if-else: 2270ms
promedio switch : 2271ms


EDITO: Tras hacer unos cambios, esta es la resolución:

Citarpromedio if-else: 15681ms
promedio switch : 6944ms

x64core

@engel lex, @mDrinky:
Intentar calcular la velocidad de este tipo de códigos es ridiculo, la decisión final es tomada por el compilador. Aquí no mencionas nisiquiera el compilador y parametros ni nada por el estilo, bien puedo activar todas las optimizaciónes. Cualquier programador con un minimo de conocimiento en C/C++ lo sabe y ya que tienen interesantes discuciónes, mDrinky puede empezar a compartir el compilador que utiliza para generar super ensamblador universal con auto-generación.

-

Mejor vayan a leer un buen libro de C/C++.

engel lex

Cita de: x64Core en  8 Diciembre 2014, 00:50 AM
@engel lex, @mDrinky:
Intentar calcular la velocidad de este tipo de códigos es ridiculo, la decisión final es tomada por el compilador. Aquí no mencionas nisiquiera el compilador y parametros ni nada por el estilo, bien puedo activar todas las optimizaciónes. Cualquier programador con un minimo de conocimiento en C/C++ lo sabe y ya que tienen interesantes discuciónes, mDrinky puede empezar a compartir el compilador que utiliza para generar super ensamblador universal con auto-generación.

-

Mejor vayan a leer un buen libro de C/C++.


es cierto cada compilador tiene sus metodos... pero solo por probar con g++ en linux me da así :P sin más parametros, x64Core tu tienes buenos conocimientos sobre lo que se refiere a temas de más bajo nivel. por que no lo pasas tu por varios compiladores con diferentes optimizaciones y sin optimizaciones y vemos las diferencias, al final dentro de un mismo compilador con los mismos parametros, las diferencias si se marcan y al final los ejemplos practicos y pruebas de concepto son más visuales y practicas para ciertas cosas, no?
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

x64core

Cita de: engel lex en  8 Diciembre 2014, 01:02 AM
es cierto cada compilador tiene sus metodos... pero solo por probar con g++ en linux me da así :P sin más parametros, x64Core tu tienes buenos conocimientos sobre lo que se refiere a temas de más bajo nivel. por que no lo pasas tu por varios compiladores con diferentes optimizaciones y sin optimizaciones y vemos las diferencias, al final dentro de un mismo compilador con los mismos parametros, las diferencias si se marcan y al final los ejemplos practicos y pruebas de concepto son más visuales y practicas para ciertas cosas, no?
¿Y sólo por el hecho que alguna persona conozca acerca de temas de bajo nivel debe de hacer estas pruebas? Pues creo que por esa misma razon de saber como esto funciona se evita perder el tiempo de esta manera, pero bueno supongo que lo decias en tono sarcastico e intentando pasarte de listo.
Para que entiendas, habran situaciónes en donde los compiladores generán código más veloz usando if's o switch's, todo dependerá de la logica del programa asi que no hay manera de concluir diciendo cosas como:"usando if's es más veloz", "en general, switch generará código más veloz" o algo por el estilo.

engel lex

Cita de: x64Core en  8 Diciembre 2014, 02:27 AM
¿Y sólo por el hecho que alguna persona conozca acerca de temas de bajo nivel debe de hacer estas pruebas? Pues creo que por esa misma razon de saber como esto funciona se evita perder el tiempo de esta manera, pero bueno supongo que lo decias en tono sarcastico e intentando pasarte de listo.
Para que entiendas, habran situaciónes en donde los compiladores generán código más veloz usando if's o switch's, todo dependerá de la logica del programa asi que no hay manera de concluir diciendo cosas como:"usando if's es más veloz", "en general, switch generará código más veloz" o algo por el estilo.

entonces según el codigo, el compilador puede generar un codigo maquina sobre los switch o if diferente, haciendolos más eficientes según el caso?

en caso general cual es la forma de saber cual sería más eficiente en tu codigo?

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

x64core

Cita de: engel lex en  8 Diciembre 2014, 02:31 AM
entonces según el codigo, el compilador puede generar un codigo maquina sobre los switch o if diferente, haciendolos más eficientes según el caso?

en caso general cual es la forma de saber cual sería más eficiente en tu codigo?


No me referia a eso, dije que va a depender de la logica de tu programa al final el código se traduce en u lenguaje que es entendido por el compilador ya no depende de las sentencias if o switch.

engel lex

Cita de: x64Core en  8 Diciembre 2014, 02:39 AM
No me referia a eso, dije que va a depender de la logica de tu programa al final el código se traduce en u lenguaje que es entendido por el compilador ya no depende de las sentencias if o switch.

XD pero mi duda es: la eficiencia no va a cambiar según usemos una u otra o otra estructura entonces? (supongamos el caso de x codigo que se enfrenta constantemente a esta estructura, caso para el que que son perfectamente intercambiables y requiriendo eficiencia ante todo)
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

x64core

#8
Cita de: engel lex en  8 Diciembre 2014, 02:46 AM
XD pero mi duda es: la eficiencia no va a cambiar según usemos una u otra o otra estructura entonces? (supongamos el caso de x codigo que se enfrenta constantemente a esta estructura, caso para el que que son perfectamente intercambiables y requiriendo eficiencia ante todo)
Es posible pero como dije todo depende de la logica de tu programa, los compiladores no tienen inteligencia artificial como para saber lo que el programador está intentando hacer, lo que si hacen es, intentar darle logica lo que se quiere lograr. Solo pensar que los compiladores hacen comparaciones como decir: "Si es una sentencia if entonces generar una instruccion test reg,reg o si encuentro un switch generar cmp reg, imm" es ridiculo.

Por ejemplo, unas situaciónes que he visto en las ultimas versiones del compilador de VC++ es que al usar una sentencia  switch con varios case's, este crea una tabla de direcciones a los destinos, a la hora de comparar se toma la dirección base de esa tabla y se le suma un offset para obtener la dirección de destino, esto es mejor que ir comparando case por case, solo imagina un switch con 100+ case's. Claro que esto va a depender, si hay pocos case's entonces podria ser mejor comparar uno por uno.




engel lex

comprendo!  ;D

entonces ya se que no tiene demasiado sentido comprar estructuras, sino solo algoritmos en si mismos
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.