6

Nota prawna: Przepraszam za szczegółowość tego pytania (myślę, że jest to interesujący problem!), Ale nie mogę zrozumieć, jak bardziej zwięźle to powiedzieć.Uzyskiwanie dostępu> 2,3,4 GB Pliki w trybie 32-bitowym na 64-bitowym (lub 32-bitowym) systemie Windows

Zrobiłem godzin badań, aby pozornie niezliczonych sposobów na rozwiązanie problemu dostępu do wielo-GB plików w procesie 32bit na 64bit Windows 7, począwszy od /LARGEADDRESSAWARE do VirtualAllocEx AWE. Nieco miło jest pisać w systemie Windows widok z wieloma mapami pamięciowymi (CreateFileMapping, MapViewOfFile, itp.), Ale nie mogę uciec przed poczuciem, że istnieje bardziej eleganckie rozwiązanie tego problemu. Poza tym jestem w pełni świadomy szablonów międzyprocesowych i iostream'a Boosta, chociaż wydają się one raczej lekkie, wymagające podobnego wysiłku, aby napisać system wykorzystujący tylko wywołania Windows API (nie wspominając już o tym, że mam już pamięć) architektura odwzorowana częściowo wdrożona przy użyciu wywołań Windows API).

Próbuję przetworzyć duże zbiory danych. Program zależy od wcześniej skompilowanych 32-bitowych bibliotek, dlatego też na razie sam program działa również w 32-bitowym procesie, mimo że system ma 64-bitowy, z 64-bitowym systemem operacyjnym. Wiem, że istnieją sposoby, dzięki którym mogę dodawać do tego otoki biblioteki, ale widząc, że jest to część większego kodu, byłoby to naprawdę przedsięwzięcie. Ustawiłem nagłówki binarne, aby umożliwić /LARGEADDRESSAWARE (kosztem zmniejszenia mojej przestrzeni jądra?), Tak, że dostaję do około 2-3 GB adresowalnej pamięci na proces, dawać lub brać (w zależności od fragmentacji sterty, itp.) .

Oto kwestia: zestawy danych to 4 + GB i mają uruchomione algorytmy DSP, które wymagają zasadniczo dowolnego dostępu w całym pliku. Wskaźnik do obiektu wygenerowanego z pliku jest obsługiwany w języku C#, ale sam plik jest ładowany do pamięci (z tym częściowym odwzorowaniem w pamięci) w C++ (to P/Invoked). Dlatego uważam, że rozwiązanie nie jest niestety tak proste, jak zwykłe dostosowanie okna w celu uzyskania dostępu do części pliku, do której muszę uzyskać dostęp, ponieważ zasadniczo chcę, aby cały plik został wyodrębniony w pojedynczy wskaźnik, z którego mogę wywołać metody uzyskać dostęp do danych prawie w dowolnym miejscu pliku.

Wygląda na to, że większość architektur odwzorowanych w pamięci polega na dzieleniu pojedynczego procesu na wiele procesów. Tak więc, na przykład, uzyskałbym dostęp do pliku 6 GB z 3 procesami, z których każdy miałby 2 GB okna do pliku. Następnie musiałbym dodać znaczną ilość logiki, aby pobierać i rekombinować dane z różnych okien/procesów. VirtualAllocEx najwyraźniej zapewnia metodę zwiększania wirtualnej przestrzeni adresowej, ale nadal nie jestem do końca pewny, czy jest to najlepszy sposób na zrobienie tego.

Ale, powiedzmy, chcę, aby ten program działał tak samo "łatwo" jak pojedynczy proces 64-bitowy w systemie 64-bitowym. Załóżmy, że nie obchodzi mnie wyrzucanie, po prostu chcę mieć możliwość manipulowania dużym plikiem w systemie, nawet jeśli, powiedzmy, 500 MB zostało załadowanych do fizycznej pamięci RAM w tym samym czasie. Czy istnieje sposób na uzyskanie tej funkcjonalności bez konieczności ręcznego pisania nieco niedorzecznego, ręcznego systemu pamięci? Czy jest jakiś lepszy sposób niż to, co znalazłem dzięki takiemu czesaniu SO i internetu?

To może być wtórne pytanie: czy istnieje sposób ograniczenia wykorzystania fizycznej pamięci RAM przez ten proces? Na przykład, co jeśli chciałbym ograniczyć proces do tylko 500 MB załadowanego do fizycznej pamięci RAM w tym samym czasie (przy jednoczesnym zachowaniu pliku z wieloma plikami stronicowanymi na dysku)?

Przykro mi z powodu długiego pytania, ale mam wrażenie, że jest to przyzwoite podsumowanie tego, co wydaje się być wieloma pytaniami (z częściowymi odpowiedziami), które znalazłem na SO i ogólnie w sieci. Mam nadzieję, że może to być obszar, w którym można uzyskać ostateczną odpowiedź (lub przynajmniej niektóre wady/zalety), a my wszyscy możemy nauczyć się czegoś wartościowego w tym procesie!

+1

tl; dr, ale jeśli chcesz używać zewnętrznej biblioteki: Qt może obsłużyć „duże pliki” cross platform, choć nie odwzorowany w pamięci (na platformach 32-bitowych). Ale wykorzystuje wewnętrzną pamięć podręczną IO, która * może * osiągnąć porównywalną wydajność? – leemes

+0

Dzięki za komentarz, leemy (nawet jeśli tl; dr jest trochę niegrzeczny, aby powiedzieć> _> ;;)! Przyjrzałem się używaniu wewnętrznej pamięci podręcznej IO, ale wydaje się, że wprowadzam sporo komplikacji, czego staram się uniknąć. Chciałbym również uniknąć dodawania do miksu dodatkowych bibliotek, takich jak Qt (Boost jest już zintegrowany). –

+0

Ograniczając pamięć RAM, można użyć obiektu zadania Windows i ograniczyć zestaw roboczy, który ogranicza fizyczną pamięć RAM. Niestety myślę, że to tylko zmaksymalizować zamiany, więc nie jest to, co chcesz. Zakładam również, że wiesz o plikach mapowanych w pamięci i nie pasują one do twoich potrzeb. –

Odpowiedz

2

można napisać klasę dostępowej, która ją podać adres bazowy i długości. Zwraca dane lub zgłasza wyjątek (lub jakkolwiek chcesz poinformować o warunkach błędu), jeśli wystąpią błędy (poza zakresem itp.).

Następnie za każdym razem, gdy trzeba odczytać z pliku, obiekt akcesora może użyć SetFilePointerEx() przed wywołaniem ReadFile(). Następnie możesz przekazać klasę accessor do konstruktora obiektów, które utworzysz po przeczytaniu pliku. Obiekty następnie używają klasy accessor, aby odczytać dane z pliku. Następnie zwraca dane do konstruktora obiektu, który przetwarza go na dane obiektu.

Jeśli później wzdłuż linii, jesteś w stanie skompilować do wersji 64-bitowej, można po prostu zmienić (lub przedłużenia) klasę dostępowej do odczytu z pamięci zamiast.

chodzi o ograniczenie ilości pamięci RAM wykorzystywanej przez proces .. to głównie kwestia upewniając się, że A) nie ma wycieków pamięci (zwłaszcza te obsceniczne) i B) niszczenie obiektów ty nie potrzeba w tej chwili. Nawet jeśli będziesz go potrzebował później, ale dane się nie zmienią ... po prostu zniszcz obiekt. Następnie odtwórz go później, gdy będziesz go potrzebować, umożliwiając ponowne odczytanie danych z pliku.

+1

Hmm ... to brzmi jak ciekawy pomysł, inetknght! Dziękuję za wejście! Chociaż brzmi to jak świetny sposób, aby przeczytać cały plik, nadal będzie wymagać dodania logicznej pewności co do ręcznego przenoszenia widoków w pliku, chociaż zgadzam się, że używanie rozszerzalnego akcesora byłoby wspaniałe, w że tylko klasa accessor będzie musiała zostać zmodyfikowana, jeśli kiedykolwiek zostanie przeniesiona w kierunku 64-bitowym. Może to w końcu być ostateczną implementacją, jeśli nie ma innych sposobów łatwego zarządzania plikiem przez inny konstrukt. –

Powiązane problemy