2013-02-08 17 views
5

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

(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

+0

* 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. –

+0

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

Odpowiedz

5

Jeśli potrzebujesz pamięć naraz, nie, naprawdę nie ma sposób to zrobić bez zmiany do jądra 64-bitowego (który, tak, by umożliwić Ci przydzielić więcej pamięci w jednym procesie)

To powiedziawszy, jeśli nie potrzebujesz całej pamięci naraz, ale zamiast tego, po prostu z szybkim dostępem, możesz zawsze odładować części pamięci do innego procesu.

Może to na przykład zadziałać, przechowując dane w innym procesie, a proces powinien tymczasowo zamapować pamięć współużytkowaną z tego procesu na własny obszar pamięci, gdy jest to wymagane. Nadal będzie przechowywany w pamięci, ale będziesz mieć trochę na głowie przy przełączaniu zakresu pamięci. Jeśli narzut jest do zaakceptowania, czy nie, zależy to od wzorców dostępu do pamięci.

Nie jest to podejście bardzo proste, ale bez zmiany jądra, aby zapewnić 64-bitową przestrzeń adresową, wygląda na to, że jesteś trochę związany.

EDYCJA: Możesz nieco podnieść limit nieco powyżej 2 GB, zmieniając konfigurację jądra, ale to tylko oznacza, że ​​zamiast tego trafisz na twardy limit. Ponadto wymagałoby to uprawnień administratora.

0

Odpowiedź jest wyraźna "Nie". Jeśli nie możesz zmienić systemu operacyjnego, nie możesz podnieść limitu. Limit dotyczy całego procesu i oczywiście żaden pojedynczy przydział nie może przekroczyć limitu na proces.

W zależności od opcji użytych do kompilacji jądra, limit może być większy niż 2 GB, ale z pewnością będzie mniejszy niż 4 GB. Ale myślę, że rekompilacja jądra również jest liczona jako "zmiana systemu operacyjnego".

Zobacz this discussion

I tak, na 64-bitowym systemie operacyjnym, które ograniczają odejdzie.

Powiązane problemy