align (C++)
Specyficzne dla firmy Microsoft
Użyj __declspec(align(#)) do precyzyjne sterowanie wyrównania danych zdefiniowanych przez użytkownika (na przykład statyczny alokacji lub automatyczne danych w funkcji).
__declspec( align( # ) ) declarator
Uwagi
Pisania aplikacji wykorzystujących najnowsze instrukcje tekstów wprowadzono pewne problemy i nowych ograniczeń.W szczególności wiele nowych instrukcji wymagają, że danych muszą być dostosowane do granice 16 bajtów.Ponadto ustawiając często używanych danych rozmiaru pamięci podręcznej linii określony procesor, możesz zwiększyć wydajność pamięci podręcznej.Na przykład jeśli definiują strukturę, w których rozmiar jest mniejszy niż 32 bajty, warto wyrównanie go do 32 bajty, aby upewnić się, że obiekty tego typu Struktura efektywne są buforowane.
# to wartość wyrównania.Prawidłowe wpisy są uprawnienia całkowitą dwóch od 1 do 8192 (w bajtach), na przykład 2, 4, 8, 16, 32 lub 64.declaratorto dane, które Deklarujesz jako wyrównane.
Informacje na temat do zwrócenia wartości typu size_t to wymagań wyrównanie typu, zobacz __alignof.Informacje na temat do deklarowania odwołań do niewyrównanych wskaźniki, jeśli platformą 64-bitowe procesory, zobacz __unaligned.
Można użyć __declspec(align(#)) podczas definiowania struct, union, lub class, lub gdy deklaruje zmienną.
Kompilator nie gwarancji lub próbują zachować atrybut wyrównanie danych podczas operacji przekształcania kopii lub danych.Na przykład memcpy skopiować struct zadeklarowanych za pomocą __declspec(align(#)) w dowolnej lokalizacji.Należy zauważyć, że zwykłych allocators — na przykład malloc, C++ operator nowei Win32 allocators — pamięci, który jest zazwyczaj nie wystarczająco wyrównane do zwrócenia __declspec(align(#)) struktury lub tablic struktur.Aby zagwarantować poprawnie wyrównania miejsce docelowe operacji przekształcania kopii lub dane, należy użyć _aligned_malloc, lub zapisać własne alokatora.
Nie można określić sposób wyrównania dla parametrów funkcji.Gdy dane, które ma atrybut wyrównanie jest przekazywane przez wartość na stosie, jego wyrównanie jest kontrolowane przez Konwencję wywołania.Jeśli wyrównanie danych jest ważna w wywoływanej funkcji, należy skopiować parametru do prawidłowo wyrównany w pamięci przed użyciem.
Bez __declspec(align(#)), Visual C++ powoduje wyrównanie danych z fizyczną granice na podstawie procesora docelowego i rozmiar danych, do 4 bajtów granice na procesorach 32-bitowych i granice 8 bajtów w 64-bitowych procesorów.Dane klasy lub struktury jest wyrównywany w klasie lub strukturze co najmniej jego wyrównanie fizycznych i bieżące ustawienia pakowania (z #pragma pack lub /Zp opcję kompilatora).
W przykładzie pokazano użycie __declspec(align(#)):
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
Ten typ ma teraz atrybut wyrównanie 32 bajtów.Oznacza to, że wszystkie wystąpienia statyczne i automatyczne uruchomić w granicach 32 bajtów.Struktura dodatkowe typy zadeklarowanych za pomocą tego typu jako członek zachować atrybut wyrównania tego typu, oznacza to, że struktura któregokolwiek z Str1 , ponieważ element zostanie ma atrybut wyrównanie co najmniej 32.
Należy pamiętać, że sizeof(struct Str1) jest równa 32.Oznacza to, że jeśli tablicę obiektów Str1 został utworzony, a baza tablicy jest 32 bajty wyrównane, każdy element członkowski tablicy jest również 32-bajty wyrównane.Aby utworzyć tablicę, których podstawą jest prawidłowo wyrównane w pamięci dynamicznej, należy użyć _aligned_malloc, lub zapisać własne alokatora.
sizeof Wartość dla dowolnej struktury jest przesunięcie końcowym elementu członkowskiego oraz rozmiar ten element członkowski, zaokrąglona w górę do najbliższej wielokrotności największej wartości wyrównanie elementu członkowskiego lub wartość wyrównanie całej struktury, którakolwiek jest większa.
Kompilator używa tych reguł dla Wyrównanie struktury:
Jeśli zastąpiona z __declspec(align(#)), wyrównanie elementu członkowskiego skalarne struktury jest minimalna jego rozmiar i bieżący pakowania.
Jeśli zastąpiona z __declspec(align(#)), Wyrównanie struktury jest maksymalną liczbę poszczególnych wyrównania z jego elementy członkowskie.
Element członkowski struktury jest umieszczana po przesunięcie od początku jej nadrzędnej strukturze jest najmniejszą wielokrotnością jego wyrównanie większą lub równą przesunięcie końca poprzedni element członkowski.
Rozmiar struktury jest najmniejszą wielokrotności jego wyrównanie większą lub równą przesunięcie od końca jego ostatniego elementu członkowskiego.
__declspec(align(#))tylko zwiększyć ograniczeń wyrównania.
Aby uzyskać więcej informacji, zobacz:
Dopasuj przykłady
Definiowanie nowych typów z __declspec(align(#))
Wyrównywanie danych w lokalnego magazynu wątków
Jak wyrównać współdziała z pakowania danych
Przykłady struktury wyrównanie(określonych x 64)
Dopasuj przykłady
W poniższych przykładach pokazano sposób __declspec(align(#)) wpływa na rozmiar i wyrównanie struktury danych.Przykłady założyć następujące definicje:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
W tym przykładzie S1 struktury jest definiowana za pomocą __declspec(align(32)).Wszystkie zastosowania S1 dla definicji zmiennej lub w inny typ deklaracje są 32-bajty wyrównane.sizeof(struct S1)Zwraca 32, i S1 ma 16 bajtów uzupełnienia po 16 bajtów do przeprowadzenia czterech liczb całkowitych.Każdy int elementu członkowskiego wymaga wyrównanie 4 bajtów, ale Wyrównanie struktury sam jest zadeklarowany jako 32.Dlatego ogólną wyrównanie jest 32.
struct CACHE_ALIGN S1 { // cache align all instances of S1
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned
W tym przykładzie sizeof(struct S2) Zwraca 16, które to dokładnie Suma rozmiary elementu członkowskiego, ponieważ jest to wielokrotnością największego wymagań wyrównanie (wielokrotnością 8).
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
W poniższym przykładzie sizeof(struct S3) zwraca 64.
struct S3 {
struct S1 s1; // S3 inherits cache alignment requirement
// from S1 declaration
int a; // a is now cache aligned because of s1
// 28 bytes of trailing padding
};
W tym przykładzie należy zauważyć, że a ma wyrównanie jego fizyczną typu, w tym przypadku 4 bajtów.Jednak S1 musi być 32-bajty wyrównane.Dwadzieścia ośmiu bajtów wypełniających postępuj zgodnie a, tak aby s1 rozpoczyna się od przesunięcia 32.S4następnie dziedziczy wymagania wyrównanie S1, ponieważ jest ona największego wymagań wyrównanie w strukturze.sizeof(struct S4)Zwraca 64.
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
Następujące trzy deklaracji zmiennych także użyć __declspec(align(#)).W każdym przypadku zmiennej musi być 32-bajty wyrównane.W przypadku tablicy adres podstawowy w tablicy, nie każdego członka tablicy, jest 32-bajty wyrównane.sizeof Wartość dla każdego członka tablicy nie występuje podczas korzystania __declspec(align(#)).
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
Aby wyrównać każdego członka tablicy, powinien być używany kod, takich jak to:
typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];
W tym przykładzie zwróć uwagę, że wyrównywanie struktury sam i wyrównywanie pierwszym elementem mają taki sam efekt:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
S6i S7 identyczne wyrównanie, alokacji i rozmiar właściwości.
W tym przykładzie adresy wyrównanie początkowego z, b, c i d są odpowiednio 4, 1, 4 i 1.
void fn() {
int a;
char b;
long c;
char d[10]
}
Wyrównanie, gdy przydzielonej pamięci w stosu zależy od tego, które alokacji funkcja jest wywoływana.Na przykład, jeśli używasz malloc, wynik zależy od rozmiaru strony.Jeśli arg > = 8, pamięć zwracana jest wyrównywany 8 bajtów.Jeśli arg < 8, wyrównanie pamięci, zwracany jest pierwszy możliwości 2 mniej niż arg.Na przykład jeśli używasz malloc(7) wyrównanie jest 4 bajtów.
Definiowanie nowych typów z __declspec(align(#))
Można zdefiniować typ z cechę wyrównanie.
Na przykład można zdefiniować struct z Wyrównanie wartości w ten sposób:
struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;
Teraz aType i bType są tej samej rozmiar (w bajtach 8), ale zmiennych typu bType zostaną porównane 32 bajtów.
Wyrównywanie danych w lokalnego magazynu wątków
Statyczny wątku lokalnej pamięci masowej (TLS) utworzone za pomocą __declspec(thread) atrybutu i umieścić w sekcji TLS do utworów obrazu dla wyrównanie dokładnie tak samo jak normalne danych statycznych.Tworzenie danych TLS, system operacyjny przydziela pamięć rozmiar sekcji TLS i szanuje atrybut wyrównania sekcji TLS.
Ten przykład przedstawia różne sposoby umieszczania danych wyrównane do lokalnego magazynu wątków.
// put an aligned integer in TLS
__declspec(thread) __declspec(align(32)) int a;
// define an aligned structure and put a variable of the struct type
// into TLS
__declspec(thread) __declspec(align(32)) struct F1 { int a; int b; } a;
// create an aligned structure
struct CACHE_ALIGN S9 {
int a;
int b;
};
// put a variable of the structure type into TLS
__declspec(thread) struct S9 a;
Jak wyrównać współdziała z pakowania danych
/Zp Opcję kompilatora i pack dyrektywę pragma skutkuje pakowania danych struktury i Unii elementów członkowskich.W tym przykładzie przedstawiono sposób /Zp i __declspec(align(#)) współpracy:
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
W poniższej tabeli przedstawiono przesunięcie każdego członka w różnych /Zp (lub #pragma pack) wartości przedstawiający sposób korzystania przez dwa.
Zmienna |
/ Zp1 |
/ Zp2 |
/ Zp4 |
/ Zp8 |
---|---|---|---|---|
a |
0 |
0 |
0 |
0 |
b |
1 |
2 |
2 |
2 |
c |
3 |
4 |
4 |
8 |
d |
32 |
32 |
32 |
32 |
e |
40 |
40 |
40 |
40 |
f |
41 |
42 |
44 |
48 |
elemencie sizeof (S) |
64 |
64 |
64 |
64 |
Aby uzyskać więcej informacji, zobacz /Zp (Wyrównanie członka struktury).
Przesunięcie obiektu jest oparta na przesunięcie obiektu poprzedniego i bieżącego ustawienia pakowania, chyba że obiekt ma __declspec(align(#)) atrybutów, w takim przypadku wyrównanie jest oparta na przesunięcie poprzedniego obiektu i __declspec(align(#)) wartość dla tego obiektu.