Je souhaite allouer mes tampons en fonction de la mémoire disponible. Tels que, lorsque je fais du traitement et que l'utilisation de la mémoire augmente, mais reste dans les limites de mémoire disponibles. Existe-t-il un moyen d'obtenir de la mémoire disponible (je ne sais pas si l'état de la mémoire virtuelle ou physique fera une différence?). La méthode doit être indépendante de la plate-forme car elle sera utilisée sur Windows, OS X, Linux et AIX. (Et si possible, je voudrais également allouer une partie de la mémoire disponible pour mon application, quelqu'un qu'elle ne change pas pendant l'exécution).
Edit: je l'ai fait avec l'allocation de mémoire configurable. Je comprends que ce n'est pas une bonne idée, car la plupart des systèmes d'exploitation gèrent la mémoire pour nous, mais mon application était un cadre ETL (destiné à être utilisé sur le serveur, mais était également utilisé sur le bureau comme plugin pour Adobe indesign). Donc, je rencontrais un problème car au lieu d'utiliser swap, Windows retournerait une mauvaise allocation et d'autres applications commenceraient à échouer. Et comme on m'a appris à éviter les accidents et ainsi, j'essayais simplement de me dégrader gracieusement.
Après avoir lu ces réponses, je suis étonné que tant de gens considèrent que la mémoire informatique d'OP appartient à d'autres. C'est son ordinateur et sa mémoire à utiliser comme bon lui semble, même si cela casse d'autres systèmes en le réclamant. C'est une question intéressante. Sur un système plus primitif, j'avais memavail()
qui me disait cela. Pourquoi l'OP ne prendrait-il pas autant de mémoire qu'il le souhaite sans perturber les autres systèmes?
Voici une solution qui alloue moins de la moitié de la mémoire disponible, juste pour être gentil. La sortie était:
Obligatoire FFFFFFFF
Requis 7FFFFFFF
Obligatoire 3FFFFFFF
Taille de mémoire allouée = 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;
}
Sur les systèmes d'exploitation de type UNIX, il y a 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;
}
Sous Windows, il y a GlobalMemoryStatusEx
:
#include <windows.h>
unsigned long long getTotalSystemMemory()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys;
}
Alors faites juste un peu de fantaisie #ifdef
s et vous serez prêt à partir.
Il y a des raisons de vouloir le faire dans HPC pour les logiciels scientifiques. (Pas de jeu, Web, entreprise ou logiciel intégré). Les logiciels scientifiques parcourent régulièrement des téraoctets de données pour effectuer un calcul (ou une exécution) (et s'exécuter pendant des heures ou des semaines) - qui ne peuvent pas tous être stockés en mémoire (et si un jour vous me dites qu'un téraoctet est standard pour n'importe quel PC ou une tablette ou un téléphone, il est probable que le logiciel scientifique puisse gérer des pétaoctets ou plus). La quantité de mémoire peut également dicter le type de méthode/algorithme qui a du sens. L'utilisateur ne veut pas toujours décider de la mémoire et de la méthode - il/elle a d'autres choses à se soucier. Le programmeur doit donc avoir une bonne idée de ce qui est disponible (4 Go ou 8 Go ou 64 Go ou environ de nos jours) pour décider si une méthode fonctionnera automatiquement ou si une méthode plus laborieuse doit être choisie. Le disque est utilisé mais la mémoire est préférable. Et les utilisateurs de ces logiciels ne sont pas encouragés à faire trop de choses sur leur ordinateur lorsqu'ils exécutent de tels logiciels - en fait, ils utilisent souvent des machines/serveurs dédiés.
Il n'y a pas de moyen indépendant de la plateforme pour ce faire, différents systèmes d'exploitation utilisent différentes stratégies de gestion de la mémoire.
Ces autres questions de débordement de pile aideront:
Attention cependant: il est notoirement difficile d'obtenir une "vraie" valeur pour la mémoire disponible sous Linux. Ce que le système d'exploitation affiche tel qu'utilisé par un processus ne garantit pas ce qui est réellement alloué au processus.
C'est un problème courant lors du développement de systèmes Linux embarqués tels que des routeurs, où vous souhaitez mettre en mémoire tampon autant que le matériel le permet. Voici un lien vers un exemple montrant comment obtenir ces informations dans un linux (en C):
Exemple Mac OS X utilisant 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;
}
(peut également fonctionner sur d'autres systèmes d'exploitation de type BSD?)
Le code ci-dessous donne la mémoire totale et libre en mégaoctets. Fonctionne pour FreeBSD, mais vous devriez pouvoir utiliser les mêmes paramètres sysctl/similaires sur votre plate-forme et faire la même chose (Linux et OS X ont au moins 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;
}
Voici la sortie du programme, comparée à la sortie vmstat (8) sur mon système.
~/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
La fonction "officielle" de cette est était std::get_temporary_buffer()
. Cependant, vous voudrez peut-être tester si votre plate-forme a une implémentation décente. Je comprends que toutes les plateformes ne se comportent pas comme souhaité.
Au lieu d'essayer de deviner, avez-vous envisagé de laisser l'utilisateur configurer la quantité de mémoire à utiliser pour les tampons, ainsi que de supposer des valeurs par défaut quelque peu conservatrices? De cette façon, vous pouvez toujours exécuter (peut-être légèrement plus lentement) sans remplacement, mais si l'utilisateur sait qu'il y a de la mémoire X disponible pour l'application, il peut améliorer les performances en configurant cette quantité.