2016-08-17 6 views
7

Szukam wydajności testów porównawczych za pomocą rejestru znacznika czasu (TSR) znalezionego w procesorach x86. Jest to przydatny rejestr, ponieważ mierzy on w monotonicznej jednostce czasu, która jest odporna na zmianę prędkości zegara. Bardzo fajny.Czy znacznik czasu Intela czyta przykład kodu asm przy użyciu dwóch dodatkowych rejestrów, niż jest to konieczne?

Oto dokument firmy Intel pokazujący fragmenty kodu ASM do rzetelnego testu porównawczego za pomocą TSR, w tym użycie narzędzia cpuid do synchronizacji potoku. Patrz strona 16:

http://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html

Aby odczytać godzinę rozpoczęcia, to mówi (I odnotowany trochę):

__asm volatile (
    "cpuid\n\t"    // writes e[abcd]x 
    "rdtsc\n\t"    // writes edx, eax 
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t" 
    // 
    :"=r" (cycles_high), "=r" (cycles_low) // outputs 
    :          // inputs 
    :"%rax", "%rbx", "%rcx", "%rdx");  // clobber 

Zastanawiam się dlaczego rejestry zdrapki są wykorzystywane do podejmowania wartości edx i eax. Dlaczego nie usunąć movs i nie odczytać wartości TSR zaraz po edx i eax? Tak:

__asm volatile(                
    "cpuid\n\t" 
    "rdtsc\n\t" 
    // 
    : "=d" (cycles_high), "=a" (cycles_low) // outputs 
    :          // inputs 
    : "%rbx", "%rcx");      // clobber  

W ten sposób można zaoszczędzić dwa rejestry, zmniejszając prawdopodobieństwo C kompilatora, która chciałaby rozlać.

Mam rację? Czy te MOV są w jakiś sposób strategiczne?

(zgadzam się, że potrzebujemy rejestrów zarysowania odczytać godzinę przystanek, jak w tym scenariuszu kolejność instrukcji jest odwrotna: trzeba rdtscp, ..., CPUID instrukcji CPUID niszczy. wynik rdtscp).

Dzięki

+2

Nie jestem ekspertem od wbudowanej składni GCC, ale zgaduję, że w drugiej wersji GCC wygeneruje * movs * samodzielnie, więc jest to kwestia czytelności. Uwaga boczna: nie powinno się '' rdtsc'be * otaczać * serializującymi instrukcjami, nie tylko wcześniej? Zwykle używam 'lfence' na rzecz' CPUID', ponieważ jest to lokalna serializacja i nie blokuje żadnego rejestru. –

+0

Spodziewam się, że pół-sprytny kompilator ponownie użyje rejestru wyjściowego dla zmiennej lokalnej, ale mogę się mylić. –

+0

Odnośnie 'lfence', czy masz źródło, które demonstruje? –

Odpowiedz

6

Masz rację, przykład jest niezgrabny. Zwykle jeśli mov jest pierwszą lub ostatnią instrukcją w instrukcji inline-asm, robisz to źle i powinieneś użyć ograniczenia, aby poinformować kompilator, gdzie chcesz dane wejście, lub gdzie jest wyjście.

Zobacz my GNU C inline asm guides/links collection i inne linki w tagu wiki o numerze . (The tag wiki jest pełen dobrych rzeczy dla ASM w ogóle, zbyt.)


mierzy w monotonicznego jednostce czasu, który jest odporny na zmiany prędkości zegara.

do profilowania, to często bardziej przydatne razy w cyklach zegara rdzenia, nie czas na ścianie zegar, so your microbenchmark results don't depend on power-saving/turbo. Liczniki wydajności może to i wiele więcej zrobić.

Mimo to, jeśli w czasie rzeczywistym jest to, co chcesz, rdtsc jest najtańszym sposobem na uzyskanie tego.


I re: dyskusja w komentarzach: tak cpuid jest tam do serializacji, upewniając się, że rdtsc i Poniższe instrukcje nie może się rozpocząć dopiero po wykonaniu CPUID. Możesz wstawić kolejny CPUID po RDTSC, ale to zwiększy narzut pomiarowy i myślę, że daje prawie zerowy wzrost dokładności/precyzji.

Nigdy nie odkryłem, kiedy/dlaczego LFENCE przydaje się przy RDTSC. instruction ref manual entry mówi tylko, że zamawia ładowanie instrukcji z pamięci. wszystkie pozostałe instrukcje. Prawdopodobnie mikroarchitektury Intela mają mocniejsze uporządkowanie dla LFENCE, ale pozostawiają oficjalnego ISA słabszego, aby mogli go zmienić bez komplikacji w stosunku do opublikowanego podręcznika.

Margaret Bloom wykopała this useful link, co oznacza, że ​​SDM Intela mówi, że LFENCE serializuje RDTSC, i ma inne rzeczy o tym, jak zrobić serializację wokół RDTSC.

+0

Dzięki za odpowiedź! Właściwie to wcale nie chcieliśmy czasu! Chcieliśmy, aby miara pracy była niezależna od czasu, więc zmiany częstotliwości nie mogą skosić wyniku. Znalazłem kilka liczników wydajności, które mogą pomóc, teraz będę szukał lekkiego sposobu na dostęp do nich bez użycia młota, który jest perf. Mam nadzieję, że możesz zaprogramować liczniki z kodu asm. –

+0

A może nie możesz: http: // stackoverflow.com/questions/39021662/how-to-configure-and-sample-intel-performance-counters-in-process –

+0

Możesz programować liczniki z przestrzeni użytkownika, ale prawdopodobnie chcesz przypiąć swoje wątki do rdzeni, ponieważ PMC nie są zapisane/przywrócone na przełącznikach kontekstowych. Zobacz http://agner.org/optimize/ dla istniejącego modułu jądra, który zapewnia dostęp do PMC, a także http://stackoverflow.com/questions/38848914/pmu-for-multi-threaded-environment/38984414#38984414 dla trochę dyskusji na temat ich używania. –

3

Nie, nie wydaje się być dobrym powodem dla redundantnych instrukcji MOV w zespole liniowym. Papier pierwszy wprowadza inline assembly z następującym stwierdzeniem:

asm volatile (
    "RDTSC\n\t" 
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t": "=r" (cycles_high1), "=r" (cycles_low1)); 

Ma to oczywisty problem, że nie poinformować kompilator, że EAX i EDX zostały zmodyfikowane przez instrukcję RDTSC. W artykule zwraca uwagę na ten błąd i koryguje je za pomocą clobbers:

asm volatile ("RDTSC\n\t" 
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: 
    “%eax”, “%edx”) 

Żadne inne uzasadnienie podano do pisania to w ten sposób inny niż skorygowania błędu w poprzednim przykładzie. Wydaje się, że autor referatu jest po prostu nie wie, że to może być napisany po prostu jako:

asm volatile ("RDTSC\n\t" 
    : "=d" (cycles_high), "=a" (cycles_low)); 

Podobnie autor najwyraźniej nieświadomy, że jest prostsza wersja poprawiła oświadczenie asm który używa RDTSC w połączeniu z CPUID, jak demonstrujesz w swoim poście.

Należy zauważyć, że autor artykułu wielokrotnie nadużywa terminu "IA64", aby odnieść się do 64-bitowego zestawu instrukcji i architektury x86 (różne nazwy, takie jak x86_64, AMD64 i Intel 64). Architektura IA-64 jest w rzeczywistości czymś zupełnie innym, jest używana przez procesory Intela Itaninum. Nie ma rejestrów EAX lub RAX i nie ma instrukcji RDTSC.

Podczas gdy nie ma to znaczenia, że ​​wbudowane złożenie autorów jest bardziej złożone niż to konieczne, fakt ten w połączeniu z niewłaściwym wykorzystaniem IA64, czegoś, co powinno zostać przyłapane przez redaktorów Intela, sprawia, że ​​wątpię w wiarygodność tego dokumentu.

+0

Dzięki za odpowiedź. Gdybym mógł zaznaczyć dwie odpowiedzi poprawnie, zrobiłbym to! Używają one 'cpuid' w dokumencie, to tam dostałem go, patrz strona 16. –

+1

@EddBarrett Yah, Wiem, mówię, że autor również nie wie, że wersja CPUID asm oświadczenie w papier można również uprościć w ten sam sposób. –

Powiązane problemy