For hasta 6.000.000.000 en C

Publicado el Viernes, 25 de abril de 2008

Una de las cosas que más disfruto del blog, es cuando se genera un intercambio con los lectores. Y algo que realmente aprecio, es ser corregido (cuando tienen razón, ¿no? sino simplemente molesta...). Hay gente que se toma esto a mal, pero en mi caso, una de las grandes razones por las que creé el blog es para aprender. Y está buenísimo cuando alguien te corrige y aprendés algo nuevo.

¿A qué viene todo esto? Hace un tiempo (7 de abril) escribí en Twitter: " Si haces un for hasta 6.000.000.000, la computadora se tranca...". Y me faltó detallar un poco más a qué me refería, ya que recibí el siguiente correo de fcr:

de fcr

para fernando[arroba]picandocodigo.net

fecha 9 de abril de 2008 14:00

asunto respuesta a mensaje en twitter

¡Mentira, no se tranca nada!

fran@jariola:~/proj/video% cat for_loco.c
#include <stdlib.h>
int main(void){
     for(uint64_t i=0; i<6000000000; i++);
}
fran@jariola:~/proj/video% cc for_loco.c -o for_loco -std=c99 -O2
fran@jariola:~/proj/video% time ./for_loco
./for_loco  0,00s user 0,00s system 66% cpu 0,001 total
fran@jariola:~/proj/video%

Sin embargo, me faltó detallar las condiciones de mi experiencia. Para ser más preciso, mi mensaje debió decir "Si hacés un for hasta 6.000.000.000 programando en una máquina con Windows XP, en Visual Studio con el framework .NET 2.0, y ejecutás la aplicación que contiene dicho código con unas cuantas aplicaciones más abiertas, la máquina se cuelga". Salió de una experiencia durante mi jornada laboral de ese día.

Si pruebo el código de fcr en mi máquina, con Debian GNU/Linux, y compilando el código en C por consola, efectivamente no se tranca:

fernando@nando-debian:~/DEVEL/C/for$ cc forLoco.c -o for_loco -std=c99 -O2
fernando@nando-debian:~/DEVEL/C/for$ time ./for_loco
real    0m0.001s
user    0m0.000s
sys     0m0.000s
fernando@nando-debian:~/DEVEL/C/for$

Bien, además de aprender que no se tranca, aprendí un par de cosas más:

-En sistemas GNU es equivalente escribir "gcc" o "cc" gcc.

-El parámetro "-std=c99" le dice a gcc que intente usar el estándar C99.

-El parámetro "O" (en éste caso "-O2"), es para usar la optimización de GCC. -On, donde n es el nivel de optimización. También está -Os que optimiza para que el binario quede lo más chico posible.

Respecto a éste último punto, a rasgos muy generales puedo decir que GCC provee varias opciones para aumentar la velocidad o reducir el tamaño de los archivos ejecutables que genera. Éste tema tengo que darle un poco más de estudio.

Por ejemplo, miren el resultado si compilo el mismo código, sin el parámetro de optimización:

fernando@nando-debian:~/DEVEL/C/for$ cc forLoco.c -o for_loco -std=c99
fernando@nando-debian:~/DEVEL/C/for$ time ./for_loco
real    0m29.273s
user    0m29.182s
sys     0m0.012s
fernando@nando-debian:~/DEVEL/C/for$

Del IRC:

<fcr> fbt: nadie compila sin el -O2

<fcr> mirá si te asfixiás

Y todo esto lo aprendí por una pavada nomás, y unos minutos en irc. Si tendré C por aprender...

15 comentarios en este post

Feed de comentarios
  1. Avatar

    Juan Funez 25 abril. 2008 - 01:34

    ¿Quien más sino Francisco?
    Lo de CC y ‘-std=c99? no tenia idea, lo de -O2 si, yo usaba -O3 para las tareas de facultad y de ahí me quedo.

    Esta muy bueno el comentario del IRC.

    Saludos.

  2. Avatar

    takedown 25 abril. 2008 - 02:59

    bueno bueno bueno… sigo hace bastante (año pasado) el blog y la verdad, siempre es bueno leerte…

    esta vez me decidi a comentar ya que estaba programando en C, algo no salia bien y vi que mi agregador de Rss (aka akregator) titilaba con 1 nuevo item…

    Y ¬¬

    C
    C
    C
    C
    C
    C

    ¬¬

    Dios que lenguaje precioso… a uno lo hace revolcarse ^^

    en fin, a tener en cuenta el -O2 😛 o el -Os pero estaria bueno encontrar info sobre cual valor darle (el mas correcto)

  3. Avatar

    YoNoSoyTu 25 abril. 2008 - 07:59

    Deberías poner contenido dentro del bucle, con -O2 (o posiblemente con -O1) GCC está optimizando tu código y posiblemente destruya ese bucle sin contenido, dejando tu programa en nada (por eso tarda tan poco).

    Ponle una suma o asigna el contador del bucle a una variable para que veas que sucede.

  4. Avatar

    Mauricio 16 mayo. 2010 - 13:49

    Hola,
    Ayer me encontré esta entrada a tu blog, y decidí hacer una pequeña prueba,a verq ue pasaba si le agregaba un printf() a la salida estandar … y me sorprendio bastante el resultado…

    <pre lang= "c"
    raul@raul-desktop:~$ cat for_loco.c
    #include
    #include
    #include

    int main(void){
    uint64_t i;
    for(i=0ll; i /dev/null

    real 21m21.155s
    user 17m18.190s
    sys 0m6.180s
    raul@raul-desktop:~$

    ¿loco no? Tal vez cuando el for esta vacío simplemente lo elimina en la optimización…
    Aclaro: no tengo más conocimientos de c más allá de lo publicado aquí.
    Saludos,

    Mauricio.

  5. Avatar

    Mauricio 17 mayo. 2010 - 18:19

    Corrijo codigo porque salio como el tujem:

    cat for_loco.c
    #include
    #include
    #include

    int main(void){
    uint64_t i;
    for(i=0ll; i /dev/null

    real 21m21.155s
    user 17m18.190s
    sys 0m6.180s

Dejar un comentario

Toasty!