2016-03-26 12 views
6

Podczas czytania this byłem zaskoczony tym, jaki poziom metaprogramowania może zrobić dla twojego układu klas. Muszę przyznać, że nie w pełni zrozumieć, co jest proponowane optymalny układ, gdybym miał stwierdzić, co zrozumiałem, to byłoby to:Czy implementacje krotek mają zoptymalizowany układ?

zamawiania członkiem klasy schodząc wyrównanie czyli typu z największą alignof wyniku idzie pierwszy itp.

Możesz mnie poprawić, jeśli coś jest nie tak (gdybyś miał krótkie wyjaśnienie, dlaczego tak się stanie, byłoby jeszcze lepiej, nie mogłem skopiować wklejonych fragmentów uzasadnienia w moim pytaniu) , ale moje pytanie dotyczy innego tematu:

Czy jakakolwiek implementacja biblioteki std::tuple ma taką optymalizację układu?

Jeśli nie, czy istnieją jakieś standardowe typy danych algebraicznych, które to robią, czy istnieje inny sposób, aby to zrobić dla mojej klasy, oprócz pisania takiej maszyny?

Odpowiedz

9

Brak implementacji biblioteki Jestem świadomy optymalizacji układu do wyrównania. Można użyć programu takiego jak ten, aby przeprowadzić inspekcję tuple układ:

#include <iostream> 
#include <tuple> 

struct empty {}; 

int 
main() 
{ 
    using T = std::tuple<double, int, empty, short, long>; 
    T t{}; 
    std::cout << &t << '\n'; 
    std::cout << &std::get<0>(t) << '\n'; 
    std::cout << &std::get<1>(t) << '\n'; 
    std::cout << &std::get<2>(t) << '\n'; 
    std::cout << &std::get<3>(t) << '\n'; 
    std::cout << &std::get<4>(t) << '\n'; 
    std::cout << &t+1 << '\n'; 
    std::cout << sizeof(T) << '\n'; 
} 

libC++ przechowuje elementy w kolejności deklaracji i optymalizuje przestrzeń z dala pustych członków. Puste elementy są przesunięte w kierunku przodu. Wydajność próbki:

0x7fff5ccf39f8 
0x7fff5ccf39f8 
0x7fff5ccf3a00 
0x7fff5ccf39f8 
0x7fff5ccf3a04 
0x7fff5ccf3a08 
0x7fff5ccf3a10 
24 

libstdC++ przechowuje elementy w kolejności odwrotnej do deklaracji i optymalizuje przestrzeń dla pustych członków. Puste elementy są przesunięte w kierunku przodu. Wydajność próbki:

0x7ffe4fc5b2a0 
0x7ffe4fc5b2b0 
0x7ffe4fc5b2ac 
0x7ffe4fc5b2a0 
0x7ffe4fc5b2a8 
0x7ffe4fc5b2a0 
0x7ffe4fc5b2b8 
24 

VS-2015 przechowuje elementy w kolejności odwrotnej do deklaracji i nie optymalizuje miejsca dla pustych elementów. Przykładowe wyjście:

0306FEF4 
0306FF04 
0306FF00 
0306FEFC 
0306FEF8 
0306FEF4 
0306FF0C 
24 

W tym przykładzie widzimy, że optymalizacja miejsca z dala do pustej członka nie kupować niczego, ponieważ wpisuje się w obszar wypełnienia tak.

Brak urządzeń, które automatyzują zadanie zmniejszania wypełnienia w standardzie.

+0

Proszę wyjaśnić, dlaczego zamawianie przez zstępujące wyrównanie byłoby optymalnym układem? –

+0

@LorahAttkins: To heurystyka, która często działa. Zakłada on, że sama klasa jest zazwyczaj maksymalnie wyrównana, więc umieszczenie maksymalnie wyrównywanych członków gwarantuje brak bajtów dopełniających między maksymalnie wyrównanymi członkami. Następnie przejdź do kolejnych największych elementów linii trasowania i ta sama logika zostanie zachowana. Gdy zabraknie członków, zazwyczaj dodaje się dodatkowe dopełnienie, aby zaokrąglić sizeof (your_class) do wielokrotności wyrównania klas. Czasami sztuczka "rzucaj po" oszczędza ci bajty, a czasem nie. Jest to dobre narzędzie do korzystania z zestawu narzędzi. –

+0

Powinienem był dodać do mojego komentarza powyżej: Wielkość każdego typu jest wielokrotnością wyrównania dla tego typu. Na przykład nie ma czegoś takiego jak typ z wyrównaniem 16 bajtów i rozmiarem 15 lub 17. Jego rozmiar będzie 16, lub 32, lub 48 itd. Oznacza to, że zarówno 'i a' * i *' i a + 1' są wskaźnikami z wyrównaniem co najmniej tak dużym, jak "alignof (a)". –