Dlaczego podział sprzętu zajmuje znacznie więcej czasu niż mnożenie na mikrokontrolerze? Na przykład na dsPIC podział zajmuje 19 cykli, a mnożenie zajmuje tylko jeden cykl zegara.
Przeszedłem kilka samouczków, w tym algorytm podziału i algorytm mnożenia na Wikipedii. Oto moje rozumowanie.
Algorytm podziału, podobnie jak metoda powolnego podziału z przywracaniem w Wikipedii, jest algorytmem rekurencyjnym. Oznacza to, że (pośrednie) wyniki z kroku k
są wykorzystywane jako dane wejściowe do kroku k+1
, co oznacza, że algorytmów tych nie można zrównoleglać. Dlatego n
ukończenie podziału wymaga co najmniej cykli, podczas gdy n
dywidenda to pewna liczba bitów. W przypadku dywidend 16-bitowych jest to co najmniej 16 cykli.
Algorytm mnożenia nie musi być rekurencyjny, co oznacza, że można go zrównoleglić. Istnieje jednak wiele różnych algorytmów mnożenia i nie mam pojęcia, który z nich może być wykorzystany przez mikrokontrolery. Jak działa mnożenie na sprzęcie / mikrokontrolerze?
Znalazłem algorytm mnożnika Daddy , który powinien zająć tylko jeden cykl zegara, aby zakończyć. Jednak nie rozumiem, że algorytm Daddy postępuje w trzech krokach, podczas gdy wyniki z kroku 1 są wykorzystywane w kroku 2 itd. Zgodnie z tym, ukończenie zajmie co najmniej trzy cykle zegara.
źródło
Odpowiedzi:
Dzielnik mapuje znacznie mniej elegancko na typowy sprzęt. Jako przykład weźmy układy FPGA Lattice ICE40.
Porównajmy dwa przypadki: ten mnożnik 8 x 8 bitów do 16 bitów:
i ten dzielnik, który redukuje operandy 8 i 8 bitów do wyniku 8 bitów:
(Tak, wiem, zegar nic nie robi )
Przegląd wygenerowanego schematu podczas mapowania mnożnika na układ FPGA ICE40 można znaleźć tutaj, a dzielnik tutaj .
Statystyki syntezy z Yosys są następujące:
zwielokrotniać
podzielić
Warto zauważyć, że wielkość generowanego verilog dla mnożnika o pełnej szerokości i dzielnika maksymalnie dzielącego nie są tak ekstremalne. Jeśli jednak spojrzysz na poniższe zdjęcia, zauważysz, że mnożnik ma być może głębokość 15, podczas gdy dzielnik wygląda bardziej na około 50; ścieżka krytyczna (tj. najdłuższa ścieżka, która może wystąpić podczas pracy) określa prędkość!
W każdym razie nie będziesz w stanie tego przeczytać, aby uzyskać wrażenie wizualne. Myślę, że różnice w złożoności są możliwe do zauważenia. Są to multiplikatory / dzielniki dla jednego cyklu!
Zwielokrotniać
Pomnóż na ICE40 (ostrzeżenie: ~ 100 Mpixel obraz)
Podzielić
( Podziel na ICE40 ) (ostrzeżenie: ~ 100 Mpixel obraz)
źródło
Powolny podział jest z natury iteracyjny, więc zwykle trwa dłużej. Istnieją nieco szybsze algorytmy powolnego podziału niż te proste, wykorzystujące tabele wyszukiwania. Algorytm SRT wytwarza dwa bity na cykl. Błąd w takiej tabeli był przyczyną niesławnego błędu Pentium FDIV (ok. 1994). Są też tak zwane algorytmy szybkiego podziału.
Oczywiście w zasadzie można po prostu użyć ogromnej tabeli odnośników do obliczenia iloczynu lub ilorazu dwóch liczb, a tym samym uzyskania wyników w jednym cyklu, ale tendencja ta szybko staje się niepraktyczna wraz ze wzrostem liczby bitów na liczbę.
źródło
Możemy mieć wiele warstw logiki na cykl zegara, ale istnieje limit, dokładnie to, ile warstw logiki możemy mieć, jak złożone mogą być te warstwy, będzie zależeć od naszej szybkości zegara i naszego procesu półprzewodnikowego.
Afaict większość mnożenia na komputerach używa wariantu binarnego długiego mnożenia. Binarne długie mnożenie obejmuje
Przyjrzyjmy się więc implementacji tego w sprzęcie.
Pozwala więc na sprawdzenie, ile etapów logicznych potrzebujemy dla mnożnika 8x8 z 16-bitowymi wynikami. Dla uproszczenia załóżmy, że nie próbujemy optymalizować tego, że nie wszystkie wyniki pośrednie mają bity we wszystkich pozycjach.
Załóżmy, że pełny sumator jest implementowany w dwóch „etapach bramki”.
Łącznie około 46 etapów logicznych. Większość z nich wydaje się na zsumowanie dwóch ostatnich wyników pośrednich.
Można to jeszcze bardziej ulepszyć, wykorzystując fakt, że nie wszystkie wyniki pośrednie mają wszystkie bity obecne (to jest w zasadzie to, co robi mnożnik dada), poprzez użycie sumatora przeniesienia wyprzedzającego dla ostatniego etapu. Dodając 7 liczb, otrzymujemy 3 zamiast trzech, aby wyprodukować dwa (zmniejszenie liczby etapów w cenie większej liczby bram i szerszych bram) itp.
To wszystko drobne szczegóły, ważne jest to, że liczba etapów potrzebnych do pomnożenia dwóch liczb n bitów i uzyskania wyniku 2n bitowego jest w przybliżeniu proporcjonalna do n.
Z drugiej strony, jeśli spojrzymy na algorytmy podziału, stwierdzimy, że wszystkie one mają iteracyjny proces gdzie.
Zatem liczba etapów logicznych wymaganych do wdrożenia podziału jest w przybliżeniu proporcjonalna do n do kwadratu.
źródło
Algorytm podziału (w rzeczywistości dowolny algorytm) można wykonać w jednym cyklu zegara. Jeśli chcesz zapłacić za dodatkowe tranzystory i niższą dozwoloną częstotliwość taktowania.
Załóżmy, że masz zestaw bramek, które implementują jeden cykl zegara istniejącego algorytmu podziału wielocyklowego. Aby algorytm był jednym cyklem, użyj wielu etapów sprzętu (podobnego do stosowanego w jednym etapie algorytmu wielocyklowego), z wyjściem jednego etapu zasilającym następny etap.
Oczywiście powodem tego nie jest, ponieważ używa wielu tranzystorów. Na przykład dla 16-bitowego podziału może użyć prawie 16 X więcej tranzystorów. Również posiadanie większej liczby bramek obniża maksymalną dozwoloną częstotliwość taktowania (ponieważ jest więcej etapów opóźnienia propagacji).
źródło
Praktyczne algorytmy podziału oparte są na zestawach numerycznych, które są zbieżne z ilorazem.
Istnieją metody addytywne, takie jak brak przywracania lub SRT, który działa poprzez dodanie lub usunięcie 2 ^ N do ilorazu i odpowiednio dodanie lub usunięcie dzielnika 2 ^ N * do częściowej reszty, aż zbiegnie się do zera.
Istnieją metody mnożenia, takie jak Newton-Raphson lub Goldshmidth, które są metodami znajdowania pierwiastków, w których dzielenie jest obliczane jako odwrotność mnożenia.
Metody addytywne dają jeden lub kilka bitów na cykl. Metody multiplikatywne podwajają liczbę bitów dla każdego cyklu, ale wymagają wstępnego przybliżenia, często uzyskiwanego przy stałej tabeli.
Mianowania „powolne” i „szybkie” wprowadzają w błąd, ponieważ rzeczywista prędkość zależy od liczby bitów, ilości sprzętu przeznaczonej na tę funkcję (a szybki mnożnik jest bardzo duży) ...
Podział jest wolniejszy niż mnożenie, ponieważ nie ma bezpośredniej, równoległej metody jego obliczania: albo istnieje iteracja, albo sprzęt jest kopiowany w celu zaimplementowania iteracji jako bloków kaskadowych (lub potokowych).
źródło
To nie jest pytanie dotyczące elektroniki. W najlepszym razie jest to pytanie komputerowe, lepiej skierowane do przepełnienia stosu.
Zobacz na przykład tutaj: Czy mnożenie jest szybsze niż dzielenie zmiennoprzecinkowe?
W rzeczywistości jest to pytanie z życia: dlaczego podział trwa tak długo, jak rozmnażanie?
Co wolisz obliczać na papierze?
lub
Dzielenie trwa dłużej niż mnożenie, ponieważ jest trudniejsze .
źródło