Jak uzyskać dostępną pamięć C++ / g++?

Chcę przydzielić moje bufory według dostępnej pamięci. Takie, że, gdy robię przetwarzanie i zużycie pamięci idzie w górę, ale nadal pozostaje w dostępnych granicach pamięci. Czy jest jakiś sposób, aby uzyskać dostępną pamięć (Nie wiem, czy stan pamięci wirtualnej lub fizycznej zrobi jakąś różnicę ?). Metoda musi być niezależna od platformy, ponieważ będzie używana w systemach Windows, OS X, Linux i AIX. (A jeśli to możliwe, to chciałbym również przeznaczyć część dostępnej pamięci dla mojej aplikacji, ktoś to nie zmienia się podczas wykonywania).

Edit: zrobiłem to z konfigurowalną alokacją pamięci. Rozumiem, że nie jest to dobry pomysł, ponieważ większość OS zarządza pamięcią dla nas, ale moja aplikacja była frameworkiem ETL(przeznaczonym do użycia na serwerze, ale był również używany na pulpicie jako wtyczka dla Adobe indesign). Więc, byłem uruchomiony w problem ponieważ zamiast używać swap, windows zwróci zły alloc i inne aplikacje zaczynają się nie udać. I jak uczono mnie unikać wypadków i tak, było po prostu staram się degradować z wdziękiem.

Author: theCakeCoder, 2010-03-25

8 answers

Po przeczytaniu tych odpowiedzi jestem zaskoczony, że tak wielu przyjmuje stanowisko, że pamięć komputerowa OP należy do innych. To jego komputer i jego pamięć do robienia tego, co uzna za stosowne, nawet jeśli złamie inne systemy. Ciekawe pytanie. Na bardziej prymitywnym systemie miałem memavail(), który powiedziałby mi to. Dlaczego operacja nie powinna zabierać tyle pamięci, ile chce, bez denerwowania innych systemów?

Oto rozwiązanie, które przydziela mniej niż połowa dostępnej pamięci. Wyjście było:

Wymagane FFFFFFFF

Wymagane 7FFFFFFF

Wymagane 3FFFFFFF

Wielkość pamięci przydzielona = 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;
}
 12
Author: Weather Vane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-29 20:43:28

W systemach operacyjnych uniksopodobnych istnieje 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;
}

W systemie Windows jest GlobalMemoryStatusEx:

#include <windows.h>

unsigned long long getTotalSystemMemory()
{
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx(&status);
    return status.ullTotalPhys;
}
Więc po prostu zrób coś wymyślnego, a będziesz gotowy.
 122
Author: Travis Gockel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 18:54:25

Istnieją powody, dla których warto to zrobić w HPC dla oprogramowania naukowego. (Nie gier, stron internetowych, oprogramowania biznesowego lub wbudowanego). Oprogramowanie naukowe rutynowo przejść przez terabajty danych, aby uzyskać przez jednego obliczenia (lub uruchomić) (i uruchomić przez godziny lub tygodnie) - z których wszystkie nie mogą być przechowywane w pamięci (i jeśli pewnego dnia powiesz mi terabajt jest standardem dla każdego komputera PC lub tabletu lub telefonu będzie to przypadek, że oprogramowanie naukowe będzie oczekiwać obsługi petabajtów lub więcej). Ilość pamięci może również dyktować rodzaj metody / algorytmu, który ma sens. Użytkownik nie zawsze chce decydować o pamięci i metodzie-ma inne zmartwienia. Tak więc programista powinien mieć dobry pomysł na to, co jest dostępne (4GB lub 8Gb lub 64GB lub mniej więcej w dzisiejszych czasach), aby zdecydować, czy metoda będzie działać automatycznie, czy też należy wybrać bardziej pracochłonną metodę. Dysk jest używany, ale pamięć jest preferowana. I użytkownicy takiego oprogramowania nie są zachęcani do robienia zbyt wielu rzeczy na swoich komputer podczas uruchamiania takiego oprogramowania-w rzeczywistości często używają dedykowanych maszyn/serwerów.

 24
Author: Paresh M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-14 12:01:04

Nie ma na to sposobu niezależnego od platformy, różne systemy operacyjne wykorzystują różne strategie zarządzania pamięcią.

Inne pytania dotyczące przepełnienia stosu pomogą:

Powinieneś jednak uważać: notorycznie trudno jest uzyskać "rzeczywistą" wartość dostępnej pamięci w Linuksie. Co wyświetla system operacyjny używany przez proces nie jest gwarancją tego, co jest faktycznie przydzielone dla procesu.

Jest to częsty problem podczas tworzenia wbudowanych systemów linux, takich jak routery, gdzie chcesz buforować tyle, ile pozwala na to sprzęt. Oto link do przykładu pokazującego, jak uzyskać te informacje w Linuksie (w C):

 9
Author: mikelong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:07

Przykład Mac OS X przy użyciu 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;
}

(może działać również na innych systemach operacyjnych podobnych do BSD ?)

 5
Author: Paul R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-25 08:55:52

"oficjalną" funkcją jest std::get_temporary_buffer(). Możesz jednak sprawdzić, czy Twoja platforma ma przyzwoitą implementację. Rozumiem, że nie wszystkie platformy zachowują się zgodnie z życzeniem.

 3
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-25 09:04:25

Poniższy kod podaje całkowitą i wolną pamięć w megabajtach. Działa na FreeBSD, ale powinieneś być w stanie używać tych samych / podobnych tunabli sysctl na swojej platformie i robić to samo (Linux i OS X mają przynajmniej sysctl)

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

Poniżej znajduje się wyjście programu, w porównaniu z wyjściem vmstat(8) w moim systemie.

~/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
 3
Author: Fehmi Noyan ISI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-23 09:31:11

Zamiast zgadywać, czy rozważyłeś pozwolenie użytkownikowi na skonfigurowanie ilości pamięci do wykorzystania w buforach, a także założenie nieco konserwatywnych domyślnych wartości? W ten sposób możesz nadal działać (prawdopodobnie nieco wolniej) bez nadpisywania, ale jeśli użytkownik wie, że dostępna jest pamięć X dla aplikacji, może poprawić wydajność, konfigurując tę ilość.

 0
Author: Mark B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-25 13:45:53