¿Cómo obtener memoria disponible C ++ / g ++?

Quiero asignar mis búferes de acuerdo a la memoria disponible. De modo que, cuando lo hago, el procesamiento y el uso de la memoria aumentan, pero aún permanece en los límites de memoria disponibles. ¿Hay alguna manera de obtener memoria disponible (no sé si el estado de la memoria virtual o física hará alguna diferencia?). El método tiene que ser plataforma independiente ya que se usará en Windows, OS X, Linux y AIX. (Y si es posible, también me gustaría asignar algo de memoria disponible para mi aplicación, alguien no cambia durante la ejecución).

Editar: lo hice con la asignación de memoria configurable. Entiendo que no es una buena idea, ya que la mayoría de los sistemas operativos administran la memoria para nosotros, pero mi aplicación era un marco ETL (destinado a ser utilizado en el servidor, pero también se utilizaba en el escritorio como complemento para el diseño de Adobe). Por lo tanto, me estaba ejecutando para emitir porque en lugar de usar swap, Windows devolvería mala alloc y otras aplicaciones comenzarían a fallar. Y como me enseñaron a evitar choques, estaba tratando de degradarme con gracia.

Después de leer estas respuestas, me asombra que muchos tomen la posición de que la memoria de la computadora de OP pertenece a otros. Es su computadora y su memoria las que tienen que ver con lo que crea conveniente, incluso si rompe otros sistemas que lo reclaman. Es una pregunta interesante. En un sistema más primitivo, tenía memavail() que me diría esto. ¿Por qué el OP no debería tomar tanta memoria como quiera sin molestar a otros sistemas?

Aquí hay una solución que asigna menos de la mitad de la memoria disponible, solo para ser amable. La salida fue:

FFFFFFFF requerido

Se requiere 7FFFFFFF

Obligatorio 3FFFFFFF

Tamaño de memoria asignado = 1FFFFFFF

 #include  #include  #define MINREQ 0xFFF // arbitrary minimum int main(void) { unsigned int required = (unsigned int)-1; // adapt to native uint char *mem = NULL; while (mem == NULL) { printf ("Required %X\n", required); mem = malloc (required); if ((required >>= 1) < MINREQ) { if (mem) free (mem); printf ("Cannot allocate enough memory\n"); return (1); } } free (mem); mem = malloc (required); if (mem == NULL) { printf ("Cannot enough allocate memory\n"); return (1); } printf ("Memory size allocated = %X\n", required); free (mem); return 0; } 

En sistemas operativos tipo UNIX, hay sysconf .

 #include  unsigned long long getTotalSystemMemory() { long pages = sysconf(_SC_PHYS_PAGES); long page_size = sysconf(_SC_PAGE_SIZE); return pages * page_size; } 

En Windows, hay GlobalMemoryStatusEx :

 #include  unsigned long long getTotalSystemMemory() { MEMORYSTATUSEX status; status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); return status.ullTotalPhys; } 

Así que solo haz algunos #ifdef sofisticados y estarás listo para ir.

Hay razones para querer hacer esto en HPC para software científico. (No juegos, web, negocios o software integrado). El software científico rutinariamente atraviesa terabytes de datos para pasar por un cómputo (o ejecución) (y se ejecuta durante horas o semanas), todos los cuales no pueden almacenarse en la memoria (y si un día me dices que un terabyte es estándar para cualquier PC o tableta o teléfono será el caso de que se espere que el software científico maneje petabytes o más). La cantidad de memoria también puede dictar el tipo de método / algoritmo que tenga sentido. El usuario no siempre quiere decidir la memoria y el método: tiene otras cosas de qué preocuparse. Entonces el progtwigdor debe tener una buena idea de lo que está disponible (4Gb o 8Gb o 64Gb o menos en estos días) para decidir si un método funcionará automáticamente o si se elegirá un método más laborioso. Se usa el disco, pero la memoria es preferible. Y los usuarios de dicho software no son alentados a hacer demasiadas cosas en su computadora cuando ejecutan dicho software, de hecho, a menudo usan máquinas / servidores dedicados.

No hay una plataforma independiente para hacer esto, los diferentes sistemas operativos usan diferentes estrategias de administración de memoria.

Estas otras preguntas de desbordamiento de stack ayudarán:

  • ¿Cómo obtener el uso de memoria en tiempo de ejecución en c ++?
  • API de uso de memoria C / C ++ en Linux / Windows

Sin embargo, debe tener cuidado: es notoriamente difícil obtener un valor “real” para la memoria disponible en Linux. Lo que el sistema operativo muestra como lo usa un proceso no es garantía de lo que realmente se asigna para el proceso.

Este es un problema común cuando se desarrollan sistemas embebidos de Linux, como enrutadores, donde se desea almacenar tanto como el hardware lo permita. Aquí hay un enlace a un ejemplo que muestra cómo obtener esta información en un Linux (en C):

Ejemplo de Mac OS X usando sysctl ( man 3 sysctl ):

 #include  #include  #include  #include  int main(void) { int mib[2] = { CTL_HW, HW_MEMSIZE }; u_int namelen = sizeof(mib) / sizeof(mib[0]); uint64_t size; size_t len = sizeof(size); if (sysctl(mib, namelen, &size, &len, NULL, 0) < 0) { perror("sysctl"); } else { printf("HW.HW_MEMSIZE = %llu bytes\n", size); } return 0; } 

(¿También puede funcionar en otros sistemas operativos similares a BSD?)

La función “oficial” para esto es std::get_temporary_buffer() . Sin embargo, es posible que desee probar si su plataforma tiene una implementación decente. Entiendo que no todas las plataformas se comportan como se desea.

El siguiente código brinda la memoria total y gratuita en megabytes. Funciona para FreeBSD, pero debería ser capaz de usar sysctl tunables iguales / similares en su plataforma y hacer lo mismo (Linux y OS X tienen sysctl al menos)

 #include  #include  #include  #include  #include  int main(){ int rc; u_int page_size; struct vmtotal vmt; size_t vmt_size, uint_size; vmt_size = sizeof(vmt); uint_size = sizeof(page_size); rc = sysctlbyname("vm.vmtotal", &vmt, &vmt_size, NULL, 0); if (rc < 0){ perror("sysctlbyname"); return 1; } rc = sysctlbyname("vm.stats.vm.v_page_size", &page_size, &uint_size, NULL, 0); if (rc < 0){ perror("sysctlbyname"); return 1; } printf("Free memory : %ld\n", vmt.t_free * (u_int64_t)page_size); printf("Available memory : %ld\n", vmt.t_avm * (u_int64_t)page_size); return 0; } 

A continuación se muestra el resultado del progtwig, en comparación con el resultado de vmstat (8) en mi sistema.

 ~/code/memstats % cc memstats.c ~/code/memstats % ./a.out Free memory : 5481914368 Available memory : 8473378816 ~/code/memstats % vmstat procs memory page disks faults cpu rbw avm fre flt re pi po fr sr ad0 ad1 in sy cs us sy id 0 0 0 8093M 5228M 287 0 1 0 304 133 0 0 112 9597 1652 2 1 97 

En lugar de tratar de adivinar, ¿ha considerado dejar que el usuario configure cuánta memoria usar para los almacenamientos intermedios, así como asumir valores predeterminados algo conservadores? De esta forma, aún puede ejecutar (posiblemente un poco más lento) sin anulación, pero si el usuario sabe que hay memoria X disponible para la aplicación, puede mejorar el rendimiento configurando esa cantidad.