2015-12-28 11 views
7

Chciałbym statycznie zainicjować ogromną (megabajtową) tablicę uint8_t.Inicjalizuj ogromną tablicę uint8_t statycznie z rozsądnym czasem kompilacji

Na początku próbowałem to:

constexpr uint8_t arr[HUGE_SIZE] = { 0, 255, ... };

Niestety, czas kompilacji powyżej jest bardzo długi (bez optymalizacji - około 30 sekund, na optymalizacje - ponad godzinę).

I okazało się, że czas kompilacji może być zredukowana do znikoma (zarówno w optymalizacji i wyłączanie przypadków) jeśli używamy c inicjalizacji styl wyrażenie:

constexpr uint8_t arr[HUGE_SIZE + 1] = "\x00\xFF\x...";

Czy to dobre podejście w C++? Czy powinienem użyć jakiegoś ciągu literowego, aby typy obu stron powyższego przypisania były równe?

+0

Czy ** naprawdę ** potrzebujesz tak dużej tablicy? Może powinieneś pomyśleć o algorytmie. – Downvoter

+0

@mkk Do czego służy tablica i czy w czasie kompilacji potrzebujesz tablicy wypełnionej pamięcią? – Poriferous

+0

Jestem zaskoczony, że optymalizacje mają znaczenie w pierwszym przypadku. Czy ktoś może to wyjaśnić? – Ctx

Odpowiedz

5

Jeśli macierz jest naprawdę duża, należy rozważyć użycie narzędzia do bezpośredniego wygenerowania pliku obiektu z tablicy. Na przykład, z asemblera GNU można zrobić coś takiego:

.section .rodata # or .data, as needed 
    .globl arr 
arr: 
    .incbin "arr.bin" # assuming arr.bin is a file that contains the data 
    .size arr,.-arr 

zmontować ten plik z asemblera GNU i połączyć go do swojego programu. Aby korzystać z tych danych w innym miejscu w programie, wystarczy zadeklarować ją jako extern "C":

extern "C" const uint8_t arr[]; 
+0

To byłoby rozwiązanie. Czy świat programistów C++ nie będzie zadowolony z tego podejścia? (-; – mkk

+0

@mkk No cóż, z tym rozwiązaniem operujesz poza sferą języka programowania C++.To dotyczy również każdego innego podejścia.W przypadku przenośnej aplikacji open source, zadbałbym o dodanie rozwiązania także dla Windowsa: – fuz

+0

Masz rację Zastanawiam się, czy osadzenie go w pliku cpp (tak jak to zrobiłem) daje pewne gwarancje, które są utracone w przypadku twojego podejścia, na przykład endianness może być uszkodzony podczas rozwijania dla różnych urządzenia (więc musimy podać wersję arr.bin dla big-endian i little-endian), mam rację? – mkk

0

Czy zamierza skompilować plik, w którym tablica jest zdefiniowany bardzo często? Jeśli nie, możesz umieścić definicję tablicy w osobnym pliku .cpp z deklaracją przekazania w pliku .h. W ten sposób napotkasz narzuty kompilacji tylko wtedy, gdy zmieni się tablica.

+0

Podczas procesu tworzenia tablica może się zmieniać nawet raz dziennie, więc utrata co najmniej godziny na skompilowanie nie jest przypadkiem. W każdym razie dzięki za odpowiedź. (-: – mkk

0

Przenieś definicję tablicy do osobnego pliku C i skompiluj ją jako taką. C++ może odnosić się do zewnętrznych danych globalnych z modułów obiektów C.

Jeśli kompilacja trwa zbyt długo, użyj tcc.

+0

'constexpr uint8_t arr [HUGE_SIZE] = {0, 255, ...};' nie kompiluje się w C. Jeśli sugerujesz inny kod, być może publikujesz by wyjaśnić swoją odpowiedź – chux

+1

Zastępując constexpr z const oczywiście . – chqrlie

1

Ustalono, że czas kompilacji dla dużych tablic poprawia się nieco, jeśli tablica jest podzielona na mniejsze porcje. Jednak podejście łańcuchowe jest nadal znacznie szybsze. Przy takim schemacie, prawdziwa macierz mogłaby być tą tablicą tablic.

Zamieszczanie poniższych przykładów, jak przetestować problem OP bez wyraźnego zakodowania milionów plików źródłowych. Jako że nie jest to duża część odpowiedzi, ale źródło informacji do zbadania, oznaczenie tej społecznościowej wiki.

#include <iostream> 
using namespace std; 

#include <cstdint> 

#define METHOD 5 

#if METHOD == 1 
// 1 byte blocks 28 secs 
#define ZZ16 65, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 
#define ZZ256 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 
#define ZZ4K ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 
#define ARR constexpr uint8_t arr[] 
#define COUT cout << arr << endl 

#elif METHOD == 2 
// 16 byte blocks 16 secs 
#define ZZ16 {66, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255}, 
#define ZZ256 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 
#define ZZ4K ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 
#define ARR constexpr uint8_t arr[][16] 
#define COUT cout << arr[0] << endl 

#elif METHOD == 3 
// 256 byte blocks 16 secs 
#define ZZ16 67, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 
#define ZZ256 {ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16}, 
#define ZZ4K ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 
#define ARR constexpr uint8_t arr[][256] 
#define COUT cout << arr[0] << endl 

#elif METHOD == 4 
// 4K byte blocks 13 secs 
#define ZZ16 68, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 
#define ZZ256 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 
#define ZZ4K {ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256}, 
#define ARR constexpr uint8_t arr[][4096] 
#define COUT cout << arr[0] << endl 

#elif METHOD == 5 
// String 4 sec 
#define ZZ16 "\x45\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF" 
#define ZZ256 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 ZZ16 
#define ZZ4K ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 
#define ARR constexpr uint8_t arr[] 
#define COUT cout << arr << endl 
#endif 

#define ZZ64K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K ZZ4K 
#define ZZ1M ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K 
#define ZZ16M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M ZZ1M 

// 3 million bytes 
ARR = { 
    ZZ1M ZZ1M ZZ1M 
}; 

int main() { 
    cout << "!!!Hello World!!!" << endl; 
    COUT; 
    cout << sizeof(arr) << endl; 
    return 0; 
} 
Powiązane problemy