2016-05-26 47 views
5

Próbuję zrozumieć właściwy sposób użycia ogrodzeń podczas pomiaru czasu z RDTSC/RDTSCP. Kilka pytań na temat SO związanych z tym zostały już szczegółowo wyjaśnione. Przeszedłem przez kilka z nich. Przeszedłem również przez ten naprawdę pomocny artykuł na ten sam temat: http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdfx86-64 użycie LFENCE

Jednak w innym blogu online jest przykład użycia LFENCE zamiast CPUID na x86. Zastanawiałem się, w jaki sposób LFENCE zapobiega zanieczyszczaniu pomiarów RDTSC przez wcześniejsze sklepy. E.g.

<Instr A> 
LFENCE/CPUID 
RDTSC 
<Code to be benchmarked> 
LFENCE/CPUID 
RDTSC 

W powyższym przypadku, LFENCE zapewnia wszystkie wcześniejsze obciążenia to kompletna przed nim (Od SDM mówi. Instrukcje LFENCE nie może przechodzić wcześniej odsłon). Ale co z wcześniejszymi sklepami (np. Instr A był sklepem)? Rozumiem, dlaczego CPUID działa, ponieważ jest to instrukcja serializacji, ale LFENCE nie jest.

Jedno wyjaśnienie znalazłem w Intel SDM VOL 3A pkt 8.3 dodaje się przypis:

LFENCE daje pewne gwarancje na polecenie Zamawiającego. Nie wykonuje się, dopóki wszystkie wcześniejsze instrukcje nie zostaną zakończone lokalnie, a żadne późniejsze instrukcje nie zostaną rozpoczęte, dopóki LFENCE nie zostanie ukończone.

Zasadniczo LFENCE zachowuje się jak UROCZYSTOŚĆ. W takim przypadku, dlaczego potrzebujemy dwóch oddzielnych instrukcji LFENCE i MFENCE?

Prawdopodobnie czegoś brakuje.

Z góry dziękuję.

Odpowiedz

5

Kluczowym punktem jest przysłówek lokalnie w cytowanym zdaniu „nie wykonuje aż wszystkie wcześniejsze instrukcje zakończyły lokalnie”.

Nie byłem w stanie znaleźć jasnej definicji "kompletnie lokalnie" całego zestawu instrukcji Intela, moje spekulacje wyjaśniono poniżej.


Aby zostać zakończone lokalnie instrukcja musi mieć to wyjście obliczane i dostępne dla innych instrukcji dalej w łańcuchu zależności. Ponadto wszelkie skutki uboczne tej instrukcji muszą być widoczne wewnątrz rdzenia.

Aby być ukończonym globalnie, instrukcja musi mieć efekty uboczne widoczne dla innych składników systemu (takich jak inne procesory).

Jeśli nie kwalifikujemy się do rodzaju "kompletności", o której mówimy, oznacza to, że nie ma to znaczenia lub jest ukryte w kontekście.


Dla wielu instrukcji wykonywanych lokalnie i globalnie, jest taki sam.
Na przykład, aby załadować , na przykład, w celu dokończenia lokalnie, niektóre dane muszą zostać pobrane z pamięci lub pamięci podręcznych. Jest to równoznaczne z ukończeniem globalnym, ponieważ nie możemy oznaczyć obciążenia, jeśli nie odczytujemy najpierw z hierarchii pamięci.

Dla sklepu sklep sytuacja jest jednak inna.

procesory

Intel mają Store Buffer obsłużyć zapisuje w pamięci, z rozdziału 11.10 podręcznika 3:

Intel 64 i procesorów IA-32 czasowego przechowywania każdego zapisu (Store) do pamięci w bufor do przechowywania. Bufor sklepu poprawia wydajność procesora, umożliwiając procesorowi kontynuowanie wykonywania instrukcji bez konieczności oczekiwania na zapis do pamięci i/lub do pamięci podręcznej. Umożliwia także opóźnianie zapisów w celu bardziej efektywnego wykorzystania cykli magistrali dostępu do pamięci.

Sklep można uzupełnić lokalnie, umieszczając go w buforze sklepu, z perspektywy rdzenia zapis jest taki, jak w pamięci.
Obciążenie z tego samego rdzenia sklepu, w określonych okolicznościach, może nawet odczytać tę wartość (nazywa się to Store Forwarding).

Do uzupełnienia globalnie jednak sklep musi być wyczerpany z bufora sklepu.

Wreszcie jest obowiązkowe, aby dodać, że magazyn buforowy jest odprowadzana przez szeregowania instrukcji:

zawartość bufora sklepie są zawsze odprowadzana do pamięci w następujących sytuacjach:
• (P6 i nowsza Procesor tylko rodziny) Kiedy wykonywana jest instrukcja serializacyjna.
• (tylko Pentium III i nowsze rodziny procesorów) Podczas korzystania z instrukcji SFENCE do zamawiania sklepów.
• (tylko modele Pentium 4 i nowsze rodziny procesorów) Podczas korzystania z instrukcji EFENCE do zamawiania sklepów.


robione z wprowadzeniem, zobaczmy co lfence, mfence i sfence zrobić:

LFENCE nie wykonuje aż wszystkie wcześniejsze instrukcje zakończyły lokalnie, a nie później nauka rozpoczyna realizację aż LFENCE kończy.

MFENCE wykonuje operację serializacji na wszystkich instrukcjach load-from-memory i store-to-memory, które zostały wydane przed instrukcją MFENCE. Tryb MFENCE nie przekształca serialu w strumień instrukcji.

SFENCE wykonuje operację serializacji na wszystkich instrukcjach zapisywania do pamięci, które zostały wydane przed instrukcją SFENCE.

Więc lfence jest słabsza forma serializacji że nie odprowadza sklepu Buffer, ponieważ skutecznie serializacji instrukcji lokalnie, wszystkie ładunki przed nim musi być zakończone przed jej zakończeniem.

sfence serializuje tylko sklepy, zasadniczo nie pozwala procesowi na wykonanie kolejnego sklepu, dopóki nie zostanie wycofany sfence. Drenuje również bufor Sklepu.

mfence jest nie prosta kombinacja tych dwóch, ponieważ nie jest szeregowania w klasycznym tego słowa znaczeniu, jest to sfence że również zapobiec przyszłym ładunki mają być wykonane.


Warto może nic że sfence został wprowadzony pierwszy i pozostałe dwójki przyszedł później, aby osiągnąć bardziej precyzyjną kontrolę nad porządkowania pamięci.

Wreszcie, zostałem użyty do zamknięcia instrukcji rdtsc między dwiema instrukcjami: lfence, aby upewnić się, że nie było możliwości zmiany kolejności "do tyłu" i "do przodu".
Jestem jednak pewien, że ta technika jest dobra.

+0

Dzięki za skomplikowaną odpowiedź. Więc jeśli dobrze rozumiem, LFENCE nie drenuje bufora magazynu, ale powoduje, że procesor czeka, aż wszystkie poprzednie instrukcje ładowania i przechowywania zakończą się lokalnie. W takim przypadku nie możemy polegać na pomiarze czasu (RDTSC) na końcu naszego kodu testu porównawczego? Ponieważ chcesz upewnić się, że zapisy zostały wykonane globalnie (przepłukane do pamięci) przed pomiarem czasu. Dzięki. –

+0

'lfence' może być użyte do pomiaru * jeśli nie chcesz czekać *, aby sklepy stały się widoczne na całym świecie. Pisanie do pamięci wymaga wielu cykli, a jeśli nie będziesz dokładnie zapisywać w pamięci podręcznej, otrzymasz niespójne wyniki. Zwykle jeden urlop zapisuje do pamięci test porównawczy, chyba że chcesz jawnie je przetestować. W takim przypadku użyj 'lfence' z' sfence' lub serializującą instrukcję, która nie spowoduje nadpisania potrzebnych rejestrów. –

+0

Ma sens. Dziękuję bardzo. –

1

Jak słusznie zauważyłeś, jest to kwestia serializacji . Jeśli chodzi o twoje pytanie:

dlaczego potrzebujemy dwóch oddzielnych instrukcji LFENCE i MFENCE?

zostanie odebrane w Intel SDM w sekcji "5.6.4 - SSE2 Kontroli Cacheability i zamawianie instrukcji":

LFENCE Serializes operacji obciążenia
MFENCE serializes operacji ładowania i przechowywania

Tak więc LFENCE jest prawdopodobnie używany, ponieważ MFENCE nie jest konieczne dla RDTSC.