Как получить доступную память C ++ / g ++? - PullRequest
59 голосов
/ 25 марта 2010

Я хочу распределить свои буферы в соответствии с доступной памятью. Так, что когда я делаю обработку и использование памяти увеличивается, но все еще остается в доступных пределах памяти. Есть ли способ получить доступную память (я не знаю, изменится ли состояние виртуальной или физической памяти?). Метод должен быть независимым от платформы, так как он будет использоваться в Windows, OS X, Linux и AIX. (И если это возможно, я бы также хотел выделить часть доступной памяти для моего приложения, которая не изменится во время выполнения).

Редактировать: я сделал это с настраиваемым распределением памяти. Я понимаю, что это не очень хорошая идея, так как большинство ОС управляют памятью для нас, но моим приложением была среда ETL (предназначенная для использования на сервере, но также использовавшаяся на рабочем столе в качестве плагина для Adobe indesign). Итак, я работал над проблемой, потому что вместо использования подкачки окна возвращали неверное размещение, а другие приложения начинали давать сбой. И, как меня учили избегать сбоев и так далее, просто пытался изящно деградировать.

Ответы [ 8 ]

136 голосов
/ 25 марта 2010

В UNIX-подобных операционных системах есть 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;
}

В Windows есть GlobalMemoryStatusEx:

#include <windows.h>

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

Так что просто сделайте несколько фантазий #ifdef с, и вам будет хорошо.

29 голосов
/ 14 июня 2013

Есть причины хотеть сделать это в HPC для научного программного обеспечения.(Не для игры, Интернета, бизнеса или встроенного программного обеспечения).Научное программное обеспечение регулярно проходит через терабайты данных, чтобы пройти одно вычисление (или запустить) (и запустить в течение нескольких часов или недель) - все это не может быть сохранено в памяти (и если однажды вы скажете, что терабайт является стандартным для любого ПКили планшет или телефон, это будет случай, когда научное программное обеспечение будет обрабатывать петабайты или более).Объем памяти также может определять способ / алгоритм, который имеет смысл.Пользователь не всегда хочет выбирать память и метод - ему / ей нужно беспокоиться о других вещах.Таким образом, программист должен иметь четкое представление о том, что доступно (4Gb или 8Gb или 64Gb или около того в наши дни), чтобы решить, будет ли метод автоматически работать или будет выбран более трудоемкий метод.Диск используется, но память предпочтительнее.И пользователям такого программного обеспечения не рекомендуется делать слишком много вещей на своем компьютере при запуске такого программного обеспечения - фактически они часто используют выделенные машины / серверы.

13 голосов
/ 29 октября 2014

Прочитав эти ответы, я удивляюсь, что так много людей считают, что компьютерная память ОП принадлежит другим. Это его компьютер и его память, которые он может использовать по своему усмотрению, даже если это ломает другие системы, требуя его. Это интересный вопрос. В более примитивной системе у меня был memavail(), который сказал бы мне это. Почему ОП не должен занимать столько памяти, сколько он хочет, не расстраивая другие системы?

Вот решение, которое выделяет менее половины доступной памяти, просто чтобы быть добрым. Вывод был:

Обязательный FFFFFFFF

Требуется 7FFFFFFF

Требуется 3FFFFFFF

Объем выделенной памяти = 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;
}
11 голосов
/ 25 марта 2010

Нет независимого от платформы способа сделать это, разные операционные системы используют разные стратегии управления памятью.

Эти другие вопросы переполнения стека помогут:

Вы должны остерегаться, хотя: общеизвестно, что трудно получить «реальное» значение для доступной памяти в Linux. То, что операционная система отображает как используемое процессом, не является гарантией того, что фактически выделено для процесса.

Это распространенная проблема при разработке встроенных систем Linux, таких как маршрутизаторы, где вы хотите буферизовать столько, сколько позволяет аппаратное обеспечение. Вот ссылка на пример, показывающий, как получить эту информацию в Linux (в C):

5 голосов
/ 25 марта 2010

Пример Mac OS X с использованием 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;
}

(может также работать в других BSD-подобных операционных системах?)

3 голосов
/ 23 мая 2016

Приведенный ниже код дает общий объем свободной памяти в мегабайтах. Работает для FreeBSD, но вы должны иметь возможность использовать те же / аналогичные переменные sysctl на своей платформе и делать то же самое (Linux и OS X имеют 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;
}

Ниже приведен вывод программы по сравнению с выводом vmstat (8) в моей системе.

~/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 голосов
/ 25 марта 2010

«Официальная» функция для этого - была std::get_temporary_buffer(). Однако вы можете проверить, имеет ли ваша платформа достойную реализацию. Я понимаю, что не все платформы ведут себя так, как хотелось бы.

1 голос
/ 25 марта 2010

Вместо того, чтобы пытаться угадать, рассматривали ли вы вопрос о том, чтобы позволить пользователю настроить объем памяти, используемый для буферов, а также предполагать несколько консервативные значения по умолчанию? Таким образом, вы все еще можете работать (возможно, немного медленнее) без переопределения, но если пользователь знает, что для приложения доступно X памяти, он может улучшить производительность, настроив этот объем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...