Professional Documents
Culture Documents
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG
Uczta programistw
Autorzy: Henry S. Warren, Jr.
Tumaczenie: Marek Ptlicki (rozdz. 1 9),
Bartomiej Garbacz (rozdz. 10 16, dod. A, B)
ISBN: 83-7361-220-3
Tytu oryginau: Hacker's Delight
Format: B5, stron: 336
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Niniejsza ksika jest doskona pozycj dla wszystkich programistw, ktrzy maj
zamiar tworzy wydajny kod. Uczta programistw nauczy Ci tworzenia aplikacji
wysokiej jakoci wyszej ni wymagana a uczelniach i kursach programowania.
Spis treci
Przedmowa...........................................................................................................9
Wstp ................................................................................................................11
Rozdzia 1. Wprowadzenie .................................................................................13
1.1. Notacja .......................................................................................................................13
1.2. Zestaw instrukcji i model wykonawczy .....................................................................17
Uczta programistw
Rozdzia 8. Mnoenie.......................................................................................151
8.1. Mnoenie czynnikw wieloelementowych ..............................................................151
8.2. Bardziej znaczca poowa 64-bitowego iloczynu ....................................................154
8.3. Konwersje midzy bardziej znaczc poow 64-bitowego iloczynu ze znakiem
i bez znaku ....................................................................................................................155
8.4. Mnoenie przez stae................................................................................................156
Spis treci
Rozdzia 7.
Manipulacja
bitami i bajtami
7.1. Odwracanie kolejnoci
bitw i bajtw
Przez operacje odwrcenia kolejnoci bitw (ang. reversing bits) rozumiemy wykonanie
odbicia lustrzanego, na przykad:
rev(0x01234567) = 0xE6A2C480
Przez operacj odwrcenia bajtw rozumiemy podobne odbicie, z tym, e w tym przypadku odwracamy kolejno bajtw w sowie. Odwracanie kolejnoci bajtw jest operacj konieczn w przypadku konwersji pomidzy formatami little-endian, stosowanymi
w procesorach DEC oraz Intel a formatem big-endian, stosowanym przez wikszo pozostaych producentw procesorw.
Odwrcenie kolejnoci bitw moe zosta wykonane w stosunkowo wydajny sposb
przez zamian kolejnoci ssiadujcych bitw, nastpnie zamian kolejnoci w ssiadujcych parach pl 2-bitowych itd. [Aus1]. Poniej przedstawiamy przykad realizacji tego
mechanizmu. Wszystkie operacje przypisania mona wykona w dowolnej kolejnoci.
Na wikszoci maszyn jest moliwe dokonanie niewielkiego usprawnienia, polegajcego na wykorzystaniu mniejszej liczby rnych staych oraz na wykonaniu ostatnich dwch
przypisa w bardziej bezporedni sposb, tak jak zostao przedstawione na listingu 7.1
(30 instrukcji z podstawowego zestawu RISC, bez rozgazie).
122
Uczta programistw
Ostatnie przypisanie zmiennej x w tym kodzie realizuje odwrcenie bajtw w dziewiciu instrukcjach zestawu podstawowego RISC. W przypadku, gdy maszyna udostpnia instrukcje przesuni cyklicznych, mona tego dokona w siedmiu instrukcjach,
wykorzystujc nastpujc formu:
rot
rot
Mona pomin ostatnie dwa wywoania instrukcji and. Dla k = 31 operacja ta dokonuje
odwrcenia bitw w sowie. Dla k = 24 odwraca bajty w sowie. Dla k = 7 odwraca
bity w kadym bajcie bez dokonywania zmian pooenia bajtw. Dla k = 16 dokonuje
zamiany psw w sowie itd. Oglnie mwic, operacja ta przenosi bit z pozycji m na
pozycj m k. Instrukcja ta moe zosta zaimplementowana w sprzcie w podobny
sposb, w jaki z reguy s implementowane instrukcje przesunicia cyklicznego (pi
segmentw MUX, z ktrych kady jest kontrolowany za pomoc jednego bitu rozmiaru przesunicia k).
123
maszyn, lecz wersja dla wartoci 6-bitowych dziaa rwnie na maszynie 32-bitowej,
natomiast wersje dla liczb 7 i 8-bitowych dziaaj na maszynach 64-bitowych.
6 bitw: remu((x 0x00082082) & 0x01122408, 255)
7 bitw: remu((x 0x40100401) & 0x442211008, 255)
8 bitw: remu((x 0x202020202) & 0x10884422010, 1023)
W wyniku powyszych wyrae powstaje czysta liczba cakowita wyrwnana do
prawej, bez zostawiania adnego niepotrzebnego bardziej znaczcego bitu.
W kadej z tych sytuacji funkcja moe zosta zastpiona funkcj lub
,
poniewa jej argumenty s liczbami dodatnimi. Funkcja (ang. reminder reszta
z dzielenia) po prostu sumuje cyfry liczby o podstawie 256 lub 1024, co dziaa zupenie tak samo, jak w przypadku metody odrzucania dziewitek (ang. casting out nines).
Dziki temu mona j zastpi za pomoc kombinacji mnoenia i przesuni w prawo.
Na przykad 6-bitowa formua posiada na maszynie 32-bitowej nastpujc posta alternatywn (mnoenie musi by wykonywane modulo 232):
t (x 0x00082082) & 0x01122408
u
( t 0x01010101) >> 24
124
Uczta programistw
(t 0x08040201) >> 27
125
Na wikszoci maszyn najpraktyczniejszy sposb realizacji tego zadania polega na utworzeniu tablicy przegldowej wszystkich wartoci (na przykad jednobajtowych lub 9-bitowych).
W algorytmie FFT zarwno liczba, i jak jej odwrcona wersja stanowi okrelon liczb bitw o okrelonej dugoci, ktra nigdy nie przekracza 32 i obydwie s wyrwnane do prawej w ramach rejestru. Zamy, e i jest 32-bitow liczb cakowit. Po zwikszeniu o 1 jej odwrconej wartoci przesunicie w prawo o odpowiedni liczb bitw
spowoduje, e liczba wynikowa stanie si waciw wartoci w algorytmie FFT (zarwno i, jak i rev(i) s wykorzystywane jako indeksy w tablicy).
Najprostszym sposb zwikszenia wartoci odwrconej liczby cakowitej jest wyszukanie lewostronnego zera, zmiana jego wartoci na 1 a nastpnie ustawienie wszystkich
bitw na lewo od tego miejsca na 0. Jeden ze sposobw realizacji tego algorytmu prezentuje nastpujcy listing:
(/
/
0/
"
1
//
0/
!2'3 /
!
126
Uczta programistw
1
1
1
1
3 + 7 + 11 + 15 + K
2
4
8
16
1
1
1
1
= 4 + 8 + 12 + 16 + K 1
4
8
16
2
1 2 3 4
= 4 + + + + K 1
2 4 8 16
= 7.
W drugim wierszu powyszych oblicze dodalimy i odjlimy 1, pierwsza z tych jedynek zostaa rozpisana jako 1/2 + 1/4 + 1/8 + 1/16 + . Pod tym wzgldem obliczenia te s podobne do przedstawionych na stronie 107). W najgorszym przypadku powyszy algorytm wymaga wykonania do duej liczby instrukcji, bo a 131.
W przypadku, gdy dostpna jest instrukcja wyliczajca liczb zer wiodcych, zwikszenie o 1 wartoci odwrconej liczby cakowitej mona zrealizowa w nastpujcy sposb:
Najpierw wyliczamy s nlz(x)
127
Zamy, e rozmiar sowa W jest potg liczby dwa. W tym przypadku operacj tasowania zupenego mona wykona za pomoc instrukcji podstawowego zestawu RISC
w log2(W/2) krokw. Kady z krokw skada si z zamiany kolejnoci drugiej i trzeciej
wiartki coraz mniejszego fragmentu sowa. Ilustruje to nastpujcy przykad:
$%&"'4#3/15,+)6789:;<=>?
$%&"',+)674#3/1589:;<=>?
$%&,+"')674#389:;/15<=>?
$%,&+")'67489#3:;/<=15>?
$%,&+)"6'7849#:3;/<=1>5?
Powyszy sposb wymaga zastosowania 42 instrukcji z podstawowego zestawu instrukcji RISC. Liczb t mona zredukowa do 30 lecz kosztem zwikszenia liczby
instrukcji w przypadku procesorw o nieograniczonej liczbie jednoczenie wykonywanych, niezalenych instrukcji. W tym celu wykorzystujemy instrukcj rnicy symetrycznej w celu wymiany ssiadujcych pl w rejestrze (opisywanej na stronie 57). W poniszym kodzie wszystkie wartoci s liczbami bez znaku:
0
0
0
0
0
0
0
0
0
0
0
0
Operacja odwrotna, zewntrzne odtasowanie (ang. outer unshuffle), moe zosta zrealizowana za pomoc odwrcenia kolejnoci operacji w powyszym kodzie:
0
0
0
0
0
0
0
0
0
0
0
0
Wykorzystanie dwch ostatnich krokw z dowolnego z powyszych algorytmw tasowania spowoduje potasowanie kadego z bajtw osobno. Wykorzystanie ostatnich trzech
krokw spowoduje potasowanie kadego z psw osobno itd. Podobne uwagi dotycz
operacji odtasowania, z t rnic, e kroki liczymy od pocztku.
W celu uzyskania wewntrznego tasowania zupenego (ang. inner perfect shuffle) na
pocztku kadego z powyszych sposobw naley doda nastpujce wyraenie, zamieniajce stronami powki sowa:
128
Uczta programistw
Istnieje take moliwo skonstruowania podobnej do metody tasowania powkowego metody odwrcenia tego przypadku tasowania (bdc szczeglnym przypadkiem
operacji kompresji, omwionej na stronie 137). Metoda ta wymaga od 26 do 29 instrukcji podstawowego zestawu RISC, w zalenoci od tego, czy wymagane jest wstpne wyczyszczenie bitw na nieparzystych pozycjach. Poniszy kod wymaga jednak
od 18 do 21 instrukcji z podstawowego zestawu RISC, natomiast w przypadku maszyny
obsugujcej rwnolege wykonanie niezalenych instrukcji kod ten moe zosta wykonany w 12 do 15 cyklach procesora.
@@4A3#1&B
129
w bajty. Wiersze i kolumny tej macierzy rozpoczynaj si na granicy bajtu. Taka pozornie prosta operacja, jak jest transpozycja tego typu macierzy jest bardzo kosztowna
pod wzgldem liczby wykorzystywanych instrukcji.
Na wikszoci maszyn adowanie i przechowywanie pojedynczych bitw byoby bardzo powolne, gwnie z powodu kodu, wymaganego w celu wyodrbnienia i (co gorsza)
przechowywania pojedynczych bitw. Lepszy sposb polega na podzieleniu macierzy
na podmacierze o rozmiarach 88 bitw. Kad z takich macierzy 88 bitw adujemy
do rejestrw, wyliczamy transpozycj podmacierzy a nastpnie macierz wynikow 88
zapisujemy w odpowiednim miejscu macierzy wynikowej.
W niniejszym podrozdziale w pierwszej kolejnoci zajmiemy si problemem wyznaczania transpozycji macierzy 88 bitw.
Sposb przechowywania tablicy, to znaczy kolejno wiersze-kolumny (ang. row-major)
lub kolumny-wiersze (ang. column-major) nie ma znaczenia. Wyznaczenie macierzy
transponowanej w kadym z tych przypadkw wymaga takich samych operacji. Dla
celw dalszych rozwaa przyjmijmy stosowanie kolejnoci wiersze-kolumny, w przypadku ktrej podmacierz 88 jest adowana do omiu rejestrw za pomoc omiu instrukcji adowania wartoci z pamici. Oznacza to, e adresy kolejnych instrukcji adowania
bajtw rni si o wielokrotno szerokoci oryginalnej macierzy liczonej w bajtach. Po
wykonaniu transpozycji podmacierz 88 zostaje umieszczona w kolumnie macierzy
docelowej. Podmacierz ta jest zapisywana za pomoc czterech instrukcji zapisu bajtu
w pamici, z adresami poszczeglnych bajtw rnicymi si od siebie o wielokrotno
szerokoci w bajtach tabeli docelowej (ktra bdzie rna od szerokoci w bajtach tabeli
rdowej, jeli ta nie bya kwadratowa). Zamy zatem, e mamy osiem 8-bitowych
wartoci, wyrwnanych do prawej w rejestrach
,
,
. Chcemy wyliczy osiem
8-bitowych wartoci, wyrwnanych do prawej w rejestrach , , , ktre bd
wykorzystane w instrukcjach zapisu bajtw w pamici. Sytuacje t ilustrujemy poniej, kady z bitw oznaczajc inn cyfr lub liter. Warto zwrci uwag na fakt, e
gwna przektna przebiega od bitu 7. bajtu 0 do bitu 0. bajtu 7. Czytelnicy przywykli do
notacji big-endian mogliby oczekiwa, e gwna przektna przebiega od bitu 0. bajtu 0
do bitu 7. bajtu 7.
!"#
$%&
'()*+
',- . ==> $/012
(/3456
%,3789
!)07:;<
-4:=>
"*18=?@
5;?A
#+29>AB
&.6<@B
130
Uczta programistw
Powyszy kod na wikszoci maszyn wymaga 174 instrukcji (62 koniunkcje, 56 przesuni oraz 56 alternatyw). Instrukcje alternatywy mona oczywicie zastpi instrukcjami dodawania. Na procesorach PowerPC kod ten moe zosta wykonany w 63 instrukcjach, co moe by do zaskakujce (siedem instrukcji przeniesienia wartoci i 56
instrukcji przesunicia cyklicznego w lewo z nastpujcym podstawieniem wartoci z zastosowaniem maski). Nie liczymy instrukcji adowania i zapisywania wartoci bajtw
ani kodu niezbdnego do wyliczenia ich adresw.
Nie jest powszechnie znany aden algorytm, ktry rozwizywa by ten problem i ktry
mona by uzna za doskonay. Mimo to kolejna z omawianych technik jest dwukrotnie
lepsza od powyszej, w kadym razie w przypadku procesorw obsugujcych instrukcje podstawowego zestawu RISC.
W pierwszej kolejnoci naley potraktowa macierz 88 jako 16 macierzy 22 i wykona transpozycje kadej z tych macierzy 22. Nastpnie ca macierz 88 traktujemy
jak cztery macierze 22, z ktrych kada zawiera macierze 22 z poprzedniego kroku
i ponownie wykonujemy transpozycj. Na kocu ca macierz traktujemy jako macierz 22 skadajc si z macierzy z poprzedniego kroku i wykonujemy transpozycj
tej macierzy. Odpowiednie przeksztacenia bd miay nastpujcy przebieg:
%,
-
!"#
$%&
'%,
'
'()*+
',- . ==>
(/3456
()375;
3789
%,3789
!)07:;<
!/04:6<
!:=>
-4:=>
"*18=?@
*+89?A
()*+5;?A
5;?A
#+29>AB
"#12=>@B
/0126<@B
&.6<@B
131
Jego zadaniem jest zamiana miejscami w sowie bitw 1. i 8. (liczc od prawej), 3. i 10.,
5. i 12. itd., nie naruszajc zawartoci bitw 0., 2., 4. itd. Zamiana bitw miejscami
jest realizowana za pomoc metody wykorzystujcej rnic symetryczn, opisanej na
stronie 56. Zawarto sowa przed i po pierwszej zamianie wyglda nastpujco:
-*$%&"'4#3/15J
$&
*%-"1J#/'543
132
Uczta programistw
instrukcje adowania, zapisu, adresowania oraz instrukcje przygotowujce oraz koczce procedur) oraz 101 instrukcji dla kodu z listingu 7.2 (instrukcje wstpne i koczce nie wystpoway, za wyjtkiem instrukcji powrotu z rozgazienia). Adaptacja kodu
z listingu 7.2 do 64-bitowej wersji standardowego zestawu RISC (w ktrej i ( byyby zapisane w tym samym rejestrze) wykona si w 85 instrukcjach.
Algorytm z listingu 7.2 wykonuje przetwarzanie od najwikszego do najmniejszego rozdrobnienia (biorc pod uwag wielko grup bitw zamienianych miejscami). Metod
t mona rwnie zmodyfikowa w taki sposb, aby wykonywaa przetwarzanie od najmniejszego do najwikszego rozdrobnienia. W tym celu traktujemy macierz 88 bitw
jako macierz 22, skadajc si z macierzy 44 bity i wykonujemy transpozycj tej
macierzy. Nastpnie kad z macierzy 44 traktujemy jako macierze 22 zoone z macierzy 22 bity i wykonujemy transpozycje tych macierzy itd. Kod wynikowy takiego
algorytmu bdzie taki sam, jak na listingu 7.2 za wyjtkiem trzech grup wyrae modyfikujcych kolejno bitw, ktre wystpi w odwrconej kolejnoci.
A B
A C
C D B D
A oznacza lew powk pierwszych 16 sw macierzy, B oznacza praw powk pierwszych 16 sw macierzy itd. Powysza transformacja moe zosta zrealizowana za pomoc nastpujcych zamian:
Prawa powka sowa 0 z lew powk sowa 16,
Prawa powka sowa 1 z lew powk sowa 17,
133
A
E
B C D A
F G H B
J K L I
N O P J
E C G
F D H
M K O
N L P
134
Uczta programistw
do najwikszego rozdrobnienia macierzy. Wewntrzna ptla jest kontrolowana wartoci zmiennej %, ktra przyjmuje kolejno wartoci wymienione wyej. Wewntrzna ptla powoduje wymian bitw
G%H okrelonych mask z bitami
G%I$H przesunitymi
w prawo o $ i rwnie okrelonymi mask , co odpowiada bitom
G%I$H okrelonym dopenieniem maski . Kod wykonujcy wspomniane zamiany bitw jest adaptacj
techniki wykorzystujcej trzy rnice symetryczne przedstawionej w podrozdziale Wymiana wartoci midzy rejestrami na stronie 56 w kolumnie (c).
Listing 7.3. Transpozycja macierzy o wymiarach 3232 bity
1 $51DE
4(#
/(
/
"14
4K44
(//0/ 4
"1## ##L4L
M4
D#E0D#L4E
4/
D#ED#E0
D#L4ED#L4E0 4
!
!
!
Po skompilowaniu tej funkcji za pomoc kompilatora GNU C na maszynie o waciwociach zblionych do podstawowego zestawu instrukcji RISC kod ten zawiera 31
instrukcji, 20 w wewntrznej ptli i 7 w zewntrznej. Funkcja ta wykonuje si zatem
w 4 + 5(7 + 16 20) = 1639 instrukcjach. Dla porwnania: gdyby funkcje t wywoano z wykorzystaniem 16 wywoa programu z listingu 7.2, wykonujcego transpozycj macierzy 88, zajoby to 16(101 + 5) = 1696 instrukcji, z zaoeniem, e te 16 wywoa zostaoby wykonanych jedno po drugim.
Obliczenia te obejmuj rwnie pi instrukcji niezbdnych do wykonania wywoania
funkcji (wasno zaobserwowana w skompilowanym kodzie). Std wynika, e obydwie
opisane funkcje s bardzo zblione pod wzgldem czasu wykonania.
Z drugiej strony dla maszyn 64-bitowych kod z listingu 7.3 mona z atwoci zmodyfikowa w taki sposb, e wykonuje transpozycj macierzy 6464 bity w okoo 4 + 6
(7 + 32 20) = 3886 instrukcjach. Realizacja tego celu za pomoc 64 wywoa transpozycji macierzy 88 wymagaoby okoo 64(85 + 5) = 5760 instrukcji.
Algorytm ten wykonuje si w miejscu (na oryginalnej macierzy), dlatego w przypadku transpozycji wikszych macierzy wymaga si dodatkowego kopiowania podmacierzy 3232-bitowych. Algorytm ten mona zmusi do dokonywania zapisu w osobnym obszarze pamici. W tym celu naley wyodrbni pierwszy lub ostatni krok ptli
$i wynik w tym kroku zapisa w osobnym obszarze pamici1.
1
Jeli zrobimy to w pierwszym kroku, unikniemy nadpisania oryginalnej zawartoci macierzy rdowej
przyp. tum.
135
Okoo poow instrukcji definiujcych funkcj na listingu 7.3 stanowi instrukcje kontrolne ptli oraz funkcje odczytujce i zapisujce piciokrotnie ca macierz. Czy rozsdne byoby zmniejszenie tego nakadu za pomoc rozwinicia ptli? Byoby w przypadku, gdyby programicie zaleao na jak najwikszej prdkoci wykonania i gdyby
zwikszona objto kodu nie stanowia problemu. Wanym te jest, aby mechanizm
pobierania instrukcji (ang. I-fetching) w procesorze poradzi sobie z pynnym wykonywaniem tak dugiego bloku nierozgazionego kodu. Przede wszystkim jednak mechanizm ten byby warty rozwaenia, jeli rozgazienia i procedury adowania i zapisu
danych z i do pamici byyby kosztownymi operacjami pod wzgldem czasu wykonywania. Wikszo programu bdzie stanowio sze wierszy wykonujcych zamian
bitw, powtrzone 16 razy (co w wyniku da 80 wierszy). Dodatkowo program bdzie
potrzebowa 32 instrukcji adowania danych, pobierajcych macierz rdow oraz 32 instrukcje zapisu danych, zapisujce macierz wynikow. Wszystko to da w wyniku 544 instrukcje.
Nasz kompilator GNU C nie rozwija ptli w tak duej liczbie przebiegw (15 w wewntrznej ptli, 5 w zewntrznej). Listing 7.4 przedstawia wersj funkcji, w ktrej rozwini dokonano rcznie. Program ten prezentujemy w wersji niepracujcej w miejscu, jednak w razie koniecznoci bdzie on poprawnie dziaa w takiej wersji. W tym
celu funkcj naley wywoa z obydwoma identycznymi argumentami. W programie
wystpuje 80 wierszy wywoujcych makro ,
. Nasz kompilator GNU C kompiluje
ten kod na maszyn obsugujc podstawowy zestaw instrukcji RISC z wykorzystaniem 576 instrukcji (bez rozgazie, za wyjtkiem powrotu z funkcji), wliczajc w to
czynnoci przygotowawcze i koczce procedur. Wykorzystana maszyna nie obsuguje
instrukcji adowania ani zapisu wielu wartoci (ang. load multiple oraz store multiple),
lecz potrafi zapisa i odczyta warto dwch rejestrw na raz, z wykorzystaniem instrukcji store double oraz load double (zapis oraz odczyt podwjnej wartoci).
Listing 7.4. Transpozycja macierzy o rozmiarze 32x32 bitw w postaci rozwinitej
N"2$5$($
(4(/ $0$
4/O
$$0 O
$
$
0 4
1 $51DE(,DE
/(
$($
($($($($($($-(
$($*($
($
($
($
($
($
(
$
($
-($
($
*($($
($($(
$($($($-($($*($($
$DE$
D
E$DE$DE
$DE$DE$DE$-D-E
...
$DE$*D*E$DE$
D
E
/
2$5$($
(
(/
2$5$
($
-(
(/
...
136
Uczta programistw
2$5$
($
(
(/
/
2$5$($((/
2$5$
($*((/
...
...
2$5$($*(
(/
2$5$($
(
(/
,DE$,D
E$
,DE$,DE$
,DE$,DE$,DE$,D-E$-
...
,DE$,D*E$*,DE$,D
E$
!
==>
$
$
$%
%$
%
%
%
%
&
&
137
$%
%$
&$
$&
%
&
&
Metoda ta nie stanowi konkurencji dla pozostaych z powodu duej kosztownoci kroku 2.
Aby wykona ten krok w rozsdnej liczbie operacji, naleaoby wykona przesunicie
cykliczne o n/2 pozycji wszystkich kolumn, ktre wykonuj przesunicie o n/2 lub
wiksz liczb pozycji (s to kolumny od n/2 1 do n 2] a nastpnie wykona przesunicie cykliczne odpowiednich kolumn o n/4 pozycji w gr itd. Kroki 1. oraz 3. wymagaj tylko n 1 instrukcji, natomiast krok 4. nie wymaga adnych instrukcji, jeli
wyniki s od razu zapisywane do odpowiednich obszarw w pamici.
W przypadku macierzy 88 zapisanej w pojedynczym sowie 64-bitowym w oczywisty
sposb (to znaczy grny wiersz macierzy jest zapisany w najbardziej znaczcych omiu
bitach rejestru) operacja transpozycji jest rwnowana trzem operacjom zewntrznego
tasowania zupenego i odtasowania [GLS1]. Jest to doskonay sposb realizacji tego zadania, o ile maszyna udostpnia instrukcj tasowania, lecz w przypadku maszyny ze
standardowym zestawem instrukcji RISC nie jest to dobre rozwizanie.
7.4. Kompresja
lub uoglniona ekstrakcja
Jzyk programowania APL posiada operacj kompresji (ang. compress) zapisywan B/V,
gdzie B jest wektorem bitw, natomiast V jest wektorem o tej samej dugoci co B,
zawierajcym dowolne elementy. Wynikiem operacji jest wektor skadajcy si z elementw V, dla ktrych odpowiadajce im bity wektora B maj warto 1. Dugo wektora wynikowego jest rwna liczbie jedynek w B.
W niniejszym podrozdziale zajmiemy si podobn operacj na bitach w sowie. Po podaniu maski m i sowa x, bity w x, dla ktrych odpowiednie bity w masce m maj warto 1 zostaj skopiowane do wyniku i przesunite (skompresowane) do prawej. Zamy na przykad, e operujemy na sowie x o nastpujcej strukturze:
$%&"'4#3/15J FB,+)
138
Uczta programistw
Mona usprawni ten kod za pomoc metody prefiksu rwnolegego (zob. rozdzia 5.,
strona 85) z wykorzystaniem operacji rnicy symetrycznej [GLS1]. Operacj prefiksu
rwnolegego z wykorzystaniem rnicy symetrycznej oznaczmy PP-XOR. Gwny
pomys polega tu na wyodrbnieniu bitw argumentu x, ktre naley przesun w prawo o nieparzyst liczb pozycji i na wykonaniu tego przesunicia. Operacj t mona
uproci przez koniunkcj x z mask w celu usunicia niepotrzebnych bitw. Bity maski przesuwamy w ten sam sposb. Nastpnie identyfikujemy te bity w x, ktre naley
przesun o liczb miejsc bdc nieparzyst wielokrotnoci dwjki (2, 6, 10 itd.)
i przesuwamy te bity w x oraz w masce. Nastpnie identyfikujemy i przesuwamy bity,
ktre naley przesun o nieparzyst wielokrotno liczby 4, nastpnie powtarzamy t
operacj dla nieparzystej wielokrotnoci 8 a nastpnie dla bitw, ktre naley przesun o 16 pozycji.
Algorytm ten (ktrego pierwsz publikacj przypisuje si [GLS1]) wydaje si by do
trudny do zrozumienia i taki sposb zrealizowania czegokolwiek nie wydaje si by
w ogle moliwy, zatem operacje wykorzystywane przez ten algorytm omwimy z nieco wiksz szczegowoci. Zamy, e naszymi wartociami wejciowymi s:
139
Kada litera w symbolizuje jeden bit (o wartoci 0 lub 1). Liczba poniej kadej jedynki w masce oznacza liczb miejsc, o ktre naley przesun w prawo dany bit sowa .
Jest to liczba zer w masce na prawo od tego miejsca. Jak wspomniano wczeniej, wygodnie jest oczyci z niepotrzebnych bitw, co da w wyniku:
$4#2B,+
Plan polega na okreleniu bitw, ktre przesuwaj si o nieparzyst liczb miejsc w prawo i przesun je o jedn pozycj. Przypomnijmy, e operacja PP-XOR w wyniku daje 1
na kadej pozycji, na ktrej liczba jedynek od tego miejsca (wcznie) w prawo jest nieparzysta. My chcemy natomiast zidentyfikowa miejsca, od ktrych w prawo liczba zer
jest nieparzysta. Moemy to wyliczy za pomoc zmiennej pomocniczej %JEE,
wyliczajc na niej PP-XOR.
Otrzymamy:
/#
/5
$4#2,+
140
Uczta programistw
W nastpnej kolejnoci musimy przygotowa mask dla drugiej iteracji, gdzie nastpi wykrywanie bitw, ktre naley przesun w prawo o nieparzyst wielokrotno dwjki.
Zauwamy, e warto %KJ identyfikuje bity, ktre maj warto 0 bezporednio
z prawej strony w oryginalnej masce oraz ktre posiadaj parzyst liczb zer po prawej stronie w oryginalnej masce. Wasnoci te cz si, tworzc wasnoci zmienionej
maski (oznacza to, e % identyfikuje wszystkie miejsca w nowej masce , ktre ssiaduj z prawej strony z zerem oraz posiadaj parzyst liczb zer ze swojej prawej strony). Warto ta, po podsumowaniu przez PP-XOR, zidentyfikuje bity, ktre naley
przesun w prawo o nieparzyst wielokrotno dwjki (2, 6, 10 itd.) Procedura nasza
bdzie polegaa na przypisaniu tej wasnoci do % i wykonaniu drugiej iteracji wymienionych krokw. Nowa warto % wynosi:
/#
Kompletna funkcja w C operacji kompresji zostaa przedstawiona na listingu 7.6. Wykonuje si w staej liczbie 127 instrukcji podstawowego zestawu RISC, wliczajc czynnoci przygotowawcze oraz koczce funkcj. Listing 7.7 przedstawia sekwencj wartoci przyjmowanych przez rne zmienne w kluczowych punktach wylicze, z tymi
samymi wartociami, ktre zostay uyte w powyszej dyskusji. Zauwamy, e produktem ubocznym tej procedury jest skompresowana wersja oryginalnej maski .
Listing 7.6. Procedura compress z wykorzystaniem prefiksu rwnolegego
&1/5(/
/#(/5(/(
/@@&BFA&/F51 B%% F
/#M/
@@%HB/F3&BFPB$515$24 1
"1 LL
/5/#0/#
@@5"#Q213GF
/5/50/5
/5/50/5
/5/50/5
/5/50/5
//5/@@% F15BH&$
//0//
@@#1/54/F/
/
0
@@#1/54/F
/#/#M/5
!
!
$4#2B,+
(
512F3&B??
/#
/5
/
$4#2,+
(
512F3&B??
/#
/5
/
/
$4#2B,+
(
512F3&B??
/#
/5
/
/
$4#2B,+
(
512F3&B??
/#
/5
/
/
$4#2B,+
(
512F3&B??
/#
/5
/
/
$4#2B,+
141
142
Uczta programistw
Dziki temu w ptli mamy tylko 21 instrukcji (adowanie staych mona zrealizowa
poza ptl), co stanowi spore usprawnienie w porwnaniu do 127 instrukcji wykorzystanych w penej wersji z listingu 7.6.
W drugim opisanym przypadku, w ktrym warto jest znana z gry, mona zrobi podobn modyfikacj, lecz moliwe s dalsze usprawnienia. By moe jedna z piciu
masek ma warto 0, w tym przypadku mona pomin jeden z powyszych wierszy
przypisa. Na przykad zamy, e maska . jest rwna 0, co oznacza, e w nie ma
adnych pozycji, ktre naley przesun o nieparzyst liczb miejsc, natomiast . bdzie rwne 0 w przypadku, gdy aden bit nie musi by przesunity o wicej ni 15 pozycji w prawo itd.
Za przykad przyjmijmy nastpujc mask:
/
/
/
/
143
instrukcjach, lecz w przypadku zastosowania wstawiania potrzebne jest tylko 11 instrukcji (w masce wystpuje pi pl jedynek). Bardziej ekstremalnym przypadkiem jest
na przykad . W tym przypadku naley przesun tylko jeden bit o 31 pozycji, co w przypadku metody wykorzystujcej prefiks rwnolegy wymaga 21 instrukcji, natomiast metoda wykorzystujca wstawianie wykorzysta tylko jedn instrukcj
(przesunicie w prawo o 31).
W operacji kompresji ze znan mask mona rwnie wykorzysta instrukcj ekstrakcji
(ang. extract), dziki czemu algorytm bdzie wymaga 3n 2 instrukcji, gdzie n jest
liczb pl jedynek w masce.
Z naszych rozwaa wynika jednoznaczny wniosek, e wybr optymalnego kodu realizujcego operacj kompresji ze znan mask nie jest atwym zadaniem.
144
Uczta programistw
...
Traktujc te wektory jako macierz bitow naley wykona transpozycj macierzy a nastpnie odbi j wedug przektnej w taki sposb, e grny wiersz bdzie zawiera najmniej znaczce bity wektorw a wynik bdzie w schemacie little-endian. W ten sposb
powysze wektory moemy przechowa w postaci nastpujcej macierzy bitowej:
5DE
5D
E
5DE
5DE
5DE
Kady bit sowa GH zawiera najmniej znaczcy bit numeru pozycji, na ktr przesuwa
si odpowiedni bit sowa . Kady bit sowa GH zawiera kolejny bit numeru pozycji
itd. Jest to sytuacja podobna do zapisu maski w ., wykorzystywanego w poprzednim
podrozdziale, z t rnic, e . odnosio si do nowej maski w algorytmie kompresji,
nie do oryginalnej maski.
Operacja kompresji, ktra jest nam teraz potrzebna, musi skompresowa do lewej wszystkie bity oznaczone w masce wartoci 1, natomiast do prawej skompresowa wszystkie
bity oznaczone w masce wartoci 02. Sposb ten nazywany jest czasem operacj rozdzielania owiec i kozw3 (ang. sheep and goats SAG) lub uoglnionym odtasowaniem (ang. generalized unshuffle). Wynik takiej operacji mona wyznaczy za pomoc
nastpujcego wyraenia:
R6(/&1/5S3" (/&1/5(M/
Wykorzystujc SAG jako operacje podstawow oraz permutacj opisan wyej, wynik przeksztacenia sowa mona wyznaczy w nastpujcych 15 krokach:
R6(5DE
5D
ER65D
E(5DE
5DER65DE(5DE
5DER65DE(5DE
5DER65DE(5DE
R6(5D
E
5DER65DE(5D
E
2
W przypadku, gdy wykorzystywany jest format big-endian do lewej naley skompresowa bity oznaczone
w masce wartoci 0, natomiast do prawej bity oznaczone wartoci 1.
Nazwa pochodzi z jednej z przypowieci w ewangelii wedug w. Mateusza (Mat 25, 3233): I zgromadz
si przed Nim wszystkie narody, a On oddzieli jednych [ludzi] od drugich, jak pasterz oddziela owce
od kozw. Owce postawi po prawej, a kozy po swojej lewej stronie. Z atwoci mona dostrzec
analogi rozdzielanie bitw na praw i lew stron rejestru wynikowego przyp. red.
145
5DER65DE(5D
E
5DER65DE(5D
E
R6(5DE
5DER65DE(5DE
5DER65DE(5DE
R6(5DE
5DER65DE(5DE
R6(5DE
W tych krokach operacja SAG jest wykorzystywana w celu wykonania stabilnego sortowania o podstawie 2 (ang. stable binary radix sort). W pierwszym kroku wszystkie
bity w , dla ktrych GH, zostaj przesunite do lewej powki wynikowego sowa, natomiast wszystkie bity, dla ktrych GH , zostaj przeniesione do prawej
powki. Oprcz tych przesuni kolejno bitw nie ulega zmianie (std wanie to
sortowanie nosi miano stabilnego). W kolejnych wierszach w podobny sposb sortowane s klucze wykorzystywane w nastpnym etapie sortowania. Szsty wiersz kodu
wykonuje sortowanie na podstawie drugiego mniej znaczcego bitu klucza itd.
Podobnie do omawianej wczeniej kompresji, w sytuacji, gdy permutacja jest wykorzystana na wikszej liczbie sw moemy uzyska znaczny przyrost wydajnoci, jeli
wstpnie wyliczymy parametry niezbdne do poszczeglnych etapw sortowania. Macierz permutacji mona rozpisa w nastpujcy sposb:
5D
ER65D
E(5DE
5DER6R65DE(5DE(5D
E
5DER6R6R65DE(5DE(5D
E(5DE
5DER6R6R6R65DE(5DE(5D
E(5DE(5DE
Bardziej bezporedni (i zapewne mniej ciekawy) sposb reprezentacji uoglnionych permutacji bitw w sowie polega na zapisie permutacji w postaci sekwencji 32 5-bitowych
indeksw.
Indeks o numerze k stanowi numer bitu w rdle, z ktrego pochodzi k-ty bit wyniku (jest
to lista typu pochodzi z, w odrnieniu od metody SAG, w ktrej lista okrela sytuacj przechodzi do). Informacje te mona upakowa w szeciu sowach 32-bitowych, co
wymaga zastosowania szeciu sw do przechowania 32-bitowych indeksw. Instrukcj t mona zaimplementowa sprztowo, na przykad w postaci:
% $ 'T (T(T(
146
Uczta programistw
Rejestr =- jest rejestrem wynikowym oraz rdowym, rejestr = zawiera bity, ktre
chcemy podda permutacji, rejestr = zawiera natomiast sze 5-bitowych indeksw
(z dwoma nieuywanymi bitami). Instrukcja ta wykonuje nastpujc operacj:
t (t << 6) | x i0 x i1 x i2 x i3 x i4 x i5
Zawarto rejestru wynikowego t zostaje przesunita w lewo o sze pozycji a w miejsce powstae w efekcie tego przesunicia zostaj wstawione wybrane bity sowa x.
Pobrane bity s okrelone szecioma 5-bitowymi indeksami sowa i w kolejnoci od
lewej do prawej. Kolejno bitw w indeksach moe by interpretowana w formacie
little-endian lub big-endian a wybr najprawdopodobniej byby dostosowany do specyfiki konkretnego procesora.
W celu dokonania permutacji sowa naley zastosowa sekwencj szeciu takich instrukcji, wszystkie z tymi samymi wartociami =- oraz = lecz z rnymi rejestrami indeksw. W pierwszym rejestrze indeksowym w sekwencji znaczenie miayby tylko indeksy i4
oraz i5, poniewa bity wybrane przez pozostae cztery indeksy zostan i tak przesunite
poza wynik =-.
Implementacja tej metody z ca pewnoci pozwala na powtrzenie wartoci indeksw,
zatem instrukcja ta moe zosta uyta rwnie w innym celu ni permutacja bitw. Mona j zastosowa w celu powtrzenia dowolnego bitu dowoln liczb razy w rejestrze wynikowym. Operacja SAG nie posiada wasnoci pozwalajcej na takie uoglnienie.
Implementacja tej instrukcji w postaci szybkiej instrukcji (tzn. wykonujcej si w pojedynczym cyklu procesora) nie jest zadaniem niewykonalnym. Ukad wyboru bitw
skada si tutaj z szeciu multiplekserw MUX 32:1. W przypadku, gdyby zbudowa je
z piciu segmentw multiplekserw MUX 2:1 we wspczesnej technologii (6 31 = 186
MUX w sumie), instrukcja ta byaby szybsza od 32-bitowej instrukcji dodawania [MD].
Operacja permutacji bitw ma zastosowanie w kryptografii, natomiast bardzo zbliona
operacja permutacji fragmentw sw (na przykad permutacja bajtw w sowie) ma
zastosowanie w grafice komputerowej. Obydwa te zastosowania bd operowa na wartociach 64-bitowych lub wrcz na 128-bitowych, natomiast na wartociach 32-bitowych
zdecydowanie rzadziej. Operacje SAG oraz bitgather daj si oczywicie zmodyfikowa w prosty sposb rwnie dla sw o wspomnianych wielkociach.
W celu wykonania szyfrowania lub odszyfrowania komunikatu za pomoc standardu DES
(Data Encryption Standard) naley wykona szereg przeksztace podobnych do permutacji. W pierwszej kolejnoci jest wykonywane generowanie klucza i zachodzi to jednorazowo podczas sesji. Operacja ta wymaga zastosowania 17 odwzorowa przypominajcych permutacje. Pierwsze z nich, nazywane permuted choice 1 dokonuje odwzorowania
64-bitowej wartoci na warto 56-bitow (wybiera 56 bitw pomijajc bit parzystoci
i wykonuje na nich permutacj). Nastpnie wykonywane jest 16 odwzorowa permutacyjnych z 56 bitw na 48 bitw, z ktrych wszystkie wykorzystuj to samo odwzorowanie, zwane permuted choice 2.
147
Po etapie generowania klucza kady 64-bitowy blok bitw w komunikacie zostaje poddany 34 operacjom permutacyjnym. Pierwsz i ostatni operacj stanowi permutacje
64-bitowej wartoci, z ktrych jedna stanowi odwrotno drugiej. Wykonuje si 16 permutacji z powtrzeniami, ktre odwzorowuj wartoci 32-bitowe na wartoci 48-bitowe,
wykorzystujc to samo odwzorowanie. Na kocu wykonywane jest 16 32-bitowych
permutacji, wykorzystujcych t sam permutacj. W caej operacji wykorzystywane jest
wiele powtrze szeciu rnych odwzorowa. S one stae i zostay opisane w [DES].
Algorytm DES jest przestarzay i w roku 1998 organizacja Electronic Frontier Foundation udowodnia, e z zastosowaniem specjalnego sprztu jest moliwe zamanie algorytmu DES. W ramach tymczasowego rozwizania National institute of Standards and
Technology (NIST) opracowa rozwizanie pod nazw Triple DES, ktre polega na
trzykrotnym wykonaniu algorytmu DES na kadym z 64-bitowych blokw, za kadym
razem wykorzystujc inny klucz (co oznacza, e klucz skada si z 192 bitw, wliczajc
24 bity parzystoci). Z tego powodu algorytm ten wymaga wykonania trzykrotnie wikszej liczby permutacji ni ma to miejsce w standardowym algorytmie DES zarwno
w operacjach szyfrowania, jak i deszyfrowania.
Prawdziwy nastpca algorytmw DES oraz Triple DES, algorytm AES (ang. Advanced Encription Standard, znany wczeniej pod nazw algorytmu Rijndael) w ogle nie
wykorzystuje permutacji na poziomie bitw. Jedyn operacj zblion do permutacji
jest przesunicie cykliczne 32-bitowych sw o wielokrotnoci liczby 8. Inne metody
kryptograficzne proponowane lub rzeczywicie wykorzystywane z reguy wykorzystuj
znacznie mniejsz liczb permutacji bitw ni ma to miejsce w algorytmie DES.
Porwnujc dwa sposoby implementacji permutacji, sposb wykorzystujcy instrukcj
bitgather ma nastpujce zalety:
prostszy proces przygotowania indeksw z danych opisujcych permutacj;
prostszy sposb implementacji sprztowej;
bardziej uoglnione odwzorowania.
doubleword);
bardziej wydajnie realizuje permutacj czci sw.
Punkt trzeci z powyszych rozwaa szerzej omwiono w pozycji [LSY]. Instrukcja SAG
pozwala na realizacj uoglnionej permutacji wartoci zoonych z dwch sw za pomoc dwch wywoa instrukcji SAG, kilku dodatkowych instrukcji z podstawowego
zestawu RISC oraz dwch penych permutacji pojedynczych sw. Instrukcja bitgather
148
Uczta programistw
A1 B2;
A2 B4;
A3 B6;
A4 B1;
A5 B3;
A6 B5;
A7 B7.
149
Indeks w macierzy,
numeracja big-endian
Numeracja little-endian
Odwrcenie kolejnoci
Dopenienie
Dopenienie
Odjcie k (mod n)
Dodanie k (mod n)
Dodanie k (mod n)
Odjcie k (mod n)
Odkodowanie FFT