crash Temat założony przez niniejszego użytkownika |
vector<bool> na dysk i z powrotem, poprawa wydajności » 2018-07-07 16:44:13 Cześć. Piszę klasę, która pozwala mi z dysku zrobić RAM, tzn chcę adresować więcej przestrzeni niż powala pamięć. Dane dzielę na chunki, obliczam który chcę zapisać/wczytać z dysku i trzymam dziada w polu typu vector<bool> chunk. Mam szybki odczyt z dysku, ale powolny zapis. Robiłem testy, czy mój dysk nie jest jakiś lewy pod względem zapisu, losowe dane pokroju gigabajta zapisuje, powiedzmy, wystarczająco szybko. Odczyt jest szybki: void diskToChunk( size_t id ) { MSG( "diskToChunk id=" + to_str( id ) ); if( this->maxGB < 1000 ) { string name = this->cacheDir + to_str( id ) + ".chunk"; FILE * file = fopen( name.c_str(), "rb" ); char * mb_array = new char[ CHUNKSIZE ]; fread( mb_array, csize, CHUNKSIZE, file ); fclose( file ); this->chunk = this->cstr2vecbool( mb_array, CHUNKSIZE ); delete[] mb_array; } else { MSG( "diskToChunk maxGB > 1000: TO-DO this fragment!!!" ); throw new exception; } MSG( "diskToChunk END JOB" ); }
inline vector < bool > cstr2vecbool( char * array, size_t size ) { vector < bool > result( size * 8 ); for( size_t i = 0; i < size; i++ ) putCharToVector( result, i, array[ i ] ); return result; }
void putCharToVector( vector < bool > & vec, size_t pos, char c ) { for( size_t i = 0; i < 8; i++ ) vec[ pos + i ] =( c &( 1 << i ) ) != 0; }
ale zapis na dysk kuleje: void chunkToDisk( long long index = - 1 ) { if( index < 0 ) index = this->currentChunkID; if( this->maxGB < 1000 ) { MSG( "chunkToDisk, currentChunkID=" + to_str( index ) ); string name = this->cacheDir + to_str( index ) + ".chunk"; char * mb_array = this->chunk2cstr(); FILE * file = fopen( name.c_str(), "wb" ); fwrite( mb_array, csize, CHUNKSIZE, file ); fclose( file ); delete[] mb_array; MSG( "chunkToDisk END JOB" ); } else { MSG( "chunkToDisk if maxgb > 1000 to-do" ); throw new exception(); } }
char * chunk2cstr() { cout << ">>>>> chunk2cstr size:" << this->chunk.size(); cin.ignore(); char * mb_array = new char[ this->chunk.size() ]; for( size_t i = 0; i < this->chunk.size(); i++ ) { for( size_t j = 0; j < 8; j++ ) mb_array[ i ] += this->chunk[ i + j ] << j; } return mb_array; }
Co można zrobić, aby poprawić wydajność? Mam cholernie dużo danych do ziterowania. Hilfe Forumowicze :) |
|
pekfos |
» 2018-07-07 17:53:54 . Dane dzielę na chunki, obliczam który chcę zapisać/wczytać z dysku i trzymam dziada w polu typu vector<bool> chunk. |
A std::vector<bool> używasz, bo..? char * mb_array = new char[ this->chunk.size() ];
|
Od kiedy to masz gwarancję, że zaalokowana pamięć jest w jakikolwiek sposób zainicjalizowana? Zasadniczo, to akurat w C++ tak się nie pisze. |
|
crash Temat założony przez niniejszego użytkownika |
» 2018-07-07 18:17:10 Nowe kompilatory wypełniają dane zerami, czytałem o tym kiedyś z oficjalnych źródeł C++. Nawet jeśli nie - poniżej w komentarzu jest memset. Ogólna faza testów poprawności/spójności danych będzie w dalszej fazie. Zresztą sprawdź sam na mniejszych niż używane przeze mnie rozmiary tablic - czy to będzie char, int, czy inny typ prosty - używając c++11/14/17 powinny być zera. Sprawa wygląda tak, że mamy kod napisany w Javie, ale z pewnych przyczyn część algorytmu, nad którym pracujemy, wymaga zupełnie innych struktur danych i podejścia, dlatego padło na C++. Co do throw new exception, nie wiedziałem przyznaję szczerze, na razie nie jest to interesujący punkt z tego względu, że wszystkie ścieżki kodu gdzie cache z danymi z dysku przekracza 1000GB, tam trzeba będzie dopisać inne obsługi struktury plików, więc - nawet gdybym wiedział, że java-style nie wchodzi w grę, to i tak to trzeba będzie napisać od początku. Wracając do mojego problemu - w wyniku analiz z konsolą i liczeniem czasu, wskazana instrukcja jest powolna. Nie bardzo wiem, jak to obejść, z Asemblerem niestety jestem na bakier totalnie. Używam chunk'ów z dysku po 10 MB (10*10^6, nie x1024^3). Docelowa maszyna, na której będzie leciał program jest dużo lepsza niż szrot, który używam, nie zmienia to postaci rzeczy, że danych do ziterowania jest w terabajtach... this->chunk = vector < bool >( CHUNKSIZE * 8 ); ....
for( size_t i = 0; i < this->chunk.size(); i++ ) { for( size_t j = 0; j < 8; j++ ) mb_array[ i ] += this->chunk[ i + j ] << j; }
|
|
pekfos |
» 2018-07-07 18:41:07 Nie odpowiedziałeś na pytanie. Dlaczego std::vector<bool>? Z punktu widzenia wydajności, to najgorszy możliwy wybór, bo to trade-off kosztem wydajności, a nie na rzecz wydajności. Zresztą, co ty w ogóle z nim robisz..? char * mb_array = new char[ this->chunk.size() ];
for( size_t i = 0; i < this->chunk.size(); i++ ) { for( size_t j = 0; j < 8; j++ ) mb_array[ i ] += this->chunk[ i + j ] << j; } |
Co to jest..? Mi to wygląda na typowe Javowe podejście. Przypominam, że w C++ masz bezpośredni dostęp do pamięci. Konwertujesz najpierw bajty na bity, a potem w drugą stronę. Po co? Zresztą sprawdź sam na mniejszych niż używane przeze mnie rozmiary tablic - czy to będzie char, int, czy inny typ prosty - używając c++11/14/17 powinny być zera. |
Dostałem krzaki. Ostatnio gdy sprawdzałem, VS 2017 to był nowy kompilator. |
|
crash Temat założony przez niniejszego użytkownika |
» 2018-07-07 19:55:05 Potrzebuję ile wlezie przestrzeni dyskowej, którą traktuję jak ram dla tablicy/wektora bool. Robię pewne obliczenia przy użyciu nowych algorytmów, które w swoim czasie zostaną opublikowane. Pomysł jest taki, aby we wstępnej fazie na dysku utworzyć strukturę folderów, w każdym folderze max 1000 plików po 10 mb.
Mam funkcje selectCacheFile, która w zależności od indeksu long long (typedef Long) wybiera chunk z dysku i ładuje go do pola this->chunk. Metody get/set pobierają/ustawiają w pamięci pole, a jeśli chunk jest w innym pliku, to selectCahceFile + saveChunk(size_t fileIndex) zapisuje aktualny chunk i ładuje inny na podstawie obliczonego indeksu. Całość zachowuje się jak wielka na 90% dysku tablica bool'i. Kombinujemy nowe algorytmy matematyczne, o których szczegółach na razie nie mogę mówić. Muszę mieć możliwość iterowania po plikach z boolami, aby imitować pamięć RAM. |
|
pekfos |
» 2018-07-07 20:02:43 Wywal std::vector<bool>.
PS: Twój kod w ogóle działa poprawnie..? |
|
crash Temat założony przez niniejszego użytkownika |
» 2018-07-07 20:47:37 Zamieniłem wszystkie wystąpienia vector<bool> w gołą tablicę. Różnica jest ogromnie nieporównywalnie szalona. Eh, na cppreference jest wzmianka o wydajności. Jesteś wielki, dziękuję za pomoc :)
Skończę kod klasy-tablicy, wrzucę do wątku dla potomnych. Powinienem się jeszcze dziś uporać. Dzięki jeszcze raz za wszystkie wskazówki :) |
|
« 1 » |