Ist es möglich, unter Linux eine große Menge an virtuellem Speicher zuzuweisen?
Möglicherweise. Aber Sie müssen es möglicherweise so konfigurieren, dass es erlaubt ist:
Der Linux-Kernel unterstützt die folgenden Overcommit-Behandlungsmodi
0 - Heuristische Overcommit-Behandlung. Offensichtliche Adressraumüberschreitungen werden zurückgewiesen. Wird für ein typisches System verwendet. Es stellt sicher, dass eine ernsthaft wilde Zuweisung fehlschlägt, während Overcommit zugelassen wird, um die Swap-Nutzung zu reduzieren. root darf in diesem Modus etwas mehr Speicher zuweisen. Dies ist die Standardeinstellung.
1 – Immer überschreiben. Geeignet für einige wissenschaftliche Anwendungen. Ein klassisches Beispiel ist Code, der Sparse-Arrays verwendet und sich nur auf den virtuellen Speicher verlässt, der fast ausschließlich aus Nullseiten besteht.
2 - Übertreiben Sie es nicht. Die gesamte Adressraumzuweisung für das System darf Swap + eine konfigurierbare Menge (Standardwert ist 50 %) des physischen RAM nicht überschreiten. Abhängig von der Menge, die Sie verwenden, bedeutet dies in den meisten Situationen, dass ein Prozess beim Zugriff auf Seiten nicht beendet wird, sondern gegebenenfalls Fehler bei der Speicherzuweisung erhält.
Nützlich für Anwendungen, die sicherstellen möchten, dass ihre Speicherzuweisungen in Zukunft verfügbar sind, ohne jede Seite initialisieren zu müssen.
Die Overcommit-Richtlinie wird über die sysctl `vm.overcommit_memory' festgelegt.
Wenn Sie also mehr virtuellen Speicher zuweisen möchten, als Sie physischen Speicher haben, dann würden Sie Folgendes tun:
# in shell
sysctl -w vm.overcommit_memory=1
RLIMIT_AS Die maximale Größe des virtuellen Speichers (Adressraum) des Prozesses in Byte. Diese Grenze wirkt sich auf Aufrufe von brk(2), mmap(2) und mremap(2) aus, die mit dem Fehler ENOMEM fehlschlagen, wenn sie diese Grenze überschreiten. Auch die automatische Stapelerweiterung wird fehlschlagen (und ein SIGSEGV generieren, das den Prozess beendet, wenn kein alternativer Stapel über sigaltstack(2) verfügbar gemacht wurde). Da der Wert long ist, beträgt diese Grenze auf Maschinen mit 32-Bit-Long entweder höchstens 2 GiB oder diese Ressource ist unbegrenzt.
Sie möchten also:
setrlimit(RLIMIT_AS, {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
});
Oder, wenn Sie dem Prozess keine Erlaubnis dazu geben können, dann können Sie dies dauerhaft in /etc/security/limits.conf konfigurieren, was alle Prozesse (eines Benutzers/einer Gruppe) betrifft.
Ok, mmap scheint zu unterstützen ... aber es erfordert einen Dateideskriptor. ... könnte ein Gewinn sein, aber nicht, wenn sie durch eine Datei unterstützt werden müssen ... Ich mag die Idee nicht, an eine Datei anzuhängen
Sie müssen keine dateigestützte mmap verwenden. Dafür gibt es MAP_ANONYMOUS.
Ich wusste nicht, welche Nummer ich für die Anfrage eingeben sollte
Verwenden Sie dann null. Beispiel:
mmap(nullptr, 256*GB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Das heißt, wenn Sie das System wie beschrieben konfiguriert haben, dann new
sollte genauso gut funktionieren wie mmap
. Es wird wahrscheinlich malloc
verwenden die wahrscheinlich mmap
verwenden wird für große Zuordnungen wie diese.
Bonus-Tipp:Sie können von der Verwendung von HugeTLB Pages profitieren.
Der Wert von 256*GB
passt nicht in einen Bereich von 32-Bit-Ganzzahltypen. Versuchen Sie es mit uint64_t
als eine Art GB
:
constexpr uint64_t GB = 1024*1024*1024;
oder erzwingen Sie alternativ eine 64-Bit-Multiplikation:
char* p = new char[256ULL * GB];
OT:Ich würde diese Definition von GB
bevorzugen :
constexpr uint64_t GB = 1ULL << 30;
Informationen zum Limit des virtuellen Speichers finden Sie in dieser Antwort.