2013-05-22 9 views
5

Jak wiemy, procesor X86 ma 64-bitową magistralę danych. Rozumiem, że procesor nie może uzyskać dostępu do arbitralnego adresu. Adres, do którego CPU może uzyskać dostęp, jest całkowitą wielokrotnością szerokości magistrali danych. Aby uzyskać wydajność, zmienne powinny rozpoczynać się od (wyrównane do) tych adresów, aby uniknąć dodatkowego dostępu do pamięci. Zmienne 32-bitowe wyrównane do granicy 4-bajtowej zostaną automatycznie wyrównane do granicy 8-bajtowej (64-bitowej), co odpowiada 64-bitowej magistrali danych x86. Ale dlaczego kompilatory wyrównują 128-bitowe zmienne do granicy 16-bajtowej? Nie granica 8 bajtów?dlaczego zmienne 128-bitowe powinny być wyrównane do granicy 16 bitów

Dzięki

Pozwolę sobie uściślić sytuację. Kompilatory używają długości zmiennej do wyrównania. Na przykład, jeśli zmienna ma długość 256 bitów, program Complier wyrówna ją do granicy 32 bajtów. Nie sądzę, że istnieje jakikolwiek procesor ma tak długą magistralę danych. Co więcej, wspólne pamięci DDR przesyłają dane 64-bitowe tylko raz, pomimo pamięci podręcznej, w jaki sposób pamięć może zapełnić szerszą magistralę danych procesora? lub tylko za pomocą pamięci podręcznej?

+3

"Jak wiemy, procesor X86 ma 64-bitową magistralę danych" - to nieprawda. x86 nie mówi nic o rozmiarach magistrali danych. Nowoczesne procesory mają w rzeczywistości większe szerokości magistrali danych. – Mysticial

+4

Procesor nie odczytuje danych z magistrali danych, lecz odczytuje je z pamięci podręcznej. 16-bajtowe wyrównanie jest wymagane, aby uniknąć przekroczenia granicy linii pamięci podręcznej. –

+0

@Mysticial Myślę, że najbardziej popularne procesory x86 obecnie mają 64-bitową magistralę danych, prawda? – iqapple

Odpowiedz

4

Jest tak wiele różnych modeli procesorów, na które zamierzam odpowiedzieć tylko w kategoriach teoretycznych i ogólnych.

Rozważmy tablicę 16-bajtowych obiektów rozpoczynającą się od adresu o wielokrotności ośmiu bajtów, ale nie o 16 bajtów. Załóżmy, że procesor ma ośmiobajtową magistralę, jak wskazano w pytaniu, nawet jeśli niektóre procesory tego nie robią. Należy jednak zauważyć, że w pewnym momencie w tablicy jeden z obiektów musi przechodzić przez granicę strony: Mapowanie pamięci zwykle działa na 4096-bajtowych stronach rozpoczynających się od granic 4096-bajtowych. W przypadku tablicy o ośmiu bajtach element tablicy zaczyna się od bajtu 4088 na jednej stronie i przechodzi do bajtu 7 na następnej stronie.

Gdy program próbuje załadować 16-bajtowy obiekt, który przekracza granicę strony, nie może już wykonywać pojedynczej mapy pamięci wirtualnej na fizyczną. Musi wykonać jedno wyszukiwanie dla pierwszych ośmiu bajtów i kolejne wyszukiwanie dla pozostałych ośmiu bajtów. Jeśli jednostka ładunkowa/magazynowa nie jest do tego zaprojektowana, wówczas instrukcja wymaga specjalnej obsługi. Procesor może przerwać pierwszą próbę wykonania instrukcji, podzielić ją na dwie specjalne mikroinstrukcje i wysłać je z powrotem do kolejki instrukcji w celu wykonania. Może to opóźnić instrukcję o wiele cykli procesora.

Ponadto, jak zauważył Hans Passant, wyrównanie współdziała z pamięcią podręczną. Każdy procesor ma pamięć podręczną pamięci i często pamięć podręczna jest zorganizowana w 32-bajtowe lub 64-bajtowe "linie". Jeśli załadujesz 16-bajtowy obiekt wyrównany do 16 bajtów, a obiekt znajduje się w pamięci podręcznej, pamięć podręczna może dostarczyć jedną linię pamięci podręcznej zawierającą potrzebne dane. Jeśli ładujesz 16-bajtowe obiekty z tablicy, która nie jest wyrównana do 16 bajtów, to niektóre z obiektów w tablicy będą zawierały dwie linie pamięci podręcznej. Po załadowaniu tych obiektów należy pobrać dwie linie z pamięci podręcznej. To może potrwać dłużej. Nawet jeśli nie zajmie to więcej czasu niż dwie linie, być może dlatego, że procesor jest zaprojektowany tak, aby zapewnić dwie linie pamięci podręcznej na cykl, może to wpływać na inne rzeczy wykonywane przez program. Zazwyczaj program ładuje dane z wielu miejsc. Jeśli obciążenia są wydajne, procesor może wykonać dwie operacje naraz. Ale jeśli jedna z nich wymaga dwóch linii pamięci podręcznej zamiast normalnej, blokuje równoczesne wykonywanie innych operacji ładowania.

Ponadto niektóre instrukcje wyraźnie wymagają wyrównania adresów. Procesor może wysłać instrukcje bezpośrednio, omijając niektóre testy, które naprawiają operacje bez wyrównanych adresów. Kiedy adresy tych instrukcji zostaną rozwiązane i okaże się, że są źle wyrównane, procesor musi je przerwać, ponieważ operacje naprawcze zostały pominięte.

+0

Wiem, że masz rację, nawet jeśli niektóre punkty są dla mnie ezoteryczne – iqapple

+0

IMO, większość z tej odpowiedzi, choć sama w sobie jest prawdziwa, jest nieistotna dla qustion, który był "Ale dlaczego kompilatory wyrównać 128-bitowe zmienne do granicy 16Byte? ". Odpowiedź na to pytanie jest po prostu taka, że ​​wymaga tego sprzęt, kompilator tego nie robi, ponieważ jest bardziej wydajny, ale ponieważ jakikolwiek inny sposób nie zadziała. mówisz "Rozważmy tablicę 16-bajtowych obiektów, która zaczyna się od adresu będącego wielokrotnością ośmiu bajtów, ale nie 16 bajtów.", dobrze, że po prostu nie zadziała (ponieważ sprzęt procesora nie obsługuje go) niezależnie czy tablica przekracza granicę strony. – Bull

+0

W rzeczywistości zależy to od tego, co oznacza pytanie "zmienna". Myślałem o 128 zmiennych, takich jak __m128i. Jeśli chodzi o rzeczy takie jak 'struct foo {char x [128];} ;, to zgadzam się z Erikiem. – Bull

5

Jednym z powodów jest to, że większość instrukcji SSE2 na X86 wymaga, aby dane były wyrównane do 128 bitów. Ta decyzja projektowa zostałaby podjęta ze względu na wydajność i unikanie nadmiernie złożonego (a zatem wolnego i dużego) sprzętu.

+0

Myślę, że to jest prawdopodobnie dobrze utknąłem tutaj w pętli próbuje dowiedzieć się, które kompilatory automatycznie wyrównują __m128i typ używany do wektoryzacji obliczeń SIMD –

Powiązane problemy