Je možné v linuxu alokovat velké množství virtuální paměti?
Možná. Možná však budete muset nakonfigurovat, aby byl povolen:
Linuxové jádro podporuje následující režimy zpracování přetížení
0 - Heuristické zpracování nadměrného závazku. Zjevné přeplnění adresního prostoru je odmítnuto. Používá se pro typický systém. Zajišťuje selhání alokace vážně divokého typu a zároveň umožňuje přetížení, aby se snížilo swapusování. root může v tomto režimu alokovat o něco více paměti. Toto je výchozí nastavení.
1 - Vždy převažujte. Vhodné pro některé vědecké aplikace. Klasickým příkladem je kód využívající řídká pole a spoléhající se pouze na virtuální paměť sestávající téměř výhradně z nula stránek.
2 - Nepřehánějte se. Celkové potvrzení adresního prostoru pro systém nesmí překročit swap + konfigurovatelné množství (výchozí je 50 %) fyzické RAM. V závislosti na množství, které používáte, to ve většině situací znamená, že proces nebude při přístupu na stránky zabit, ale podle potřeby obdrží chyby při alokaci paměti.
Užitečné pro aplikace, které chtějí zaručit, že jejich alokace paměti budou dostupné v budoucnu, aniž by museli inicializovat každou stránku.
Zásada overcommit se nastavuje pomocí sysctl `vm.overcommit_memory'.
Pokud tedy chcete alokovat více virtuální paměti, než máte fyzické paměti, pak byste chtěli:
# in shell
sysctl -w vm.overcommit_memory=1
RLIMIT_AS Maximální velikost virtuální paměti procesu (adresního prostoru) v bajtech. Tento limit ovlivňuje volání brk(2), mmap(2) a mremap(2), která selžou s chybou ENOMEM při překročení tohoto limitu. Také automatické rozšiřování zásobníku se nezdaří (a vygeneruje SIGSEGV, který proces ukončí, pokud přes sigaltstack(2) nebyl zpřístupněn žádný alternativní zásobník). Protože hodnota je dlouhá, na strojích s 32bitovou délkou je buď tento limit maximálně 2 GiB, nebo je tento zdroj neomezený.
Takže byste chtěli:
setrlimit(RLIMIT_AS, {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
});
Nebo, pokud k tomu nemůžete dát procesu oprávnění, můžete to trvale nakonfigurovat v /etc/security/limits.conf, což ovlivní všechny procesy (uživatele/skupiny).
Ok, takže se zdá, že mmap podporuje ... ale vyžaduje deskriptor souboru. ... může být výhra, ale ne, pokud musí být podložena souborem ... nelíbí se mi představa připojování k souboru
Nemusíte používat soubor mmap zálohovaný. Na to je MAP_ANONYMOUS.
Nevěděl jsem, jaké číslo mám zadat
Poté použijte null. Příklad:
mmap(nullptr, 256*GB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
To znamená, že pokud jste nakonfigurovali systém podle popisu, pak new
by měl fungovat stejně dobře jako mmap
. Pravděpodobně bude používat malloc
který bude pravděpodobně používat mmap
pro velké alokace, jako je tato.
Bonusová rada:Můžete využít výhod používání HugeTLB Pages.
Hodnota 256*GB
nezapadá do rozsahu typu 32bitové celé číslo. Zkuste uint64_t
jako typ GB
:
constexpr uint64_t GB = 1024*1024*1024;
nebo alternativně vynutit 64bitové násobení:
char* p = new char[256ULL * GB];
OT:Preferoval bych tuto definici GB
:
constexpr uint64_t GB = 1ULL << 30;
Pokud jde o limit virtuální paměti, viz tato odpověď.