Foros del Web » Programación para mayores de 30 ;) » C/C++ »

¿Alguna idea para optimizar el código?

Estas en el tema de ¿Alguna idea para optimizar el código? en el foro de C/C++ en Foros del Web. Estoy usando la librería SFML 2, lo que pasa es que al principio consume aprox 4% del CPU según htop, pero también cuenta que estoy ...
  #1 (permalink)  
Antiguo 26/03/2013, 23:53
 
Fecha de Ingreso: abril-2011
Mensajes: 224
Antigüedad: 13 años
Puntos: 8
¿Alguna idea para optimizar el código?

Estoy usando la librería SFML 2, lo que pasa es que al principio consume aprox 4% del CPU según htop, pero también cuenta que estoy usando una netbook con intel atom.

Cualquier optimización, por más peqieña que sea, me serviría.

Muchas gracias.

Código C++:
Ver original
  1. #include <SFML/Graphics.hpp>
  2. #include <SFML/Audio.hpp>
  3. #include <SFML/System.hpp>
  4.  
  5. int main()
  6. {
  7.     // Ventana en la que se muestra todo el contenido del juego.   
  8.     sf::RenderWindow gameWindow(sf::VideoMode(1024, 600, 32), "Project Genesis",
  9.                                 sf::Style::Fullscreen);
  10.  
  11.     // Se establece el límite de frames por segundo a 60
  12.     gameWindow.setFramerateLimit(60);
  13.  
  14.     enum Boton{NUEVO_JUEGO, CONTINUAR, OPCIONES, SALIR};
  15.     Boton boton = NUEVO_JUEGO;
  16.  
  17.     // Música
  18.     sf::SoundBuffer buffer;
  19.     buffer.loadFromFile("main.wav");
  20.  
  21.     sf::SoundBuffer button;
  22.     button.loadFromFile("button.wav");
  23.  
  24.     sf::SoundBuffer selection;
  25.     selection.loadFromFile("selection.wav");
  26.  
  27.     sf::Sound sound;
  28.     sound.setBuffer(buffer);
  29.     sound.setLoop(true);
  30.  
  31.     sf::Sound buttons;
  32.     buttons.setBuffer(button);
  33.  
  34.     sf::Sound selections;
  35.     selections.setBuffer(selection);
  36.  
  37.     sf::Texture menu_i;
  38.     if(!menu_i.loadFromFile("menu.png"))
  39.         return EXIT_FAILURE;
  40.     sf::Sprite menu_s;
  41.     menu_s.setTexture(menu_i);
  42.  
  43.     sf::Texture nuevo_juego_i;
  44.     if(!nuevo_juego_i.loadFromFile("nuevo_juego.png"))
  45.         return EXIT_FAILURE;
  46.     sf::Sprite nuevo_juego_s;
  47.     nuevo_juego_s.setTexture(nuevo_juego_i);
  48.     nuevo_juego_s.setPosition(700, 225);
  49.  
  50.     sf::Texture nuevo_juego2_i;
  51.     if(!nuevo_juego2_i.loadFromFile("nuevo_juego2.png"))
  52.         return EXIT_FAILURE;
  53.     sf::Sprite nuevo_juego2_s;
  54.     nuevo_juego2_s.setTexture(nuevo_juego2_i);
  55.     nuevo_juego2_s.setPosition(700, 225);
  56.  
  57.     sf::Texture continuar_i;
  58.     if(!continuar_i.loadFromFile("continuar.png"))
  59.         return EXIT_FAILURE;
  60.     sf::Sprite continuar_s;
  61.     continuar_s.setTexture(continuar_i);
  62.     continuar_s.setPosition(700, 275);
  63.  
  64.     sf::Texture continuar2_i;
  65.     if(!continuar2_i.loadFromFile("continuar2.png"))
  66.         return EXIT_FAILURE;
  67.     sf::Sprite continuar2_s;
  68.     continuar2_s.setTexture(continuar2_i);
  69.     continuar2_s.setPosition(700, 275);
  70.  
  71.     sf::Texture opciones_i;
  72.     if(!opciones_i.loadFromFile("opciones.png"))
  73.         return EXIT_FAILURE;
  74.     sf::Sprite opciones_s;
  75.     opciones_s.setTexture(opciones_i);
  76.     opciones_s.setPosition(700, 325);
  77.  
  78.     sf::Texture opciones2_i;
  79.     if(!opciones2_i.loadFromFile("opciones2.png"))
  80.         return EXIT_FAILURE;
  81.     sf::Sprite opciones2_s;
  82.     opciones2_s.setTexture(opciones2_i);
  83.     opciones2_s.setPosition(700, 325);
  84.  
  85.     sf::Texture salir_i;
  86.     if(!salir_i.loadFromFile("salir.png"))
  87.         return EXIT_FAILURE;
  88.     sf::Sprite salir_s;
  89.     salir_s.setTexture(salir_i);
  90.     salir_s.setPosition(700, 375);
  91.  
  92.     sf::Texture salir2_i;
  93.     if(!salir2_i.loadFromFile("salir2.png"))
  94.         return EXIT_FAILURE;
  95.     sf::Sprite salir2_s;
  96.     salir2_s.setTexture(salir2_i);
  97.     salir2_s.setPosition(700, 375);
  98.  
  99.     gameWindow.draw(menu_s);
  100.     gameWindow.draw(nuevo_juego2_s);
  101.     gameWindow.draw(continuar_s);
  102.     gameWindow.draw(opciones_s);
  103.     gameWindow.draw(salir_s);
  104.     gameWindow.display();
  105.  
  106.     sf::Image captura;
  107.     captura = gameWindow.capture();
  108.     captura.saveToFile("captura.png");
  109.    
  110.     sound.play();
  111.  
  112.     // Mientras la ventana esté abierta
  113.     while(gameWindow.isOpen())
  114.     {
  115.         // Ciclo para procesar eventos
  116.  
  117.         // Variable para almacenar los eventos
  118.         sf::Event Event;
  119.  
  120.         while(gameWindow.pollEvent(Event))
  121.         {
  122.             switch (Event.type)
  123.             {
  124.                 case sf::Event::Closed:
  125.                     gameWindow.close();
  126.                     break;
  127.                 case sf::Event::KeyPressed:
  128.                     if(Event.key.code == sf::Keyboard::Escape)
  129.                         gameWindow.close();
  130.                     if(Event.key.code == sf::Keyboard::Up)
  131.                     {
  132.                         buttons.play();
  133.                         switch(boton)
  134.                         {
  135.                             case NUEVO_JUEGO:
  136.                                 boton = SALIR;
  137.                                 break;
  138.                             case CONTINUAR:
  139.                                 boton = NUEVO_JUEGO;
  140.                                 break;
  141.                             case OPCIONES:
  142.                                 boton = CONTINUAR;
  143.                                 break;
  144.                             case SALIR:
  145.                                 boton = OPCIONES;
  146.                                 break;
  147.                         }
  148.                     }
  149.                     if(Event.key.code == sf::Keyboard::Down)
  150.                     {
  151.                         buttons.play();
  152.                         switch(boton)
  153.                         {
  154.                             case NUEVO_JUEGO:
  155.                                 boton = CONTINUAR;
  156.                                 break;
  157.                             case CONTINUAR:
  158.                                 boton = OPCIONES;
  159.                                 break;
  160.                             case OPCIONES:
  161.                                 boton = SALIR;
  162.                                 break;
  163.                             case SALIR:
  164.                                 boton = NUEVO_JUEGO;
  165.                                 break;
  166.                         }
  167.                     }
  168.                     if(Event.key.code == sf::Keyboard::Return)
  169.                     {
  170.                         switch(boton)
  171.                         {
  172.                             case SALIR:
  173.                                 selections.play();
  174.                                 while(selections.getStatus() == sf::SoundSource::Status::Playing)
  175.                                     sf::sleep(sf::milliseconds(1));
  176.                                 gameWindow.close();
  177.                                 break;
  178.                         }
  179.                     }
  180.                 default:
  181.                     break;
  182.             }
  183.  
  184.             // Limpia la pantalla
  185.             gameWindow.clear();
  186.  
  187.             switch(boton)
  188.             {
  189.                 case NUEVO_JUEGO:
  190.                     gameWindow.draw(menu_s);
  191.                     gameWindow.draw(nuevo_juego2_s);
  192.                     gameWindow.draw(continuar_s);
  193.                     gameWindow.draw(opciones_s);
  194.                     gameWindow.draw(salir_s);
  195.                     break;
  196.                 case CONTINUAR:
  197.                     gameWindow.draw(menu_s);
  198.                     gameWindow.draw(nuevo_juego_s);
  199.                     gameWindow.draw(continuar2_s);
  200.                     gameWindow.draw(opciones_s);
  201.                     gameWindow.draw(salir_s);
  202.                     break;
  203.                 case OPCIONES:
  204.                     gameWindow.draw(menu_s);
  205.                     gameWindow.draw(nuevo_juego_s);
  206.                     gameWindow.draw(continuar_s);
  207.                     gameWindow.draw(opciones2_s);
  208.                     gameWindow.draw(salir_s);
  209.                     break;
  210.                 case SALIR:
  211.                     gameWindow.draw(menu_s);
  212.                     gameWindow.draw(nuevo_juego_s);
  213.                     gameWindow.draw(continuar_s);
  214.                     gameWindow.draw(opciones_s);
  215.                     gameWindow.draw(salir2_s);
  216.                     break;
  217.             }
  218.  
  219.             // Redibuja la oantalla
  220.             gameWindow.display();
  221.         }
  222.     }
  223. }

Saludos.
  #2 (permalink)  
Antiguo 27/03/2013, 01:46
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: ¿Alguna idea para optimizar el código?

Un consumo de un 4% no lo veo para nada preocupante ya que has de cargar las texturas. Si fuese mucho más elevado ese consumo entendería que quisieras bajarlo.

La única optimización que se me ocurre es pasar a un switch el contenido del case "sf::Event::KeyPressed:". En un switch el compilador construye, si es más óptimo (sino usa una estructura similar al if), una tabla de hash para realizar los saltos, en lugar de comprobar una a una las condiciones. Pero vamos, que aunque sea una pequeña optimización, no es algo que te vaya a bajar el consumo de CPU. Has probado con los switch del compilador? Los -O
__________________
Aviso: No se resuelven dudas por MP!
  #3 (permalink)  
Antiguo 27/03/2013, 02:51
 
Fecha de Ingreso: abril-2011
Mensajes: 224
Antigüedad: 13 años
Puntos: 8
Respuesta: ¿Alguna idea para optimizar el código?

No he probado, probaré, gracias. Y sí, empezar con 4% no es alarmante, pero olvidé mencionar que cuando la canción empieza a sonar "bien", sube a ~70-80%, y eso sí es terrorífico. :S
  #4 (permalink)  
Antiguo 27/03/2013, 03:00
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: ¿Alguna idea para optimizar el código?

Cita:
Iniciado por reethok Ver Mensaje
No he probado, probaré, gracias. Y sí, empezar con 4% no es alarmante, pero olvidé mencionar que cuando la canción empieza a sonar "bien", sube a ~70-80%, y eso sí es terrorífico. :S
Eso ya es otra cosa xD

De todas formas, si el consumo viene básicamente de la reproducción de la canción... ya estas descartando que sea algo de tu código, sino que se trata de la propia función de reproducir el audio. Como ahí no creo que le vayas a meter mano... yo optaría por otras opciones:

1) Bajar la "calidad" (o muestreo) del audio para que no tenga que consumir tanta CPU para reproducirlo. Yo haría un proyecto de prueba donde reproduzcas un audio y al pulsar una tecla te muestre el consumo de CPU que tenía y repita la prueba con otro audio diferente. Así podrás ver que formato/calidad te consume menos

2) La otra opción es... cambiar de librería de audio :P

Yo optaría por hacer las pruebas del punto 1. Si con eso no ves ningún cambio en el consumo de CPU... no te va a quedar otra que pasar al punto 2.
__________________
Aviso: No se resuelven dudas por MP!
  #5 (permalink)  
Antiguo 27/03/2013, 05:42
 
Fecha de Ingreso: abril-2011
Mensajes: 224
Antigüedad: 13 años
Puntos: 8
Respuesta: ¿Alguna idea para optimizar el código?

Bueno, primero que nada gracias por tu respuesta, ahora, he logrado ciertos avances descubriendo cosas un poco "raras".

1.- Usando el flag -O3 hago que el porcentaje de consumo del CPU se mantenga en 3-4%, que sigue siendo mucho a mi parecer, pero ya va mejor. Probaré bajando el framerate a 45 o 30.

2.- Si uso los flags -O1 u -O2, no pasa ABSOLUTAMENTE nada, me corre el programa como si no utilizara optimización alguna, ¿a qué se deberá?

Saludos!

EDIT Acabo de probar con 30FPS y -O3 y va a 70% del CPU, algo definitivmente está mal con los procesadores Atom xD

Última edición por reethok; 27/03/2013 a las 05:50
  #6 (permalink)  
Antiguo 27/03/2013, 06:25
 
Fecha de Ingreso: julio-2012
Mensajes: 375
Antigüedad: 11 años, 9 meses
Puntos: 28
Respuesta: ¿Alguna idea para optimizar el código?

El % de CPU no se corresponde con la carga sino con las veces "que descansa".

Prueba compilar este programa:

Código C++:
Ver original
  1. int main()
  2. {
  3.     int Cosita = 0;
  4.    
  5.     while (true)
  6.     {
  7.         Cosita++;
  8.         Cosita--;
  9.     }
  10.     return 0;
  11. }

No hace nada, pero consume el 100% de la CPU (en procesadores mononúcleo). Como puedes ver, no está haciendo nada del otro mundo. Incluso podríamos dejarlo así:

Código C++:
Ver original
  1. int main()
  2. {
  3.     while (true);
  4.  
  5.     return 0;
  6. }

La razón que use el 100% de la CPU es que este programa no deja descansar al procesador.

En condiciones normales el procesador siempre está descansando porque está esperando una acción (por ejemplo, ya sea a que el usuario le introduzca datos por teclado/ratón o porque está cargando archivos del disco duro). Muy a menudo también se "induce" a que el procesador descanse (con alguna función tipo sleep).

En resumen, el uso de la CPU depende de:

- Los descansos que tenga el procesador en el programa.
- Los núcleos que tenga el procesador (cada núcleo puede lanzar un hilo de ejecución, por tanto si saturas un núcleo te quedan los demás). Como tienes un procesador mononúcleo el porcentaje se dispara.

Última edición por amchacon; 27/03/2013 a las 06:32
  #7 (permalink)  
Antiguo 27/03/2013, 20:15
Avatar de dontexplain  
Fecha de Ingreso: junio-2012
Mensajes: 536
Antigüedad: 11 años, 10 meses
Puntos: 127
Respuesta: ¿Alguna idea para optimizar el código?

Cita:
Iniciado por amchacon Ver Mensaje
En resumen, el uso de la CPU depende de:

- Los descansos que tenga el procesador en el programa.
- Los núcleos que tenga el procesador (cada núcleo puede lanzar un hilo de ejecución, por tanto si saturas un núcleo te quedan los demás). Como tienes un procesador mononúcleo el porcentaje se dispara.
Toda la razón. Hace no mucho tiempo estuve haciendo straces a algunos procesos y hace muchos descansos. Las llamadas al sistema revelan que hace o bien con sleep descansos de segundos o con microsleep (usleep), incluso con nanosleep que admite estructuras de {seconds, nanoseconds} para la resolución del descanso (sobre todo). Desconozco el impacto que pueden tener en el rendimiento, porque no lo he analizado más que nada, pero también se usa while, y su impacto es relativamente bajo (creo que menor que sleep porque hace interrupciones para calcular la diferencia de tiempo además de que hace llamadas a estas funciones de la librería)

(asumiendo que val es un bool)

while(val)

Código Ensamblador:
Ver original
  1. mov eax, 00000001h (00000032h)
  2. // entre medias las operaciones que sean
  3. cmp eax,dword ptr [val] // asumiendo 4 bytes y que val podría haber cambiado
  4. je main+xxh (u otra, pero la cuestión es que salte a 00000032h)

Asumo que true es 1 (lo es), y que cmp compara el valor de eax donde se almacena true invariablemente con el valor del puntero [val] que almacena el boleano variable. En la línea 4 hay un salto corto, revisar EB. (1)

Si consigo que mi PC deje de dar pantallazos azules cuando le de la gana, reviso el código resultante de usleep y microsleep y posteo la comparación aquí.

(1) El salto corto hace un salto relativo corto a la posición indicada como suma. La mayoría de los desensambladores suelen sumar a ese valor +2 posiciones de memoria porque las instrucciones son 2 bytes y hace el cálculo teniendo en cuenta el tamaño. En cualquier caso siempre será el valor de main+((xxh)+2) ya que será referente a EIP que almacena siempre la siguiente dirección de la memoria mientras ejecuta. O sea, si está ejecutando 0x0000000d almacenará 0x0000000f y el salto será referente a la segunda dirección, ergo habrá que sumar el offset corto a esa última dirección.
__________________
21añero.
HTML/CSS, PHP, JS/jQuery, Mysql; NodeJS/Socket.io (& V8); C++ ; Python (wxpy); Ensamblador.
Músico (clarinetista/pianista) y compositor

Última edición por dontexplain; 27/03/2013 a las 20:51

Etiquetas: idea, int, salir, variable
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:37.