Zadanie jest proste: napisz asembler, który oblicza rząd wielkości liczby całkowitej przy użyciu jak najmniejszej liczby cykli zegara.
- Rząd wielkości jest zdefiniowany jako
log10
, a nielog2
. - Zakres ważny wkład jest
0
do włącznie. Zachowanie danych wejściowych poza tym zakresem jest niezdefiniowane.1012
- Wartości należy zaokrąglić w dół do najbliższej liczby całkowitej, z wyjątkiem tego, że przy danych wejściowych
0
wyjście powinno być0
. (Można to uznać za najlepszą reprezentację ujemnej nieskończoności możliwą w liczbach całkowitych bez znaku). - Musi być montażem x86.
- Liczba całkowita musi być wartością czasu wykonywania , a nie liczbą całkowitą statyczną / wbudowaną. Nie wiemy więc, co to jest w czasie kompilacji.
- Załóżmy, że masz już załadowaną liczbę całkowitą do rejestru. (Ale w celu zwiększenia przejrzystości należy uwzględnić ustawienie wartości w rejestrze).
- Nie można wywoływać żadnych zewnętrznych bibliotek ani funkcji.
- Bezpłatnie korzystać z dowolnych instrukcji dostępnych w dokumentach firmy Intel .
- Nie C.
- Dowolna z ~ 7 architektur Intel Core jest akceptowalna (wymienionych na stronie 10 ). Idealnie Nehalem (Intel Core i7).
Zwycięską odpowiedzią jest ta, która wykorzystuje najmniejszą możliwą liczbę cykli zegara. Oznacza to, że może mieć najwięcej operacji na sekundę. Przybliżone podsumowania cyklu zegara znajdują się tutaj: http://www.agner.org/optimize/instruction_tables.pdf . Obliczanie cykli zegara może nastąpić po opublikowaniu odpowiedzi.
math
fastest-algorithm
assembly
Lance Pollard
źródło
źródło
Odpowiedzi:
7 cykli, stały czas
Oto rozwiązanie oparte na mojej odpowiedzi na to SO Pytanie . Używa BSR do zliczania, ile bitów jest potrzebnych do utrzymania liczby. Sprawdza, ile cyfr dziesiętnych jest potrzebnych do przedstawienia największej liczby, jaką może pomieścić wiele bitów. Następnie odejmuje 1, jeśli faktyczna liczba jest mniejsza niż najbliższa potęga 10 z taką liczbą cyfr.
Kompiluje na GCC 4.6.3 dla Ubuntu i zwraca wartość w kodzie wyjścia.
Nie jestem pewien interpretacji tej tabeli cykli dla dowolnego nowoczesnego procesora, ale używając metody @ DigitalTrauma na procesorze Nehalim, mam 7 ?
źródło
The integer must be a runtime value, not a static/inline integer. So we don't know what it is at compile time.
Najlepszy przypadek 8 cykli, Najgorszy przypadek 12 cykli
Ponieważ pytanie nie jest jasne, opieram to na opóźnieniach Ivy Bridge.
Podejście polega na użyciu instrukcji
bsr
(odwrotne skanowanie bitów) jako log2 biedaka (). Wynik jest używany jako indeks do tabeli skoków, która zawiera wpisy dla bitów od 0 do 42. Zakładam, że biorąc pod uwagę, że operacja na danych 64-bitowych jest niejawnie wymagana, to użyciebsr
instrukcji jest OK.W najlepszych przypadkach dane wejściowe z możliwością zbierania mogą odwzorować
bsr
wynik bezpośrednio na wielkość. np. dla danych wejściowych z zakresu 32-63bsr
wynikiem będzie 5, który jest odwzorowany na wielkość 1. W tym przypadku ścieżka instrukcji to:W najgorszym przypadku dane wejściowe
bsr
zostaną odwzorowane na dwie możliwe wielkości, więc wpis z możliwością zbierania dodaje jeszcze jedną wartość,cmp
aby sprawdzić, czy wartość wejściowa jest> 10 n . Np. Dla danych wejściowych z zakresu 64-127bsr
wynik będzie wynosić 6. Odpowiedni wpis , który można przesuwać, sprawdza, czy dane wejściowe> 100, i odpowiednio ustawia wielkość wyjściową.Dodatkowo dla ścieżki najgorszego przypadku mamy dodatkową instrukcję mov, aby załadować 64-bitową wartość natychmiastową do użycia w
cmp
, więc ścieżka instrukcji najgorszego przypadku to:Oto kod:
Zostało to wygenerowane głównie z danych wyjściowych asemblera gcc dla kodu C w wersji proof-of-concept, który napisałem . Zauważ, że kod C używa obliczalnego goto do implementacji tabeli skoków. Używa również
__builtin_clzll()
wbudowanego gcc, który kompiluje się dobsr
instrukcji (plus anxor
).Rozważałem kilka rozwiązań, zanim doszedłem do tego:
FYL2X
obliczyć logarytm naturalny, a następnieFMUL
przez niezbędną stałą. Prawdopodobnie wygrałoby to, gdyby był to konkurs [tag: instrukcja: golf]. AleFYL2X
ma opóźnienie 90-106 dla mostu Ivy.Zakodowane wyszukiwanie binarne. To może faktycznie być konkurencyjne - zostawię to komuś innemu do wdrożenia :).
Kompletna tabela wyników. Jestem pewien, że jest teoretycznie najszybszy, ale wymagałby tabeli przeglądowej 1 TB - jeszcze niepraktycznej - może za kilka lat, jeśli Prawo Moore'a będzie nadal obowiązywać.
źródło
jmp
ijcc
nie mają opóźnień, tylko koszty przepustowości. Prognozowanie gałęzi + wykonywanie spekulacyjne oznaczają, że zależności sterujące nie są częścią łańcuchów zależności danych.