Mam duży zestaw danych- około 6 mln próbek w dwuwymiarowej tablicy.
Żeby zmniejszyć rozmiar danych chciałbym skorzystać z pól bitowych.
Wyczytałem że nie można korzystać z tablic w polach bitowych.
Jak to obejść?
Pola bitowe nie slużą wcale do oszczędzania pamięci i efekty mogą być odwrotne. 6mln próbek nawet gdyby każda próbka składała się z 8bajtowych liczb to nadal jest niecałe 50MB pamięci. Zapewne masz w komputerze 4GB albo i więcej. Po co kombinować?
Pakietów danych jest o wiele więcej więc gra jest warta świeczki i dlatego zależy mi na tym sposobie.
Możliwe że kod spakowanych informacji i kod "dobierania się" do nich będzie krótszy.
Po kilku eksperymentach porzucam pomysł.
Temat do zamknięcia
Pola bitowe to po prostu nadanie poszczególnym bitom jakiś informacji/stanów, np. zamiast stosować bool, nadajesz jednemu bitowi tę informację - to w ogóle ma się nijak do oszczędzania tak dużych porcji danych, całkiem o co innego chodzi.
Najprościej skompresuj sobie to zlibem:
http://www.gamedev.pl/articles.php?x=view&id=245
- jeśli mowa o oszczędności RAM, nie trzymaj wszystkiego w pamięci tylko pisz i czytaj aktualnie przetwarzany fragment do pliku (tak np. robią programy nagrywające dźwięk).
Więcej chyba nic nie zrobisz, cóż nie da się w magiczny sposób zmniejszyć ilości danych bez utraty jakości :>
Więcej chyba nic nie zrobisz, cóż nie da się w magiczny sposób zmniejszyć ilości danych bez utraty jakości :>
Moje rozwiązanie (warto zaznaczyć bezstratne):
Jako że będę pracował na 12 bitowych próbkach to będę wrzucał po dwie do struktury trzech liczb typu unsigned char(24 bity). Następnie wyliczę ze struktur współczynniki transformaty, które następnie skompresuję.
"niewykorzystywalnosc tablic przy polach bitowych" nie oznacza, ze w ogole nie mozesz uzywac tablic. Oznacza jedynie, ze element tablicy nie moze byc polem bitowym.
Tzn.
//majac jakies pole w stylu:
char bum : 5;
//nie mozesz "z niego" utworzyc tablicy
char (bum[15]) : 5; // to by byla jedyna opcja zapisu noszaca znamiona poprawnej skladni
char bum : 5[15]; // bezsens
char[15] bum : 5; // bezsens
po prostu nie ma zbytnio jak tego sensownie napisac..
Trzeba wiec sie postarac, aby element byl zwykly, zas pola bitowe jakos upchnac w elemencie tablicy, bedacym czyms innym, np. struktura.
drobna uwaga: http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.4
większa uwaga, dla MSVC: http://msdn.microsoft.com/en-us/library/yszfawxh(VS.80).aspx (jesli uzywasz visualstudio, przeczytaj caly ten artykul)
Biorac pod uwage ze masz pola po 12 bitow, faktycznie, dobrze upychac do 3 bajtow, albo 12 aby miec pewnosc ze zaden align-do-4B sie nie odezwie. Na szczescie w razie problemow align mozna narzucic poprzez dyrektywy kompilatora attribute-packed albo pragma-pack,1
Na przyklad:
struct bisample
{
unsigned short sample0 : 12;
unsigned short sample1 : 12;
} samples[1000];
//i oczywiscie
unsigned short getSample(int idx)
{
return idx % 2 ? samples[idx/2].sample1 : samples[idx/2].sample0 ;
}
natomiast, czy bedzie ta tablica zajmowac dokladnie 10003 czy 1000(3+1) czy inna ilosc pamieci, to zalezy od tego, jak kompilator ja sobie upakuje. ustawienie attribute-packed / pragma-pack,1 spowoduje ze na pewno bedzie zajmowac 3000. oczywiscie, jesli zadbasz o to, aby pola skladaly sie na wielokrotnosc 32/64 bitow, nie bedziesz musial klopotac sie alignem. Tak czy owak, czy on wystapi, czy nie, normalne czytanie z tablicy w stylu samples[idx].sample1 zawsze odbedzie sie poprawnie, nawet jezeli nic nie bedziesz konfigurowal recznie i nawet jesli rozmiar paczki nie bedzie wielokrotnoscia szerokosci szyny. Ot, wtedy dane po cichu zajma wiecej miejsca nizby powinny.