Как получить доступную память C++ / g++?
Я хочу выделить мои буферы в соответствии с доступной памятью. Такой, что, когда я делаю обработку и использование памяти идет вверх, но все еще остается в доступных пределах памяти. Есть ли способ получить доступную память (я не знаю, будет ли состояние виртуальной или физической памяти иметь какое-либо значение ?). Метод должен быть независимым от платформы, поскольку он будет использоваться в Windows, OS X, Linux и AIX. (И если это возможно, то я также хотел бы выделить часть доступной памяти для моего приложения, кто-то он не меняется во время выполнения).
Edit: я сделал это с настраиваемым выделением памяти.
Я понимаю, что это не очень хорошая идея, так как большинство ОС управляют памятью для нас, но мое приложение было платформой ETL (предназначенной для использования на сервере, но также использовалось на рабочем столе в качестве плагина для Adobe indesign). Итак, я работал над проблемой, потому что вместо использования swap windows вернет bad alloc, а другие приложения начнут отказывать. И как меня учили избегать аварий и так, было просто пытаюсь изящно деградировать.
8 ответов:
прочитав эти ответы, я удивлен, что так много занимают позицию, что компьютерная память OP принадлежит другим. Это его компьютер и его память делать с тем, как он считает нужным, даже если он ломает другие системы, принимая претензии на него. Это интересный вопрос. На более примитивной системе у меня было
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; }
в 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; }так что просто сделать некоторые фантазии
#ifdefS и вы будете хорошо идти.
есть причины, чтобы сделать это в HPC для научного программного обеспечения. (Не игра, веб, бизнес или встроенное программное обеспечение). Научное программное обеспечение обычно проходит через терабайты данных, чтобы пройти через одно вычисление (или запустить) (и запустить в течение нескольких часов или недель) - все из которых не могут быть сохранены в памяти (и если однажды вы скажете мне, что терабайт является стандартным для любого ПК, планшета или телефона, это будет случай, когда научное программное обеспечение будет обрабатывать петабайты или больше). Сумма память также может диктовать вид метода / алгоритма, который имеет смысл. Пользователь не всегда хочет решать память и метод - у него есть другие вещи, о которых нужно беспокоиться. Таким образом, программист должен иметь хорошее представление о том, что доступно (4 ГБ или 8 ГБ или 64 ГБ или около того в эти дни), чтобы решить, будет ли метод автоматически работать или более трудоемкий метод должен быть выбран. Диск используется, но память предпочтительнее. И пользователи такого программного обеспечения не рекомендуется делать слишком много вещей на их компьютер при запуске такого программного обеспечения-на самом деле, они часто используют выделенные машины/серверы.
нет независимого от платформы способа сделать это, разные операционные системы используют разные стратегии управления памятью.
эти другие вопросы переполнения стека помогут:
- как получить использование памяти во время выполнения в C++?
- C/C++ API использования памяти в Linux / Windows
вы должны следить, хотя: трудно получить "реальное" значение памяти в Linux. Что? операционная система отображается так, как используется процессом, не является гарантией того, что на самом деле выделено для процесса.
Это распространенная проблема при разработке встроенных систем linux, таких как маршрутизаторы, где вы хотите буферизировать столько, сколько позволяет оборудование. Вот ссылка на пример, показывающий, как получить эту информацию в Linux (в В):
пример 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-подобных операционных системах ?)
"официальная" функция для этого
std::get_temporary_buffer(). Однако вы можете проверить, имеет ли ваша платформа достойную реализацию. Я понимаю, что не все платформы ведут себя так, как хотелось.
приведенный ниже код дает общую и свободную память в мегабайтах. Работает для 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
вместо того, чтобы пытаться угадать, вы подумали о том, чтобы позволить пользователю настроить, сколько памяти использовать для буферов, а также предполагать несколько консервативные значения по умолчанию? Таким образом, вы все еще можете работать (возможно, немного медленнее) без переопределения, но если пользователь знает, что для приложения доступна память X, они могут повысить производительность, настроив эту сумму.
Comments