Come ottenere la memoria disponibile C ++ / g ++?

Voglio allocare i miei buffer in base alla memoria disponibile. Tale che, quando faccio l’elaborazione e l’utilizzo della memoria sale, ma rimane ancora nei limiti di memoria disponibili. C’è un modo per ottenere la memoria disponibile (non so se lo stato della memoria virtuale o fisica farà alcuna differenza?). Il metodo deve essere indipendente dalla piattaforma poiché verrà utilizzato su Windows, OS X, Linux e AIX. (E se ansible, vorrei anche allocare parte della memoria disponibile per la mia applicazione, qualcuno non cambia durante l’esecuzione).

Modifica: l’ho fatto con l’allocazione di memoria configurabile. Capisco che non sia una buona idea, dato che la maggior parte dei sistemi operativi gestiscono la memoria per noi, ma la mia applicazione era un framework ETL (destinato a essere utilizzato sul server, ma era anche utilizzato sul desktop come plugin per Adobe indesign). Quindi, stavo correndo al problema perché invece di usare swap, windows restituiva allocazione errata e altre applicazioni iniziano a fallire. E come mi è stato insegnato per evitare incidenti e così, stavo solo cercando di degradare con grazia.

Avendo letto queste risposte, sono stupito dal fatto che così tanti prendano la posizione che la memoria del computer dell’OP appartiene agli altri. È il suo computer e la sua memoria a fare ciò che ritiene opportuno, anche se rompe altri sistemi che lo rivendicano. È una domanda interessante Su un sistema più primitivo avevo memavail() che mi avrebbe detto questo. Perché l’OP non dovrebbe prendere tutta la memoria che vuole senza sconvolgere altri sistemi?

Ecco una soluzione che alloca meno della metà della memoria disponibile, solo per essere gentile. L’output era:

FFFFFFFF richiesto

Richiesto 7FFFFFFF

Richiesto 3FFFFFFF

Dimensione della memoria allocata = 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; } 

Sui sistemi operativi UNIX-like, c’è sysconf .

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

Su Windows, c’è GlobalMemoryStatusEx :

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

Quindi fai un po ‘di #ifdef e sarai #ifdef per andare.

Ci sono motivi per voler farlo in HPC per software scientifico. (Non giochi, web, business o software incorporato). I software scientifici passano regolarmente attraverso terabyte di dati per passare da un calcolo (o un’esecuzione) (e vengono eseguiti per ore o settimane) – i quali non possono essere archiviati in memoria (e se un giorno mi dici che un terabyte è standard per qualsiasi PC o tablet o telefono sarà il caso che il software scientifico dovrà gestire petabyte o più). La quantità di memoria può anche dettare il tipo di metodo / algoritmo che ha senso. L’utente non sempre vuole decidere la memoria e il metodo – lui / lei ha altre cose di cui preoccuparsi. Quindi il programmatore dovrebbe avere una buona idea di ciò che è disponibile (4Gb o 8Gb o 64Gb o giù di lì in questi giorni) per decidere se un metodo funzionerà automaticamente o se sarà scelto un metodo più laborioso. Il disco è usato ma la memoria è preferibile. E gli utenti di tale software non sono incoraggiati a fare troppe cose sul proprio computer quando eseguono tale software – infatti, usano spesso macchine / server dedicati.

Non esiste un modo indipendente dalla piattaforma per farlo, i diversi sistemi operativi utilizzano diverse strategie di gestione della memoria.

Queste altre domande di overflow dello stack aiuteranno:

  • Come ottenere l’utilizzo della memoria in fase di esecuzione in c ++?
  • API di utilizzo della memoria C / C ++ in Linux / Windows

Dovresti fare attenzione però: è notoriamente difficile ottenere un valore “reale” per la memoria disponibile in linux. Ciò che il sistema operativo mostra come utilizzato da un processo non è una garanzia di ciò che viene effettivamente assegnato per il processo.

Questo è un problema comune nello sviluppo di sistemi Linux embedded come i router, in cui si desidera memorizzare il buffer tanto quanto l’hardware lo consente. Ecco un link ad un esempio che mostra come ottenere queste informazioni in un linux (in C):

Esempio di Mac OS X utilizzando 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; } 

(potrebbe funzionare anche su altri sistemi operativi simili a BSD?)

La funzione “ufficiale” per questo è std::get_temporary_buffer() . Tuttavia, potresti voler verificare se la tua piattaforma ha una buona implementazione. Capisco che non tutte le piattaforms si comportano come desiderato.

Il codice qui sotto fornisce la memoria totale e libera in Megabyte. Funziona con FreeBSD, ma dovresti essere in grado di usare lo stesso / simile sintonizzatore sysctl sulla tua piattaforma e fare lo stesso con la stessa cosa (Linux e OS X hanno almeno sysctl)

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

Di seguito è riportato l'output del programma, confrontato con l'output vmstat (8) sul mio 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 

Invece di provare a indovinare, hai considerato di consentire all’utente di configurare la quantità di memoria da utilizzare per i buffer, oltre ad assumere valori predefiniti piuttosto conservativi? In questo modo è ancora ansible eseguire (eventualmente leggermente più lento) senza override, ma se l’utente sa che è disponibile una memoria X per l’app, è ansible migliorare le prestazioni configurando tale quantità.