2010-03-25 19 views
49

Quiero asignar mis búferes de acuerdo con 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).¿Cómo obtener memoria disponible C++/g ++?

Editar: Lo hice con 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 usaba 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.

+12

No tiene sentido hacer esto.En todos los sistemas operativos modernos, la memoria utilizada por una aplicación no afecta la memoria disponible para otras aplicaciones, ya que es completamente virtual. Solo asigna lo que requieres. –

+4

@LokiAstari: falso, por supuesto. un sistema tiene mucho que puede asignar. Elegí no tener archivos de intercambio, por lo que mi sistema tiene 8GiB, después de eso, C++ llama a 'new' throw' bad_alloc' y falla otra aplicación. En linux y ventanas recientes hay un OOM Killer que elegirá una aplicación para matar. un virus podría asignar muchas cosas en múltiples procesos y usar ese hecho para bloquear otras aplicaciones. Sin mencionar, si tiene un archivo de página, el sistema se acumulará y se congelará hasta que no se pueda usar. (generalmente el WM solo muere, pero en Windows no hay Ctrl-Alt-F1) –

+1

@ v.oddou: nada de eso es relevante para el contexto de la pregunta. Por lo tanto, mi comentario se mantiene. –

Respuesta

13

Después de leer estas respuestas, estoy asombrado de que muchos tomen la posición de que la memoria de la computadora de OP pertenece a otros. Es su computadora y su memoria tiene 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 decí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 producción fue de:

Obligatorio FFFFFFFF

Obligatorio 7FFFFFFF

Obligatorio 3FFFFFFF

tamaño de memoria asignada = 1FFFFFFF

#include <stdio.h> 
#include <stdlib.h> 

#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; 
} 
+1

en Linux, puede usar el comando binutils 'free' (¿o es un comando bash? Tal vez) puede ejecutar usando' execve' o 'system'. Un enfoque divertido también podría intentar asignar (y escribir en 1) hasta que no se detecte la memoria disponible. sin mencionar la velocidad de verificación para que se detecte el intercambio. –

+8

Esta es una solución extremadamente * horrible *. Imagine que está trabajando en una computadora y, de repente, comienza a intercambiarse y se ralentiza, y algunas aplicaciones fallan debido a la falta de memoria y una conexión de red falla, etc. Se aterroriza de tener software malicioso, apagado o funcionamiento de antivirus. y descubra que esto fue causado por alguna aplicación tonta que asignaba y liberaba cantidades enormes de memoria que ni siquiera necesita. – Michael

+0

@Michael Creo que estoy dispuesto a estar de acuerdo contigo, pero luego no desarrollaría código en una máquina en la que todo lo que se ejecuta realmente importara. –

9

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 pila ayudará:

Usted debe mirar hacia fuera sin embargo: Es muy difícil de 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):

+0

linux usa asignación diferida, puede garantizar que la memoria se asigna escribiendo en ella. –

112

En los sistemas operativos UNIX, no es sysconf.

#include <unistd.h> 

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

En Windows, no es GlobalMemoryStatusEx:

#include <windows.h> 

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

Así que sólo lo hacen algunos de lujo #ifdef s y usted estará listo para salir.

Y para que no producen marcas por una tonelada ... como otros han dicho, no debe ocupar todo el espacio disponible y probablemente hay mejores maneras de hacer lo que realmente quiere hacer. Esta técnica realmente no le da la misma definición de cantidad de memoria, ya que algunos sistemas operativos usarán "páginas" para significar lo que quieran (búferes de disco, dispositivos de E/S). Hay una gran desconexión de entre el espacio de memoria al que tiene acceso y los bytes físicos en la RAM (busque el translation lookaside buffer para solo un ejemplo de esto).

+0

No creo que recibas downvoted por eso ya que * es * realmente útil. Podemos sugerir que es una mala idea tanto como nos gusta, pero, si alguien realmente quiere hacer algo tonto (aunque dudo en usar esa palabra), ¿quiénes somos para negarles las herramientas? – paxdiablo

+5

no es que quiera agotar toda la memoria, es que no quiero ir y cargar demasiados datos que no puedo procesar con la memoria disponible (quiero permanecer adentro sin usar o algún espacio que no probablemente sea accedido por otros procesos). De nuevo, no quiero ser tonto si quiero asignar toda la memoria disponible pero quiero decidir qué límite debo poner en la aplicación para que no absorba toda la memoria y se cuelgue ~ ___ ~ – theCakeCoder

+1

Para algunos sistemas operativos ' sysctl' puede ser una mejor alternativa a 'sysconf'. Ver 'man 3 sysctl'. –

4

Mac OS X ejemplo usando sysctl (man 3 sysctl):

#include <stdio.h> 
#include <stdint.h> 
#include <sys/types.h> 
#include <sys/sysctl.h> 

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 BSD-como?)

+4

Esto devuelve la memoria física total en el sistema, memoria no disponible (libre). –

2

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.

0

En lugar de intentar 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.

24

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 programador 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.

+0

No era exactamente un software científico, califico que era más que construir un marco de ETL, por supuesto, estaba destinado a ejecutarse en servidores dedicados. Probablemente, necesitaba una memoria máxima permitida como, Java o Maltab toma como parámetro de inicio. – theCakeCoder

+0

Hay razones para hacer esto con el software de renderizado al menos. Desea usar tanta memoria como tenga. por ejemplo: la memoria física disponible (× α con 0.5 <α <0.8) será el límite para el tamaño del mapa de fotones. + some 'min (physi, 2GiB)' para evitar que las máquinas con 256 GB de RAM tarden una eternidad en construir el mapa de fotones. pero aún. También puede imaginar itinerancia en juegos, he visto motores que transmiten activos IN y OUT para mantener un objetivo de memoria. Cuanta más memoria tenga, más lejos podrá ver. –

3

El código de abajo da la memoria total y libre en megabytes. Funciona para FreeBSD, pero usted debería ser capaz de utilizar mismas sintonizables de sysctl/similares de la plataforma y hacer lo mismo (Linux & OS X tienen sysctl al menos)

#include <stdio.h> 
#include <errno.h> 

#include <sys/types.h> 
#include <sys/sysctl.h> 
#include <sys/vmmeter.h> 

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 la salida del programa, en comparación con la salida 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 
r b w  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 
Cuestiones relacionadas