elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]  (Leído 5,686 veces)
NOB2014


Desconectado Desconectado

Mensajes: 366



Ver Perfil
¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« en: 4 Mayo 2016, 20:03 pm »

Hola a todos.
Copie el código de la siguiente página que me indico Eternal Idol, referente a realloc:
http://www.cplusplus.com/reference/cstdlib/realloc/

Y grande fue mi sorpresa cuando descubrí que utilizando memoria dinámica se podía hacer lo mismo que con un array, digo sorpresa porque considero haber leído bastante sobre punteros y en ninguno hace referencia a esto. -
Si esto es correcto, tengo 1 pregunta para hacerles. -
¿Que es más eficiente, utilizar array o memoria dinámica?, para el caso. -  

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4.  
  5. int main ( void ){
  6. size_t ingresos, n, contador = 0, ok, ch;
  7. int* numeros = NULL;
  8. int* mas_numeros = NULL;
  9.  
  10. do{
  11. do{
  12. printf("\n Ingresa un numero entero(maximo %d  => 0 finaliza )....: ", INT_MAX);
  13. ok = scanf("%u", &ingresos) == 1 && ingresos >= 0 && ingresos <= INT_MAX;
  14. while( (ch = getchar()) != EOF && ch != '\n' );
  15. if( ok == 0 ){
  16. printf( "\n El ingreso es incorrecto, intentelo nuevamente...\n\n\t Pulse una tecla para continuar..." ); getchar();
  17. }
  18. }while(!ok);
  19.  
  20. contador++;
  21.  
  22. mas_numeros = (int*)realloc( numeros, contador * sizeof(int) );
  23.  
  24. if( mas_numeros!=NULL ){
  25. numeros=mas_numeros;
  26. numeros[contador-1]=ingresos;
  27. }
  28. else{
  29. free( numeros );
  30. puts( "Error (re)allocating memory" );
  31. exit(1);
  32. }
  33. }while (ingresos!=0);
  34.  
  35. printf ("\n Numeros introducidos.....: ");
  36. for( n=0; n < contador - 1; n++ )
  37. printf( "%d ",numeros[n] );
  38.  
  39. free (numeros);
  40.  
  41. return 0;
  42. }

Es redundante decir que al código original le efectué bastante modificaciones, pero la esencia es la misma.

Saludos.


« Última modificación: 4 Mayo 2016, 21:44 pm por NOB2014 » En línea

abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: asombrado, admirado, sorprendido, pasmado, maravillado, impresionado, alucinado.
« Respuesta #1 en: 4 Mayo 2016, 20:31 pm »

¿Que es más eficiente, utilizar array o memoria dinámica?, para el caso. - 

Es preferible usar memoria dinámica si no sabes a prior la cantidad de datos que vas a manejar, asi solo reservas memoria para los datos que realmente se usan.

Código:
printf("\n Ingresa un numero entero(maximo %d  => 0 finaliza )....: ", INT_MAX);

Claro ejemplo si no sabes cuantos datos vana meter es preferible reservar memoria dinamicamente.

Si por el contrario usas, un numero fijo, no hay problema de usar un array estatico

Saludos!


En línea

MAFUS


Desconectado Desconectado

Mensajes: 1.603



Ver Perfil
Re: asombrado, admirado, sorprendido, pasmado, maravillado, impresionado, alucinado.
« Respuesta #2 en: 4 Mayo 2016, 20:54 pm »

Los arrays y las tablas són siempre más eficientes, pues son datos que se guardan en la pila y el código que se genera para acceder a ellos es más rápido que acceder el montón. Por otra parte la memoria de la pila es bastante más limitada, en tamaño que la del montón y para un gran número de elementos te podrías quedar sin pila de programa rápidamente.
También está el tema de pasar arrays a funciones como argumentos: como es un puntero se pierde totalmente la ventaja de un array propio ya que hay que tratarlo como si estuviera en el montón.
Por último la función realloc es una de las más lentas pues debe acceder al montón, comprobar si hay memoria suficiente para la nueva asignación,  copiar todos los datos que le son posible a la nueva asignación y liberar la memoria del puntero original.
En línea

NOB2014


Desconectado Desconectado

Mensajes: 366



Ver Perfil
Re: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« Respuesta #3 en: 5 Mayo 2016, 00:35 am »

Hola, gracias a ambos por las respuestas, muy esclarecedoras por cierto. -
Una cosita más, la memoria asignada a la pila y el montón es monitoreada por el SO, hay alguna manera con C saber cuanta memoria se le asigna a estas 2 areas de memoria de un determinado programa(cuantos bytes). -

Citar
Los arrays y las tablas són siempre más eficientes, pues son datos que se guardan en la pila y el código que se genera para acceder a ellos es más rápido que acceder el montón. Por otra parte la memoria de la pila es bastante más limitada, en tamaño que la del montón y para un gran número de elementos te podrías quedar sin pila de programa rápidamente.

No hay contradicciones en esta descripción, digo.



Saludos.
« Última modificación: 5 Mayo 2016, 00:39 am por NOB2014 » En línea

abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-
Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.935


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: asombrado, admirado, sorprendido, pasmado, maravillado, impresionado, alucinado.
« Respuesta #4 en: 5 Mayo 2016, 01:42 am »

Los arrays y las tablas són siempre más eficientes, pues son datos que se guardan en la pila

Normalmente las variables locales van en la pila y las globales van en la sección de datos.

y el código que se genera para acceder a ellos es más rápido que acceder el montón.

¿Que? Esto dependera de la plataforma pero en PC las instrucciones de cadena son mas rapidas que push/pop seguro (y ni hablar las de extensiones multimedia) ... ademas la pila es memoria virtual igual que el monton (mov* se terminara usando para leer casi siempre).

También está el tema de pasar arrays a funciones como argumentos: como es un puntero se pierde totalmente la ventaja de un array propio ya que hay que tratarlo como si estuviera en el montón.

Tampoco lo entiendo, un puntero a la pila no guarda diferencia con un puntero al monton ...

No hay contradicciones en esta descripción, digo.

Cuando algo habla de un S.O. no aplica a todos.
« Última modificación: 5 Mayo 2016, 01:57 am por Eternal Idol » En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
HardForo

Desconectado Desconectado

Mensajes: 219


HardForo.com


Ver Perfil WWW
Re: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« Respuesta #5 en: 5 Mayo 2016, 04:05 am »

Citar
¿Que? Esto dependera de la plataforma pero en PC las instrucciones de cadena son mas rapidas que push/pop seguro (y ni hablar las de extensiones multimedia) ... ademas la pila es memoria virtual igual que el monton (mov* se terminara usando para leer casi siempre).

Lo que sucede es que usar encontrar un espacio en HEAP del tamaño indicado para evitar fragmentacion implica esfuerzo para el SO.
En línea

HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *
MAFUS


Desconectado Desconectado

Mensajes: 1.603



Ver Perfil
Re: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« Respuesta #6 en: 5 Mayo 2016, 07:00 am »

Moverse en la pila local es restar un literal a base pointer, un acceso al montón es cargar la dirección de memoria y despues hay que calcular el offset.



Dos programas que hacen casi lo mismo. El primero crea un array normal, en la pila; el segundo lo crea en el motón mediante malloc.
Código en C del array en pila:
Código
  1. #include <stdio.h>
  2.  
  3. int main( void ){
  4.    int array[5];
  5.  
  6.    array[3] = 3;    
  7.    printf("%i", array[3]);
  8.  
  9.    return 0;
  10. }

Código en C del array en el montón:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main( void ){
  5.    int *array = malloc(sizeof(int) * 5);
  6.  
  7.    array[3] = 3;    
  8.    printf("%i", array[3]);
  9.  
  10.    return 0;
  11. }

Código ensamblador generado, sin optimización y en sintaxis INTEL, por GCC para el array en la pila:
Código
  1. .file "c.c"
  2. .intel_syntax noprefix
  3. .section .rodata
  4. .LC0:
  5. .string "%i"
  6. .text
  7. .globl main
  8. .type main, @function
  9. main:
  10. .LFB0:
  11. .cfi_startproc
  12. push rbp
  13. .cfi_def_cfa_offset 16
  14. .cfi_offset 6, -16
  15. mov rbp, rsp
  16. .cfi_def_cfa_register 6
  17. sub rsp, 32
  18. mov DWORD PTR [rbp-20], 3
  19. mov eax, DWORD PTR [rbp-20]
  20. mov esi, eax
  21. mov edi, OFFSET FLAT:.LC0
  22. mov eax, 0
  23. call printf
  24. mov eax, 0
  25. leave
  26. .cfi_def_cfa 7, 8
  27. ret
  28. .cfi_endproc
  29. .LFE0:
  30. .size main, .-main
  31. .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
  32. .section .note.GNU-stack,"",@progbits

Código ensamblador generado, sin optimización y en sintaxis INTEL, por GCC para el array en el montón:
Código
  1. .file "d.c"
  2. .intel_syntax noprefix
  3. .section .rodata
  4. .LC0:
  5. .string "%i"
  6. .text
  7. .globl main
  8. .type main, @function
  9. main:
  10. .LFB2:
  11. .cfi_startproc
  12. push rbp
  13. .cfi_def_cfa_offset 16
  14. .cfi_offset 6, -16
  15. mov rbp, rsp
  16. .cfi_def_cfa_register 6
  17. sub rsp, 16
  18. mov edi, 20
  19. call malloc
  20. mov QWORD PTR [rbp-8], rax
  21. mov rax, QWORD PTR [rbp-8]
  22. add rax, 12
  23. mov DWORD PTR [rax], 3
  24. mov rax, QWORD PTR [rbp-8]
  25. add rax, 12
  26. mov eax, DWORD PTR [rax]
  27. mov esi, eax
  28. mov edi, OFFSET FLAT:.LC0
  29. mov eax, 0
  30. call printf
  31. mov eax, 0
  32. leave
  33. .cfi_def_cfa 7, 8
  34. ret
  35. .cfi_endproc
  36. .LFE2:
  37. .size main, .-main
  38. .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
  39. .section .note.GNU-stack,"",@progbits

Como se puede ver la escritura y la lectura en el montón, mediante puntero necesita de muchas más instrucciones que el acceso a un elemento el array.
« Última modificación: 5 Mayo 2016, 09:49 am por MAFUS » En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.935


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« Respuesta #7 en: 5 Mayo 2016, 14:47 pm »

Lo que sucede es que usar encontrar un espacio en HEAP del tamaño indicado para evitar fragmentacion implica esfuerzo para el SO.

Pero eso no es el codigo generado.


Moverse en la pila local es restar un literal a base pointer, un acceso al montón es cargar la dirección de memoria y despues hay que calcular el offset.

Repito: eso es dependiente de la plataforma. Comparar el acceso a un elemento de un array para hablar de optimizacion no me parece lo mas idoneo ... pero igual como vemos no hay instrucciones especiales para acceder a la pila, son simples mov.

Como se puede ver la escritura y la lectura en el montón, mediante puntero necesita de muchas más instrucciones que el acceso a un elemento el array.

No, lo que se puede ver no es eso sino el codigo que genero un compilador A con una configuracion B para una plataforma C. Y obviamente ese codigo estaba muy poco optimizado, dudo muchisimo que un compilador moderno no pueda llegar a esto e incluso a algo mas veloz:

Código
  1. mov QWORD PTR [rbp-8], rax ;guardamos en la variable local array el resultado de malloc
  2. mov DWORD PTR [rax + 0Ch], 3 ;escribimos en array[3]
  3. mov eax, DWORD PTR [rax + 0Ch] ;leemos de array[3]

Igual no es una buena idea equiparar el numero de instrucciones a su velocidad de ejecucion, las instrucciones de 128 bits son mas largas para codificar y a la misma vez son mas rapidas para ejecutar.

PD. No se puede comparar el codigo optimizado ya que este codigo es tan trivial que al hacerlo el compilador directamente pone el numero 3 donde corresponda como parametro de printf.



Este si se puede comparar optimizado aunque sigue siendo trivial:

Código
  1.    #include <stdio.h>
  2.  
  3.    int main( void ){
  4.        int array[5];
  5.  
  6. for (int x = 0; x < 5; ++x)
  7.        array[x] = 5 - x;  
  8.        printf("%i", array[3]);
  9.  
  10.        return 0;
  11.    }

Código
  1.    #include <stdio.h>
  2.    #include <stdlib.h>
  3.  
  4.    int main( void ){
  5.        int *array = malloc(sizeof(int) * 5);
  6.  
  7. for (int x = 0; x < 5; ++x)
  8.        array[x] = 5 - x;    
  9.  
  10.        printf("%i", array[3]);
  11.  
  12.        return 0;
  13.    }

Compilador VC++ con configuracion para optimizar tamaño /O1 (y GS- para el ejemplo de la pila) en x64.

Código
  1. main:
  2.  0000000000000000: 48 83 EC 48        sub         rsp,48h
  3.  0000000000000004: 33 C0              xor         eax,eax
  4.  0000000000000006: 8D 48 05           lea         ecx,[rax+5]
  5.  0000000000000009: 89 4C 84 20        mov         dword ptr [rsp+rax*4+20h],ecx
  6.  000000000000000D: 48 FF C0           inc         rax
  7.  0000000000000010: FF C9              dec         ecx
  8.  0000000000000012: 48 83 F8 05        cmp         rax,5
  9.  0000000000000016: 7C F1              jl          0000000000000009
  10.  0000000000000018: 8B 54 24 2C        mov         edx,dword ptr [rsp+2Ch]
  11.  000000000000001C: 48 8D 0D 00 00 00 00 lea         rcx,[??_C@_02IKAHHCAI@?$CFi?$AA@]
  12.  0000000000000023: E8 00 00 00 00     call        printf
  13.  0000000000000028: 33 C0              xor         eax,eax
  14.  000000000000002A: 48 83 C4 48        add         rsp,48h
  15.  000000000000002E: C3                 ret

Código
  1. main:
  2.  0000000000000000: 48 83 EC 28        sub         rsp,28h
  3.  0000000000000004: B9 14 00 00 00     mov         ecx,14h
  4.  0000000000000009: E8 00 00 00 00     call        malloc
  5.  000000000000000E: 33 C9              xor         ecx,ecx
  6.  0000000000000010: 8D 51 05           lea         edx,[rcx+5]
  7.  0000000000000013: 89 14 88           mov         dword ptr [rax+rcx*4],edx
  8.  0000000000000016: 48 FF C1           inc         rcx
  9.  0000000000000019: FF CA              dec         edx
  10.  000000000000001B: 48 83 F9 05        cmp         rcx,5
  11.  000000000000001F: 7C F2              jl          0000000000000013
  12.  0000000000000021: 8B 50 0C           mov         edx,dword ptr [rax+0Ch]
  13.  0000000000000024: 48 8D 0D 00 00 00  00 lea         rcx,[??_C@_02IKAHHCAI@?$CFi?$AA@]
  14.  000000000000002B: E8 00 00 00 00     call        printf
  15.  0000000000000030: 33 C0              xor         eax,eax
  16.  0000000000000032: 48 83 C4 28        add         rsp,28h
  17.  0000000000000036: C3                 ret

Como podemos ver las instrucciones mov de la pila usan 4 bytes y las del monticulo 3 :silbar:
« Última modificación: 5 Mayo 2016, 15:11 pm por Eternal Idol » En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« Respuesta #8 en: 5 Mayo 2016, 15:35 pm »

Interesante debate.

Aun.que creo que la pregunta era mas orientada a alguien que apenas esta aprendiendo a user apuntadores.

Supongo que las optimizaciones que se puedan a hacer al codigo en C podrian tener distintos resultados dependiendo de la plataforma y flags del compilador.

Lo que comentan sobre si mov usa 3 o 4 bytes podria dejarse para aplicaciones muy especializadas  donde cada ciclo del procesador cuente.

No habia visto la diferencia en ASM sobre usar memoria en el stack o en el heap me parecen muy didacticos.

En línea

+ 1 Oculto(s)

Desconectado Desconectado

Mensajes: 298


un defecto se puede convertir en una virtud


Ver Perfil WWW
Re: ¿Que es más eficiente, utilizar array o memoria dinámica? [C]
« Respuesta #9 en: 5 Mayo 2016, 15:49 pm »

tienen diferentes propositos...

no puedes comparar

slds
En línea

Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Que tipo de lista dinamica me conviene utilizar? « 1 2 »
.NET (C#, VB.NET, ASP)
Skeletron 18 9,779 Último mensaje 13 Febrero 2010, 06:09 am
por Skeletron
Memoria dinámica
Programación C/C++
eleon 6 4,756 Último mensaje 24 Enero 2012, 22:17 pm
por Eternal Idol
Memoria dinamica? « 1 2 »
Programación C/C++
vangodp 11 5,186 Último mensaje 30 Abril 2014, 12:35 pm
por vangodp
Memoría dinámica
Programación C/C++
Developer Diego 4 2,405 Último mensaje 20 Mayo 2014, 23:10 pm
por Developer Diego
Generar Imagen dinámica con GD para utilizar de placeholder (Solucionado)
PHP
AlbertoBSD 4 2,175 Último mensaje 28 Diciembre 2019, 21:50 pm
por AlbertoBSD
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines