To wydaje się być bardzo częstym problemem, ale nadal nie znalazłem jednoznacznej odpowiedzi.Przydziel więcej niż 2 GB na stercie za pomocą C++ na 32-bitowym jądrze linuxowym
Mam dostęp do serwera, na którym działa Linux, ma 16 GB pamięci RAM i 16-rdzeniowy (64-bitowy) procesor (/ proc/cpuinfo podaje "Procesor Intel (R) Xeon (R) E5520 @ 2.27GHz"). Jednak jądro ma 32 bity (uname -m daje i686). Oczywiście nie mam dostępu do roota, więc nie mogę zmienić tego .
Używam C++ - program, który napisałem, który wykonuje pewne obliczenia pamięci głodny, więc muszę Big sterty - ale gdy próbuję przeznaczyć więcej niż 2 GB, dostaję badalloc, chociaż ULimit zwrotów "Nieograniczony". Dla uproszczenia powiedzmy, mój program jest taki:
#include <iostream>
#include <vector>
int main() {
int i = 0;
std::vector<std::vector<int> > vv;
for (;;) {
++i;
vv.resize(vv.size() + 1);
std::vector<int>* v = &(vv.at(vv.size() - 1));
v->resize(1024 * 1024 * 128);
std::cout << i * 512 << " MB.\n";
}
return 0;
}
Po kompilacji z g ++ (bez flag), wyjście jest:
512 MB.
1024 MB.
1536 MB.
2048 MB.
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
O ile rozumiem, to jest ograniczenie Systemy 32-bitowe, najwyraźniej dlatego, że 32-bitowy wskaźnik może pomieścić 2^32 różnych adresów (czy mogę słusznie przypuszczać, że jeśli skompilowałem ten sam program na tym samym serwerze, ale ten serwer miał jądro 64-bitowe, to program mógł przydzielić więcej niż 2 GB?)
Nie chodzi o to, czy przydzielona pamięć jest przyległa, czy o cieńszy cień w przykładowym programie , ten sam problem występuje, aw moim rzeczywistym programie nie ma dużych bloków pamięci , tylko wiele małych .
Moje pytanie brzmi: Czy jest coś, co mogę zrobić? Nie mogę zmienić systemu operacyjnego, ale oczywiście mogę zmodyfikować mój kod źródłowy, używać różnych opcji kompilatora itp. ... , ale potrzebuję więcej niż 2 GB pamięci, wszystko na raz, i nie ma oczywistego sposobu na dalszą optymalizację algorytm używany przez program.
Jeśli odpowiedź brzmi "nie", dobrze by było o tym wiedzieć.
Dzięki, Lukas
(1) Użyj 64-bitowego systemu operacyjnego i aplikacji natywnej. (2) Włącz obsługę [rozszerzenia adresu fizycznego] (http://en.wikipedia.org/wiki/Physical_Address_Extension#Operating_system_support) na komputerze docelowym, jeśli ma on 32 bity. To powinno ci kupić dodatkowy gB do pracy. Poza tym (co wydaje się, że jesteś przypięty do całkiem wąskich możliwości) samodzielnie zarządzany system stronicowania dysku może być Twoją jedyną opcją. – WhozCraig
* Czy mam rację, zakładając, że jeśli skompilowałem ten sam program na tym samym serwerze, ale ten serwer miał jądro 64-bitowe, to program mógł przydzielić więcej niż 2 GB? * - Tak. Możesz * może * być w stanie trochę lepiej wypróbować (może nawet do 3,5 Gb/s) przy pomocy przełączników itp. Zasadniczo, chociaż masz problem z skalowalnością i jeśli naprawdę nie możesz znaleźć sposobu na podzielenie przetwarzania według czasu lub proces, aby uniknąć trafienia limitu, musisz przejść do wersji 64-bitowej. –
Czy uda mu się obejść ten problem, ponieważ wiele procesów alokuje po 2 GB. Następnie wymyśl mechanizm IPC do odczytu/zapisu danych do fragmentów pamięci innego procesu, w razie potrzeby? Lub po prostu uruchomić jedną lub więcej instancji memcached? – selbie