File_mapping dla opornych

0

Witam,
jestem nowy na tym forum, więc się przedstawię: Mam na imię Andrzej i studiuje na polibudzie warszawskiej. W C++ piszę sobie od czasu do czasu jakieś proste aplikacje consolowe. Swoją wiedzę o programowaniu opieram na Symfonii Grębosza i Borlandzie 3.1 (mam nadzieję że jeszcze ktoś go pamięta :)

Dość o mnie, teraz co mnie tu przyniosło:
W jednej ze swoich aplikacji mam do zapisu i odczytu bardzo duże pliki: 2, 8 (obecnie, w przyszłości 16 i więcej) GB i chciałbym w jakiś sposób móc szybko je zapisywać i wczytywać (póki co pomijam prędkość dysku). Wymyśliłem/wygooglałem dwa podejścia:

  1. Mając procesor 8 rdzeniowy mógłbym np.: podzielić plik na 8 kawałków i zadbać, żeby każdy wątek wczytywał swój kawałek pliku. Może mi ktoś podpowiedzieć jak taki plik szybko wrzucić do pamięci? Z mojego doświadczenia jednak wiem, że zabawia wieloma wątkami potrafi zakończyć się trudnymi do znalezienia zapętleniami, więc się trochę tego pomysłu obawiam...

  2. Poprzez file mapping, ale o tym jeszcze ni nie wiem :/

Mówiąc szczerze pierwsze rozwiązanie to jest to wymyślone a drugie wygooglane :)

Dlatego potrzebuję od Was pomocy:

  1. Jak uważacie, które podejście jest właściwe? A może coś zupełnie innego?
  2. Gdzie mogę poczytać o file mappingu (ale tak dla kompletnego żółtodzioba w tej kwestii, najchętniej to jakieś książki, wyszukiwarka heliona na zapytanie file mapping nic mądrego nie zwraca...)

Ze swojej strony dodam, że zależy mi przede wszystkim na stabilności rozwiązania. Komputer pewnie będzie mielił dane przez weekend albo tydzień, w związku z tym nie cieszy mnie perspektywa zawieszającego się programu :)

Jeszcze dla informacji: system operacyjny: Windows 7 x64; IDE: VS2005

Z góry dzięki za szybką odpowiedź.
Pozdrawiam
sagrado

0

Procesor bierze niewielki udział we wczytywaniu plików, więc podział wczytywania pliku na wątki NIC ci nie da. Tu wąskim gardłem jest dysk twardy. Jeśli chcesz przyspieszyć wczytywanie, to wczytaj plik w jednym kawałku (zmierz wielkość pliku i wczytaj jego zawartość jednym wywołaniem czytania). Jeśli jednak plik jest na to za duży to wczytuj go w kawałkach po dokładnie 32KB.
Defragmentacja dysku też może usprawnić operacje dyskowe.

0

Czyli mogę wczytać na raz całe 8 GB? (Zakładam, że mam dostępne tyle ramu i system x64).
Czy procedura wczytywania takiego pliku różni się jakoś od zwyczajnego wczytywanie po 1 bicie? Jakim poleceniem to zrobić?

Co do czytania rozmiaru pliku myślałem, żeby dać sobie taką informację w nagłówku - tylko czy mogę odczytać nagłówek nie czytając całego pliku?

I druga rzecz skąd akurat te 32 KB?

Może te pytania brzmią strasznie lamersko, ale moje doświadczenie z zapisem plików ograniczało się zawsze do kilku bitowych plików tekstowych lub binarnych, w które wpisywałem sobie kilka parametrów obliczeń, żeby nie klepać ich każdorazowo w konsoli.

Oczywiści te giganty są binarne.

Do tej pory wczytuję sobie plik za pomocą:

FILE* f;
fopen_s(&f, "tablica.bin", "r");
unsigned long lSize= 0;
fseek (f , 0 , SEEK_END);
lSize= ftell(f);
rewind(f);

pLSTab= new float [2*tabSize*tabSize]; //gdzie tabSize to dlugosc boku, pLSTab jest oczywiście wskaźnikiem
for(int i=0; i<2*tabSize*tabSize; i++)
{
    fread(&pLSTab[i],1,lSize,f); //mogę tutaj zamiast "1" wpisać 8GB, albo jako parametr rozmiar pliku ze wspomnianego nagłówka?
}
fclose(f);
//cos tam robie z tablica
delete[] pLSTab;

Nie muszę dodawać, że wczytanie tego zajmuje wieki :)

0
//mogę tutaj zamiast "1" wpisać 8GB, albo jako parametr rozmiar pliku ze wspomnianego nagłówka?
(...)

Nie muszę dodawać, że wczytanie tego zajmuje wieki

Nie wiem, czy zauważyłeś, ale fread znajduje się w pętli, sama zamiana na 8GB( [!!!] ) nie wystarczy... Z drugiej strony, czytanie w całości tak dużych plików do pamięci nie jest dobrym pomysłem.

0
0x666 napisał(a)

Z drugiej strony, czytanie w całości tak dużych plików do pamięci nie jest dobrym pomysłem.

Dlaczego?

A jeśli nie tak duże to w jakich kawałkach? I czy nie będzie to zależne od formatu plików na dysku? Chociaż w wypadku Windowsa to chyba tylko NTFS wchodzi w rachubę.

0

Między innymi dlatego, że ładowanie "zajmuje wieki" i zajmuje niepotrzebnie zasoby. Już lepiej zmapować plik.

Jeśli chodzi o pozostałe pytania, trudno coś sensownego powiedzieć, zbyt ogólnie przedstawiłeś problem.

0

użytkownik 0x666 napisał:

Już lepiej zmapować plik

No właśnie jak? - jakaś literatura? Pod tym względem jestem kompletnie zielony.

zbyt ogólnie przedstawiłeś problem

Postaram się więc bardziej szczegółowo:
Mam do wczytywania bardzo duże (kilkugigowe) pliki binarne. Plik zawsze będzie miał wielkość: 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768... itd MB. W plikach jest zapisana tablica jednowymiarowa floatów.

Chcę mieć teraz możliwość sprawnego wczytania całego pliku do RAM (o ile dysponuję wystarczającą ilością) lub w przypadku gdy nie mam to takiego kawałka pliku dla którego pamięcią dysponuje.

Przykładowo: jeśli mam plik o wielkości 4GB i dysponuję 2GB wolnego RAMu to chciałbym wczytać połowę danych - wykonać obliczenia - zapisać w tym samym pliku, po czym wczytać drugą połowę i operację powtórzyć.

Chciałem zapytać:
Jak wczytać/zapisać taki plik możliwie najszybciej?
I jeśli poprzez mapowanie pliku to jak to się robi?</quote>

0

jakaś literatura?

TU masz wszystko, co trzeba.

1 użytkowników online, w tym zalogowanych: 0, gości: 1