Z pogranicza informatyki esejów i ćwiczeń kilka

Transkrypt

Z pogranicza informatyki esejów i ćwiczeń kilka
Z pogranicza informatyki esejów i ćwiczeń kilka
Piotr Fulmański1
30 listopada 2007
1
E-mail: [email protected]
2
Spis treści
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Spis treści
Spis treści
3
Przedmowa
5
1 Zbuduj sobie HDA
1.1 Układy cyfrowe . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Postawienie problemu i jego analiza . . . . . . . . . . . . . .
1.3 Identyfikacja sygnałów wejściowych i wyjściowych . . . . . .
1.4 Troszkę bardziej formalny opis działania układu sterującego
1.5 Podstawowe bramki . . . . . . . . . . . . . . . . . . . . . .
1.6 Tworzenie schematu układu . . . . . . . . . . . . . . . . . .
1.6.1 Etap I . . . . . . . . . . . . . . . . . . . . . . . . . .
1.6.2 Etap II . . . . . . . . . . . . . . . . . . . . . . . . .
1.7 Minimalizacja układu poprzez minimalizację wyrażenia logicznego . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.8 Mnemotechniczne sposoby minimalizacji wyrażeń logicznych
1.9 Kod Gray’a . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.10 Tablice Karnaugha . . . . . . . . . . . . . . . . . . . . . . .
2 Dwie bramki to już układ
2.1 Komparator jednobitowy . . . .
2.2 Sumator jednobitowy . . . . . . .
2.3 Dekoder adresowy . . . . . . . .
2.4 Przerzutniki . . . . . . . . . . . .
2.4.1 Przerzutniki typu R-S . .
2.4.2 Hazard . . . . . . . . . .
2.4.3 Synchroniczny przerzutnik
2.4.4 Przerzutnik typu D . . . .
2.4.5 Przerzutnik typu J-K . .
. . .
. . .
. . .
. . .
. . .
. . .
typu
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
R-S
. . .
. . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
8
8
9
12
14
14
15
.
.
.
.
15
15
21
22
.
.
.
.
.
.
.
.
.
27
27
28
30
32
32
33
35
36
36
4
Przedmowa
2.5
2.6
2.7
Rejestr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Pamięć . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Licznik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3 Dlaczego 2+2=5?
3.1 Dlaczego? . . . .
3.2 Doświadczenie 1
3.3 Doświadczenie 2
3.4 Wnioski . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
41
41
42
45
49
4 Obliczenia numeryczne
53
4.1 O strukturze pamięci . . . . . . . . . . . . . . . . . . . . . . . 53
4.2 O tym co, jak i w czym liczymy . . . . . . . . . . . . . . . . . 55
5 Architektury równoległe
5.1 Podział . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Klasyfikacja architektur równoległych według Flynna .
5.2.1 SISD . . . . . . . . . . . . . . . . . . . . . . . .
5.2.2 SIMD . . . . . . . . . . . . . . . . . . . . . . .
5.2.3 MIMD . . . . . . . . . . . . . . . . . . . . . . .
5.3 Klasyfikacja architektur równoległych według Duncana
5.3.1 Wektorowe . . . . . . . . . . . . . . . . . . . .
5.3.2 SIMD . . . . . . . . . . . . . . . . . . . . . . .
5.3.3 Systoliczne . . . . . . . . . . . . . . . . . . . .
5.3.4 MIMD z pamięcią rozproszoną . . . . . . . . .
5.3.5 MIMD z pamięcią wspólną . . . . . . . . . . .
5.3.6 MIMD/SIMD . . . . . . . . . . . . . . . . . . .
5.3.7 Przepływ danych . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
59
59
59
60
60
61
61
62
62
63
63
63
63
63
6 Errata
65
6.1 Poprawki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.2 Uzupełnienie literatury . . . . . . . . . . . . . . . . . . . . . . 67
Bibliografia
69
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Przedmowa
Pisanie jest jedyną sztuką, której
musimy się nauczyć pisząc.
Autor anonimowy
Trudno powiedzić czym jest niniejszy skrypt1 . Z pewnością nie jest to
podręcznik do Wstępu do informatyki, gdyż takowy został już przez autorów wydany. Nie jest to także skrypt do ćwiczeń, choć niektóre rozdziały
mogą to sugerować. Najprostszym określeniem będzie: zbiór różności. Tak
więc znajdziemy tutaj zarówno materiał ćwiczeniowy służący pogłębianiu
informacji zawartych we „Wstęp do informatyki. Podręcznik” jak i rozdziały mogące stanowić w przyszłości II tom wspomnianego podręcznika.
II tomu jednak nie będzie. Przyjęta w niniejszym skrypcie formuła daje
bowiem większą swobodę w doborze tematów. Ponieważ z założenia jest to
zbiór różności tak więc nie jest konieczne przestrzeganie ciągłości wywodów i
stopniowanie trudności materiłu. Zasadniczo każdy rozdział jest niezależny
od pozostałych i nie zakłada się, że wszystko zostanie tutaj wyjaśnione. Jak
sam tytuł mówi jest to bowiem zbiór kilku ćwiczeń i wykładów (czyli esejów,
bo wykład to nic innego jak opowiadanie na jakiś temat) w jakiś sposób,
mocniejszy lub luźniejszy, związanych z informatyką.
Piotr Fulmański, Ścibór Sobieski
1
W obecnej postaci nie jest to nawet skrypt. Jest to zbiór notatek jakie i tak dla siebie
sporządzamy przygotowywując zajęcia.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
6
SPIS TREŚCI
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Rozdział 1
Zbuduj sobie HDA
Wykład to przenoszenie wiadomości
z notatek wykładowcy do notatek ucznia
– z pominięciem mózgów ich obu.
Pokolenia uczniów
1.1
Układy cyfrowe
Układy cyfrowe, nazywane także układami logicznymi są strukturami
przetwarzającymi sygnały dwuwartościowe. Działanie tych układów opisane
jest za pomocą algebry sygnałów, która należy do rodziny algebr Boole’a.
Elementy zbioru wartości, którymi algebra ta operuje, zwykło się oznaczać
przez 0 i 1. Wartości te odpowiadają poziomom napięcia wytwarzanego
przez układy elektroniczne. W tak zwanej logice dodatniej napięciu wysokiemu odpowiada wartość sygnału 1, natomiast niskiemu – wartość 0; w
logice ujemnej mamy do czynienia z sytucją odwrotną.
W tym rozdziale skupimy się na jednym z rodzajów układów logicznych
jakim są układy kombinacyjne. Długo zastanawialiśmy się jak podejść do
tego tematu aby łagodnie wprowadzić czytelnika w niezwykły świat układów cyfrowych. Wybawieniem okazała się książka Cezarego Zielińskiego [5]
właśnie z uwagi na czytelne i zrozumiałe prowadzenie wywodów. Z niej
zaczerpnęliśmy pomysł na prosty automat.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
8
Zbuduj sobie HDA
produkt
bułka
bułka + parówka
bułka + parówka + musztarda
cena
2
3
5
Tablica 1.1. Funkcjonalność HDA
Rys. 1.1. HDA - projekt wstępny
1.2
Postawienie problemu i jego analiza
Zadaniem naszym jest skonstruowanie automat do wydawania hotdogów nazywanego w skrócie HDA (hot-dog automat). Przyjmijmy, że automat może wydać następujące rodzaje produktów: bułkę, bułkę z parówką,
bułkę z parówką i musztardą. Koszt związany z nabyciem odpowiedniego
produktu, to odpowiednio 2, 3 i 5 zł. Zakładamy, że automat akceptuje
monety o nominałach 1, 2 i 5 zł i nie wydaje reszty. Ponadto zakładamy, że
akceptowana jest tylko najmniejsza liczba monet z dopuszczalnego zbioru
(a więc np. nie można wrzucić 2 razy po 2 zł i 1 raz 1 zł). Na rysunku 1.1
przedstawiono schemat projektowanego automatu.
1.3
Identyfikacja sygnałów wejściowych i wyjściowych
Jeśli chcemy zaprojektować układ elektroniczny sterujący HDA, to musimy określić co będzie stanowiło sygnał wejściowy i jakie sygnały powinien
automat generować. Potem zastanowimy się nad ich wzajamną relacją, tj.
jakie sygnały wejściowe powodują powstanie jakich sygnałów wyjściowych.
Sygnały wejściowe – sygnały powstające w otoczeniu układu; układ nie
ma bezpośredniego wpływu na ich pojawienie się.
Sygnały wyjściowe – sygnały wytwarzane przez układ i kierowane do
jego otoczenia.
Zbiór sygnałów wejściowych zestawiono w tabeli 1.2 natomiast wyjściowych
w tabeli 1.3. Po ich uwzględnieniu projekt przyjmie postać jak na rysunku
1.2.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.4 Troszkę bardziej formalny opis działania układu sterującego
Przyczyna pojawienia
się sygnału wejściowego
Wrzucenie monety o niminale 1
Wrzucenie monety o niminale 2
Wrzucenie monety o niminale 5
Naciśnięcie przycisku START
9
Wejście
x1
x2
x5
xS
Tablica 1.2. Sygnały wejściowe
Działanie podjęte przez
automat
Wydanie bułki
Wydanie parówki
Wydanie musztardy
Zwrot monet
Wyjście
yB
yP
yM
yZ
Tablica 1.3. Sygnały wyjściowe
1.4
Troszkę bardziej formalny opis działania układu
sterującego
Tak więc zadaniem projektowanego układu sterującego jest wytworzenie
sygnałów wyjściowych yB , yP , yM oraz yZ na podstawie sygnałów wejściowych x1 , x2 , x5 , xS . Ujmując to bardziej precyzyjnie dążymy do skonstruowania takiej funkcji f (·), która pozwoli na odwzorowanie zależności pomiędzy sygnałami wejściowymi i wyjściowymi. Tak więc należy wyznaczyć 4
funkcje:
yB = fB (x1 , x2 , x5 , xS ),
yP
= fP (x1 , x2 , x5 , xS ),
yM
= fM (x1 , x2 , x5 , xS ),
yS = fS (x1 , x2 , x5 , xS ).
Przyjmując za x wektor [x1 , x2 , x5 , xS ] natomiast za y wektor y1 , y2 , y5 , yS
możemy to samo zapisać w następujący sposób
y = f (x),
f : A → A,
Rys. 1.2. HDA - kolejny projekt
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
(1.1)
10
Zbuduj sobie HDA
Wejście
tylko
wrzucono
monety
S
1+S
2+S
5+S
1+2+S
1+5+S
2+5+S
1+2+5+S
Działanie podjęte przez automat
Wyjście
NOP
—
NOP
ZWROT
otwórz pojemnik z bułką
otwórz pojemnik z bułką, parówka i
musztardą
otwórz pojemnik z bułką i parówka
ZWROT
ZWROT
ZWROT
—
yZ
yB
yB + yP + yM
yB + yP
yZ
yZ
yZ
Tablica 1.4. Sygnały wejściowe, działanie, sygnały wyjściowe
gdzie A = {0, 1} × {0, 1} × {0, 1} × {0, 1}.
Związek pomiędzy sygnałami z otoczenia automatu, działaniem jakie
wykona urządzenie oraz sygnałami wyjściowymi zestawiono w tabeli 1.4.
Wszystkie możliwe kombinacje sygnałów wejściowych i odpowiadające
im reakcje automatu w postaci wygenerowania odopowiednich sygnałów
wyjściowych zestawiono w tabeli 1.5.
Spróbujemy teraz to co przedstawiono w tabeli 1.5 zapisać przy pomocy
wyrażeń Boolowskich. Rozważania zacznijmy od kolumny yM jako, że tylko
w jednym przypadku yM przyjmuje wartość równą 1:
yM = 1
[x1 , x2 , x5 , xS ] = [0, 0, 1, 1].
jeżeli
Zapisując to troszkę bardziej „matematycznie” otrzymujemy:
yM = 1
jeżeli
x1 = 0 ∧ x2 = 0 ∧ x5 = 1 ∧ xS = 1,
a więc:
yM = 1
jeżeli
x̄1 ∧ x̄2 ∧ x5 ∧ xS ,
co pisząc skrótowo daje ostatecznie
yM = 1
jeżeli
x̄1 x̄2 x5 xS .
Postąpmy teraz podobnie z sygnałem yP .
yP = 1 jeżeli [x1 , x2 , x5 , xS ] = [0, 0, 1, 1]
lub [x1 , x2 , x5 , xS ] = [1, 1, 0, 1].
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.4 Troszkę bardziej formalny opis działania układu sterującego
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
x1
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
x2
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
x5
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
xS
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
yB
0
0
0
1
0
1
0
0
0
0
0
0
0
1
0
0
yP
0
0
0
1
0
0
0
0
0
0
0
0
0
1
0
0
yM
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
yZ
0
0
0
0
0
0
0
1
0
1
0
1
0
0
0
1
Tablica 1.5. Sygnały wyjściowe, działanie, sygnały wyjściowe
Zapisując to troszkę bardziej „matematycznie” otrzymujemy:
yP = 1 jeżeli
∨
x1 = 0 ∧ x2 = 0 ∧ x5 = 1 ∧ xS = 1
x1 = 1 ∧ x2 = 1 ∧ x5 = 0 ∧ xS = 1,
a więc:
yP = 1 jeżeli x̄1 ∧ x̄2 ∧ x5 ∧ xS
∨
x1 ∧ x2 ∧ x̄5 ∧ xS ,
co pisząc skrótowo daje ostatecznie
yP = 1 jeżeli x̄1 x̄2 x5 xS + x1 x2 x̄5 xS .
Sygnał yB .
yB = 1 jeżeli [x1 , x2 , x5 , xS ] = [0, 0, 1, 1]
lub [x1 , x2 , x5 , xS ] = [0, 1, 0, 1]
lub [x1 , x2 , x5 , xS ] = [1, 1, 0, 1].
Zapisując to troszkę bardziej „matematycznie” otrzymujemy:
yB = 1 jeżeli x1 = 0 ∧ x2 = 0 ∧ x5 = 1 ∧ xS = 1
∨
x1 = 0 ∧ x2 = 1 ∧ x5 = 0 ∧ xS = 1
∨
x1 = 1 ∧ x2 = 1 ∧ x5 = 0 ∧ xS = 1,
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
11
12
Zbuduj sobie HDA
a więc:
yB = 1 jeżeli x̄1 ∧ x̄2 ∧ x5 ∧ xS
∨
x̄1 ∧ x2 ∧ x̄5 ∧ xS
∨
x1 ∧ x2 ∧ x̄5 ∧ xS ,
co pisząc skrótowo daje ostatecznie
yB = 1 jeżeli x̄1 x̄2 x5 xS + x̄1 x2 x̄5 xS + x1 x2 x̄5 xS .
Sygnał yZ .
yZ = 1 jeżeli
lub
lub
lub
[x1 , x2 , x5 , xS ] = [0, 1, 1, 1]
[x1 , x2 , x5 , xS ] = [1, 0, 0, 1]
[x1 , x2 , x5 , xS ] = [1, 0, 1, 1]
[x1 , x2 , x5 , xS ] = [1, 1, 1, 1].
Zapisując to troszkę bardziej „matematycznie” otrzymujemy:
yZ = 1 jeżeli
∨
∨
∨
x1
x1
x1
x1
= 0 ∧ x2
= 1 ∧ x2
= 1 ∧ x2
= 1 ∧ x2
= 1 ∧ x5
= 0 ∧ x5
= 0 ∧ x5
= 1 ∧ x5
= 1 ∧ xS
= 0 ∧ xS
= 1 ∧ xS
= 1 ∧ xS
=1
=1
=1
= 1,
a więc:
yZ = 1 jeżeli
∨
∨
∨
x̄1 ∧ x2 ∧ x5 ∧ xS
x1 ∧ x̄2 ∧ x̄5 ∧ xS
x1 ∧ x̄2 ∧ x5 ∧ xS
x1 ∧ x2 ∧ x5 ∧ xS ,
co pisząc skrótowo daje ostatecznie
yZ = 1 jeżeli x̄1 x2 x5 xS + x1 x̄2 x̄5 xS + x1 x̄2 x5 xS + x1 x2 x5 xS .
1.5
Podstawowe bramki
Tutaj narysować bramki AND, OR, NOT; podać tablicę prawdy dla
nich; powiedzieć jakim operacjom boolowskim odpowiadają te bramki. Narysować bramki NAND i NOR. Wprowadzić pojęcie systemu funkcjonalnie
pełnego.
NAND
• NOT
y = N AN D(x, x) = N OT (AN D(x, x)) = N OT (x);
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.5 Podstawowe bramki
13
Rys. 1.3. Bramki AND, OR i NOT
Rys. 1.4. Bramki NAND i NOR
• OR
y = N AN D(x̄1 , x̄2 ) = N OT (AN D(x̄1 , x̄2 )) = N OT (x̄1 x̄2 )
¯1 + x̄
¯ 2 = x1 + x2 ;
= x̄
• AND
z = N AN D(x1 , x2 ) = N OT (AN D(x1 , x2 ))
y = N AN D(z) = N OT (AN D(z, z)) = N OT (z)
= N OT (N OT (AN D(x1 , x2 ))) = AN D(x1 , x2 )
NOR
• NOT
y = N OR(x, x) = N OT (OR(x, x)) = N OT (x);
• AND
y = N OR(x̄1 , x̄2 ) = N OT (OR(x̄1 , x̄2 )) = N OT (x̄1 + x̄2 )
¯1 x̄
¯ 2 = x1 x2 ;
= x̄
• OR
z = N OR(x1 , x2 ) = N OT (OR(x1 , x2 ))
y = N OR(z) = N OT (OR(z, z)) = N OT (z)
= N OT (N OT (OR(x1 , x2 ))) = OR(x1 , x2 )
Definicja 1.1 (System funkcjonalnie pełny). Systemem funkcjonalnie pełnym nazywamy zbiór operatorów, który jest w stanie wyrazić dowolne wyrażenie logiczne.
Z definicji wynika, że trójka operatorów AND, OR oraz NOT stanowi układ
funkcjonalnie pełny. Układ funkcjonalnie pełny stanowi także np. OR i
NOT. Co ciekawe istnieją także operatory, które w połączeniu same z sobą
pozwalają uzyskać równoważnik funkcji AND, OR i NOT a więc tworzą
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
14
Zbuduj sobie HDA
x1
0
0
1
1
x2
0
1
0
1
NAND(x1 ,x2 )
1
1
1
0
NOR(x1 ,x2 )
1
0
0
0
Tablica 1.6. Definicja funkcji NAND i NOR
układ funkcjonalnie pełny. Operatorami tymi jest operator NAND i NOR.
Dla ścisłości wywodu zauważmy, że istnieją tylko dwa operatory dwuargumentowe o takiej własnści (patrz informacje dla dociekliwych 1.1 na stronie
14). Definicje tych operatorów zawiera tabela 1.6.
Dla dociekliwych 1.1. Dwuargumentowym funktorem zdaniotwórczym (dalej będziemy pisać: funktorem) nazwiemy funkcję przyporządkowującą każdemu układowi < x1 , x2 >, gdzie x1 , x2 ∈ {0, 1}, 0 oznacza fałsz, 1 – prawdę,
wartość 0 lub 1.
Wszystkie funktory, jedno lub dwuargumentowe dają się zdefiniować za
pomocą alternatywy i negacji.
Istnieją funktory dwuargumentowe, które wystarczają do zdefiniowania
wszystkich funktorów jedno i dwuargumentowych. Jak udowodnił E.Żyliński
są tylko dwa takie funktory:
• o15 1 pochodzący od H.M.Scheffera nazywany dyzjunkcją (zdanie a o15
b czytamy: nie a lub nie b); wówczas negacja to: a o15 a a alternatywa
to (a o15 a) o15 (b o15 b);
• o5 pochodzący od J.Łukasiewicza nazywany jednoczesnym zaprzeczeniem; wówczas negacja to: a o5 a a alternatywa to (a o5 b) o5 (a o5
b).
1.6
1.6.1
Tworzenie schematu układu
Etap I
Rysujemy odpowiednie schematy cząstkowe odpowiadające funkcjom generującym sygnały wyjściowe (rys. 1.5).
1
Oznaczenie odnosi się do oznaczeń użytych w tabeli 1.7.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.7 Minimalizacja układu poprzez minimalizację wyrażenia logicznego15
0
0
1
1
0
1
0
1
0
0
1
1
0
1
0
1
o1
0
0
0
0
o9
0
1
1
0
o2
0
0
0
1
o10
1
0
1
0
o3
0
0
1
0
o11
1
1
0
0
o4
0
1
0
0
o12
0
1
1
1
o5
1
0
0
0
o13
1
0
1
1
o6
0
0
1
1
o14
1
1
0
1
o7
0
1
0
1
o15
1
1
1
0
o8
1
0
0
1
o16
1
1
1
1
Tablica 1.7. Funktory dwuargumentowe
Rys. 1.5. Pierwsza wersja schematu HDA
1.6.2
Etap II
Redukujemy powtarzające się elementy układu (rys. 1.6).
1.7
Minimalizacja układu poprzez minimalizację
wyrażenia logicznego
Niestety podobne zabiegi do tych właśnie przeprowadzonych nie dadzą
się zastosować do układu generującego sygnał yZ . W tym przypadku musimy zminimalizować wyrażenia algebraiczne opisujace ten sygnał.
yZ
= x̄1 x2 x5 xS + x1 x̄2 x̄5 xS + x1 x̄2 x5 xS + x1 x2 x5 xS
= x2 x5 xS (x1 + x̄1 ) + x1 x̄2 xS (x5 + x̄5 )
= xS (x2 x5 + x1 x̄2 ).
Jako wynik przeprowadzonej minimalizacji otrzymujemy układ przedstawiony na rysunku (rys. 1.7).
1.8
Mnemotechniczne sposoby minimalizacji wyrażeń logicznych
Przeprowadzone do tej pory operacje minimalizacji układów miały jedną
zasadniczą wadę – wymagały myślenia. Mówiąc inaczej, wymagały inter-
Rys. 1.6. Uproszczony schemat HDA
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
16
Zbuduj sobie HDA
Rys. 1.7. Uproszczony schemat HDA
wencji człowieka i jego aktywnego udziału w procesie. W tym przypadku
było to proste, ale chyb nikt nie ma wątpliwości, że w przypadku bardziej
złożonych układów, ludzie nie są w stanie zanalizować ich poprawinie i dokonać optymalnych zmian. Stąd też zajmiemy się teraz poszukiwaniem
pewnych sposobów zautomatyzowania procesu upraszczania wyrażeń boolowskich a tym samym upraszczania złożonych układów.
Definicja 1.2 (Jedynka funkcji). Jedynką funkcji nazywamy wektor zerojedynkowy, dla którego funkcja przyjmuje wartość 1.
Definicja 1.3 (Reguła sklejania). Jeżeli dwa iloczyny różnią się między
sobą tylko na jednym miejscu, w którym w jednym z iloczynów dany literał2 występuje w afirmacji3 a w drugim w negacji, to literał ten może być
usunięty, w wyniku czego powstaje pojedyńczy iloczyn nie zawierający tego
literału. Regułę można zapisać w postaci:
bB + b̄B = (b + b̄)B = B,
gdzie B jest iloczynem pozostałych literałów z wyjątkiem b (oraz b̄).
Tak więc minimalizację wyrażenia logicznego można osiągnąć przez analizowanie wektorów zerojedynkowych reprezentujących poszczególne jedynki
funkcji (patrz przykład 1.1).
Przykład 1.1.
analiza wektorów
zero-jedynkowych
algebraiczna analiza
wyrażenia
y=~x1*x2*x5*xS + x1*x2*x5*xS = (~x1+x1)*x2*x5*xS=
|
|
= 1*x2*x5*xS=
|
|
=
x2*x5*xS
0111
1111
|
|
|
| a więc
+-----+-------+
|
| a więc
|
|
|
2
Literał czyli symbol nazwy sygnału. Piszemy „literał”, gdyż mamy na myśli cały
symbol, który czasem może być wieloliterowy.
3
Ze słownika języka polskiego: afirmajcja – potwierdzenie czegoś, uznanie, aprobata.
W tym kontekście oznacza to sygnał niezanegowany.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.8 Mnemotechniczne sposoby minimalizacji wyrażeń logicznych
różnica na -> _111
jednym
miejscu
17
_111
Wypisując wszystkie jedynki funkcji i sumując je otrzymujemy wyrażenie będące sumą iloczynów. Każdy z czynników jest w tym przypadku iloczynem pełnym, czyli takim, który zawiera wszystkie literały. Taką postać
wyrażenia nazywamy Kanoniczną Alternatywna Postacią Normalną
(Kanoniczną Postacią Normalną Sumy). Po minimalizacji czynniki
nie będą już pełnymi iloczynami – taką postać nazywać będziemy wówczas
Alternatywną Postacią Normalną (Postacią Normalną Sumy). Dualną postacią do PNS jest Koniunkcyjna Postać Normalna i jest to jak
łatwo zgadnąć iloczyn sum odpowiednich wyrażeń.
Opierając się na regule sklejania w łatwy sposób możemy redukować wyrażenia. Kłopot polega jednak na zautomatyzowaniu tego procesu. Spróbujmy wykonać kilka doświadczeń związanych z minimalizowaniem wyrażeń.
1. Zminimalizujmy wartość wyrażenia w = ābc̄d + abc̄d. Mamy
w = ābc̄d + abc̄d = bc̄d(ā + a) = bc̄d.
Utwórzmy teraz pewną tabelę, nie wnikając w to dlaczego tak a nie
inaczej ona wygląda.
\cd|
\ |
ab\|00 01 11 10
---+----------00 |
01 |
11 |
10 |
Wypełniamy teraz tabelę symbolami 1 i 0 stosownie do badanego wyrażenia. I tak ponieważ w minimalizowanym wyrażeniu mamy abc̄d
więc stawiamy 1 na przecięciu wiersz oznaczonego jako 11 (odpowiednik ab) oraz kolumny 01 (odpowiednik c̄d). Podobnie postępujemy z
drugim czynnikiem. W pozostałe pola wpisujemy wartość 0, otrzymując ostatecznie
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
18
Zbuduj sobie HDA
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 0 0 0 0
01 | 0 1 0 0
11 | 0 1 0 0
10 | 0 0 0 0
Zauważmy, że „ jedynki” są „obok siebie” tworząc prostokąt a w wyrażeniu jakie jest wynikiem minimalizacji pozostały te element indeksu
kolumny i wiersza, które są wspólne dla obu „ jedynek”. Przejdźmy
do kolejnego przykładu.
2. Zminimalizujmy wartość wyrażenia w = ābc̄d + ābcd + abcd. Mamy
w = ābc̄d + ābcd + abcd = ābc̄d + ābcd + ābcd + abcd
= (c̄ + c)ābd + (ā + a)bcd = ābd + bcd.
Ponownie jak poprzednio wypełniamy tabelę symbolami 1 i 0 stosownie do badanego wyrażenia, otrzymując:
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 0 0 0 0
01 | 0 1 1 0
11 | 0 0 1 0
10 | 0 0 0 0
W tym przypadku „ jedynki” również są obok siebie, ale ich układ
jest troszkę inny. Jeśli jednak dopuścimy możliwość wielokrotnego
wykorzystania pewnej „ jedynki” wówczas możemy mówić o dwóch
nachodzących na siebie parach „ jedynek” tworzących dwa prostokąty:
\cd|
\ |
ab\|00 01 11 10
---+-----------
\cd|
\ |
ab\|00 01 11 10
---+-----------
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.8 Mnemotechniczne sposoby minimalizacji wyrażeń logicznych
00
01
11
10
|
|
|
|
0
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
00
01
11
10
|
|
|
|
0
0
0
0
0
1
0
0
0
1
0
0
19
0
0
0
0
Wielokrotne wykorzystanie „ jedynki” jest oczywiście uzasadnione teoretycznie jako, że w dowolnym wyrażeniu boolowskim możemy dowolny z czynników dopisać tyle razy ile chcemy, w myśl jednego z
praw: x = x + x. Ponieważ mieliśmy tutaj dwie grupy po dwie „ jedynki” więc zminimalizowane wyrażenie ma dwa czynniki. Ponownie
w każdym z wyrażeń usunięto zmienną, która miała różną wartość dla
każdej z jedynek (w parze).
3. Zminimalizujmy wartość wyrażenia w = ābc̄d + ābcd + abc̄d + abcd.
Mamy
w = ābc̄d + ābcd + abc̄d + abcd = ābd + abd = abd.
Wypełniamy tabelę symbolami 1 i 0 stosownie do badanego wyrażenia,
otrzymując:
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 0 0 0 0
01 | 0 1 1 0
11 | 0 1 1 0
10 | 0 0 0 0
Ponownie „ jedynki” są obok siebie a o układzie jaki tworzą można
powiedzieć, iż jest to szczególny przypadek prostokąta – kwadrat. Zauważmy, że ponownie w minimalizowanym wyrażeniu pozostały jedynie te indeksy wierszy i kolumn z „ jedynkami” które nie ulegały
zmianie.
¯
4. Zminimalizujmy wartość wyrażenia w = abc̄d¯ + abc̄d + abcd + abcd.
Mamy
w = abc̄d¯ + abc̄d + abcd + abcd¯ = abc̄ + abc = ab.
Wypełniamy tabelę symbolami 1 i 0 stosownie do badanego wyrażenia,
otrzymując:
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
20
Zbuduj sobie HDA
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 0 0 0 0
01 | 0 0 0 0
11 | 1 1 1 1
10 | 0 0 0 0
Ponownie „ jedynki” są obok siebie i tworzą prostokąt.
¯
5. Zminimalizujmy wartość wyrażenia w = āb̄c̄d¯ + āb̄cd¯ + ab̄c̄d¯ + ab̄cd.
Mamy
¯
w = āb̄c̄d¯ + āb̄cd¯ + ab̄c̄d¯ + ab̄cd¯ = āb̄d¯ + ab̄d¯ = b̄d.
Wypełniamy tabelę symbolami 1 i 0 stosownie do badanego wyrażenia,
otrzymując:
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 1 0 0 1
01 | 0 0 0 0
11 | 0 0 0 0
10 | 1 0 0 1
Jeśli teraz dopuścimy możliwość „zawijania” tabeli (czyli przyjmiemy,
że ostatnia kolumna jest sąsiednia w stosunku do pierwszej; podobnie
z wierszami), wówczas ponownie „ jedynki” są obok siebie i tworzą
prostokąt.
Jaki wniosek można wyciągnąc z przedstawionych przykładów? Otórz jeśli
mając dane pewne wyrażenie uda nam się uzupełnić tabelkę w ten sposób aby umieszczone w niej „ jedynki” pogrupować w prostokąty (nazywane ogólnie klatkami), wówczas z danego prostokąta wybieramy tylko te
symbole, które dla wszystkich „ jedynek” pozostały niezmienne; symbole te
utworzą minimalizowane wyrażenie. Ważne jest aby pamiętać, że prostokąty muszą zawierać 2k elementów, przy czym k = 1, . . . , n, gdzie n jest
ilością argumentów funkcji4 .
4
Nie można tego akurat zauważyć na prezentowanych przykładach, ale pozostawiamy
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.9 Kod Gray’a
21
1-bitowy
0
1
2-bitowy
0
0
0
1
1
1
1
0
3-bitowy
0 0 0
0 0 1
0 1 1
0 1 0
1 1 0
1 1 1
1 0 1
1 0 0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
4-bitowy
0 0 0
0 0 1
0 1 1
0 1 0
1 1 0
1 1 1
1 0 1
1 0 0
1 0 0
1 0 1
1 1 1
1 1 0
0 1 0
0 1 1
0 0 1
0 0 0
Tablica 1.8. 1-, 2-, 3- i 4-bitowe kody Greya
1.9
Kod Gray’a
Kluczem do sukcesu przy minimalizacji wyrażeń w przykładach z poprzedniego podrozdziału był sposób wypełniania tabeli a właściwie sposób
numerowania jej wierszy i kolumn. Zauważmy, że każde dwa wiersze czy kolumny (uwzględniając możliwość „zawijania”) różnią się tylko jednym symbolem. I tak np. wiersz „trzeci” numerowany jako 11 różni się od „czwartego” numerowanego jako 10 na drugiej pozycji numeru; pierwsza jest taka
sama i jest nią „ jedynka”. Tak więc bardzo pożądaną umiejetnością jest
zdolnośc do konstruowania kodów mających właśnie taką własność – dwa
sąsiednie kody różnią się tylko na jednej pozycji. Własność taką posiada na
przykład Kod Greya. Tablica 1.8 zawiera przykłady 1-, 2-, 3- i 4-bitowych
kodów Greya.
wykonanie kilku prób jako ćwiczenie dla czytelnika.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
22
Zbuduj sobie HDA
Rys. 1.8. Tablice Karnaugha dla funkcji 3, 4, 5 i 6 argumentów
1.10
Tablice Karnaugha
Pomysł wykorzystania kodów Greya do konstruowania tablic podobnych
to tych z przykładu pochodzi od M. Karnaugh (1953 r.).Stąd też tablice tego
typu nazywamy tablicami Karnaugha. Przykładowe tablice Karnaugha dla
funkcji 3, 4, 5 i 6 zmiennych przedstawiono na rysunku 1.8. Uzupełnijmy
teraz wiadomości o tablicach Karnaugha o informacje, których w podanych
przykładach nie było. Zacznijmy od wartości nieokreślonych. Otórz czasem
zdarza się tak, że pewna kombinacja sygnałów wejściowych nie może wystąpić – na przykład żarówka jest albo włączona, albo wyłączona; nie może
być częściowo włączona5 . Wówczas podczas uzupełniania tablicy pozostaną
nam pola nieokreślone. Każde takie nieokreślone pole może mieć wartość
1 lub 0 w zależności od naszych potrzeb. Mówiąc inaczej, to my ustalamy
jaką wartość ma pole nieokreślone. Nie ma to dla układu żadnego znaczenia
bo przecież i tak nigdy taka sytuacja nie wystąpi. Popatrzmy na kolejne
przykłady.
1. Zminimalizujmy wartość wyrażenia w = āb̄c̄d¯ + ābc̄d¯ + ab̄c̄d¯ wiedząc,
¯ Wypełniamy tabelę symbolami
że nie wystąpi układ sygnałów: abc̄d.
1 i 0 stosownie do badanego wyrażenia, otrzymując:
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 1 0 0 0
01 | 1 0 0 0
11 | ? 0 0 0
10 | 1 0 0 0
W tym przypadku wygodnie jest przyjąć, że w pole odpowiadające
¯
wyrażeniu abc̄d¯ wpisujemy wartość 1. Tak więc w = c̄d.
2. Zminimalizujmy wartość wyrażenia w = ābc̄d + ābcd wiedząc, że nie
5
Dopuszczając nawet istnienie sprytnych układów umożliwiajacych przyciemnianie
światła powiemy co najwyżej, że żarówka słabiej świeci, ale nie powiemy, że świeci i
nie świeci w tym samym czasie.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.10 Tablice Karnaugha
23
¯ Wypełniamy tabelę symbolami 1 i 0
wystąpi układ sygnałów: āb̄cd.
stosownie do badanego wyrażenia, otrzymując:
\cd|
\ |
ab\|00 01 11 10
---+----------00 | 0 0 0 ?
01 | 0 1 1 0
11 | 0 0 0 0
10 | 0 0 0 0
W tym przypadku wygodnie jest przyjąć, że w pole odpowiadające
wyrażeniu āb̄cd¯ wpisujemy wartość 0. Tak więc w = ābd.
Zauważmy, że dotychczas zawsze otrzymywaliśmy wyrażenie w Alternatywnej Postaci Normalnej, czyli sumy iloczynów. Aby uzyskać równoważną
Koniunkcyjną Postań Normalną, czyli iloczyn sum nieznacznie musimy zmodyfikować nasze działania:
• do tabeli wpisujemy zera funkcji (zamiast jedynek jak to miało miejsce
do tej pory);
• wspólne literały z klatki stanowią sumę;
• pomiędzy sumami otrzymanymi z klatek piszemy znak iloczynu;
• literały wchodzące w skład sumy są wstawiane w afirmacji jeśli literał
ma w klatce wartość 0 i w negacji, jeśli dany literał ma wartość 1.
Projektując funkcje realizujące odpowiednie odwzorowanie możemy żądać aby uzyskane wyrażenie algebraiczne było w jednej z dwóch wspomnianych form. W szczególności rozważmy takie zadanie. Utworzyć wyrażenie
algebraiczne w postaci sumy iloczynów i iloczynu sum realizujące związek
pomiędzy wejściem i wyjściem opisany tabelką 1.9. W tabelce tej dodano
także dwie dodatkowe kolumny: suma iloczynów oraz iloczyn sum – wartości z tych kolumn posłużą nam do budowy odpowiednich wyrażeń. Jeśli
chcemy otrzymać wyrażenie w postaci sumy iloczynów, wówczas w kolumny
opisanej jako suma iloczynów bierzemy te wiersze, dla których wyjście równe
jest 1 i łączymy je operatorem sumy. Chcąc otrzymać wyrażenie w postaci
iloczynu sum wybieramy te wiersze z kolumny opisanej jako iloczyn sum,
dla których wyjście równe jest 0 i łączymy je operatorem iloczynu. Tak więc
w naszym przypadku otrzymujemy
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
24
Zbuduj sobie HDA
Wejście
x
y
0
0
0
1
1
0
1
1
Wyjście
z
1
0
1
1
Sumy
iloczynów
x̄ȳ
x̄y
xȳ
xy
Iloczyny
sum
x+y
x + ȳ
x̄ + y
x̄ + ȳ
Tablica 1.9. tutu
x1
0
0
0
0
1
1
1
1
Wejście
x2 x3
0
0
0
1
1
0
1
1
0
0
0
1
1
0
1
1
Wyjście
y
0
0
1
1
0
0
1
0
Sumy
iloczynów
x̄1 x̄2 x̄3
x̄1 x̄2 x3
x̄1 x2 x̄3
x̄1 x2 x3
x1 x̄2 x̄3
x1 x̄2 x3
x1 x2 x̄3
x1 x2 x3
Iloczyny
sum
x1 + x2 + x3
x1 + x2 + x̄3
x1 + x̄2 + x3
x1 + x̄2 + x̄3
x̄1 + x2 + x3
x̄1 + x2 + x̄3
x̄1 + x̄2 + x3
x̄1 + x̄2 + x̄3
Tablica 1.10. tutu
suma iloczynów
z = x̄ȳ + xȳ + xy = ȳ(x̄ + x) + x(ȳ + y) = ȳ + x;
iloczyn sum
z = x + ȳ
W przykładzie tym dosyć łatwo można zaobserwować jak tworzy się odpowiednie wyrażenia wpisywane do dwóch ostatnich kolumn. Niestety z
dydaktycznego punktu widzenia posiada on pewną niedoskonałość. O ile widać jasno, że za pierwszym razem otrzymaliśmy wyrażenie w postaci sumy
iloczynów, o tyle wrażenie w postaci iloczynu sum. . . jest iloczynem sum,
ale bez iloczynu. Rozważmy zatem jeszcze jeden przykład, w którym stanie
się to wyraźniejsze. Relacje pomiędzy wejściem a wyjściem opisuje tabelka
1.10.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
1.10 Tablice Karnaugha
25
suma iloczynów
y = x̄1 x2 x̄3 + x̄1 x2 x3 + x1 x2 x̄3
= x̄1 x2 (x̄3 + x3 ) + x2 x̄3 (x̄1 + x1 )
= x̄1 x2 + x2 x̄3 ;
iloczyn sum
y = (x1 + x2 + x3 )(x1 + x2 + x̄3 )(x̄1 + x2 + x3 )
·
(x̄1 + x2 + x̄3 )(x̄1 + x̄2 + x̄3 )
= [(x1 + x2 ) + (x3 x̄3 )][(x̄1 + x2 ) + (x3 x̄3 )]
·
[(x̄1 + x̄3 ) + (x2 x̄2 )]
= (x1 + x2 )(x̄1 + x2 )(x̄1 + x̄3 )
= [x2 + (x1 x̄1 )](x̄1 + x̄3 )
= x2 (x̄1 + x̄3 ).
Oczywiście w obu tych przykładach możemy skorzystać z tablic Karnaugh.
Zacznijmy od wyrażenia w postaci sumy iloczynów.
y = x̄1 x2 x̄3 + x̄1 x2 x3 + x1 x2 x̄3 = . . .
Tworząc odpowiednią tablicę, otrzymujemy
\x_3
\ |
x_1 x_2\| 0 | 1 |
--------+---+---+
0
0 |
0
1 | 1
1
1
1 |
1
1
0 |
a więc
= x̄1 x2 + x2 x̄3 .
Zajmijmy się teraz drugą z postaci kanonicznych, tj. postacią iloczynu sum.
y = (x1 + x2 + x3 )(x1 + x2 + x̄3 )(x̄1 + x2 + x3 )
·
(x̄1 + x2 + x̄3 )(x̄1 + x̄2 + x̄3 )
= ...
Tworząc odpowiednią tablicę, otrzymujemy
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
26
Zbuduj sobie HDA
\x_3
\ |
x_1 x_2\| 0 | 1 |
--------+---+---+
0
0 | 0
0
0
1 |
1
1 |
0
1
0 | 0
0
co daje (mamy dwie klatki: pierwsza i druga kolumna z pierwszego i ostatniego wiersza oraz druga kolumna z ostatniego i przedostaniego wiersza)
· · · = x2 (x̄1 + x̄3 ).
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Rozdział 2
Dwie bramki to już układ
W rozdziale 1 zapoznaliśmy się z podstawowymi pojęciami, elementami
i sposobami opisu układów cyfrowych. Teraz spróbujemy tę wiedzę wykorzystać projektując różne mniej lub bardziej złożone układy. Jak później
zobaczymy, z tych układów tworzy się układy o większej złożoności a z
tychże tworzy się. . . procesor. A podstawą zawsze są „zwykłe” bramki.
2.1
Komparator jednobitowy
Układ tego typu porównuje ze sobą dwa bity – jeśli są takie sam, to
zwraca wartość 1, jeśli zaś różne to 0. Związek pomiędzy sygnałami wejściowymi i wyjściowymi przedstawiono w tabeli 2.1. Bazujac na wcześniej
zdobytej wiedzy, otrzymujemy, następujące wyrażenie opisujące sygnał na
wyjściu układu
y = ī1 ī2 + i1 i2 .
Odpowiedni schemat przedstawiono na rysunku 2.1. Komparator jednobitowy jest cegiełką, która posłuży nam do zbudowania komparatora nWejście
i1 i2
0
0
0
1
1
0
1
1
Wyjście
o
1
0
0
1
Tablica 2.1. Zależnośc pomiędzy wejściem i wyjściem komparatora 1-bitowego
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
28
Dwie bramki to już układ
Rys. 2.1. Komparator 1-bitowy.
Rys. 2.2. Komparator 4-bitowy
bitowego, w naszym przypadku 4-bitowego; odpowiedni schemat przedstawiono na rysunku 2.2.
2.2
Sumator jednobitowy
Kolejnym, wydaje się niezbędnym, elementem każdego procesora jest
sumator. Podobnie jak z komparatorem, rozważa się sumator 1-bitowy a
następnie z niego buduje się sumatory n-bitowe. Jak sama nazwa mówi,
układ tego typu odpowiedzialny jest za wykonywanie jednej z 4 podstawowych operacji arytmetycznych – dodawania. Sumator posiada następujące
wejścia i wyjścia
wejścia
• ci (ang. carry in) – sygnał przeniesienia z poprzedniej pozycji;
dzieki niemu możemy łączyć sumatory 1-bitowe celem dodawania
liczb o większej liczbie bitów;
• i1 , i2 – dodawane bity;
• co (ang. carry out) – przeniesienie do następnej pozycji;
wyjścia
• o – bit sumy danych i1 oraz i2 .
Związek pomiędzy sygnałami wejściowymi i wyjściowymi przedstawiono w
tabeli 2.2. Otrzymujemy, następujące wyrażenia opisujące sygnały na wyjściu układu
co = c̄i i1 i2 + ci ī1 i2 + ci i1 ī2 + ci i1 i2 ,
o = c̄i ī1 i2 + c̄i i1 ī2 + ci ī1 ī2 + ci i1 i2 .
Narysujmy teraz tablice Karnaugha dla obu tych wyrażeń.
\c_i
\c_i
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
2.2 Sumator jednobitowy
29
Wejście
ci i1 i2
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Wyjście
co
o
0
0
0
1
0
1
1
0
0
1
1
0
1
0
1
1
Tablica 2.2. Zależnośc pomiędzy wejściem i wyjściem sumatora 1-bitowego
\ |
i_1 i_2\| 0 | 1 |
--------+---+---+
0
0 |
0
1 |
1
1
1 | 1
1
1
0 |
1
\ |
i_1 i_2\| 0 | 1 |
--------+---+---+
0
0 |
1
0
1 | 1
1
1 |
1
1
0 | 1
Jak widać wyrażenie co możemy uprościć w oparciu o tablicę, natomiast w
stounku do drugiego musimy niestety wykazać się inteligencją. Zacznijmy
od podstawowych przekształceń:
o = c̄i ī1 i2 + c̄i i1 ī2 + ci ī1 ī2 + ci i1 i2
= c̄i (ī1 i2 + i1 ī2 ) + ci (ī1 ī2 + i1 i2 )
= ...
(2.1)
Zauważmy teraz, że zachodzi następujący związek:
i¯1 i2 + i1 i¯2 = (i¯1 i2 )(i1 i¯2 )
= (i1 + ī2 )(ī1 + i2 ) = (i1 + ī2 )i1 + (i1 + i¯2 )i2
= i¯1 i¯2 + i1 i2 .
Tak więc przyjmując podstawienie
s = ī1 i2 + i1 ī2
otrzymujemy
o = · · · = c̄i s + ci s̄.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
(2.2)
30
Dwie bramki to już układ
Rys. 2.3. Układ generujący sygnał co
Rys. 2.4. Układ generujący sygnał o
Schematy układów generujących sygnały wyjściowe co i o przedstawiono na
rysunkach 2.3 oraz 2.4. Na rysunku 2.5 przedstawiono symboliczny zapis
układu będącego sumatorem 1-bitowym natomiast rysunek 2.6 przedstawia
schemat sumatora 4-bitowego.
2.3
Dekoder adresowy
Dekoder to inaczej układ przekształcający jeden kod binarny na inny.
Budowa dekodera uzależniona jest od realizowanego zadania. W tym przypadku będziemy mieć do czynienia z dekoderem adresowym, czyli układem
wybierającym jedną z kilku możliwości (konkretnie: jedną z kilku komórek
pamięci) na podstawie podanego adresu. Ustalmy zatem, że wybieramy
jedną spośród 4 komórek pamięci. Zatem układ powinien mieć 4 wyjścia.
Sygnał o wartości 1 powinien być zawsze tylko na jednym wyjściu – tym
Rys. 2.5. Symboliczny zapis układu będącego sumatorem 1-bitowym
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
2.3 Dekoder adresowy
31
Rys. 2.6. Schemat sumatora 4-bitowego
Wejście
a1 a2
0
0
0
1
1
0
1
1
o1
1
0
0
0
Wyjście
o2 o3 o4
0
0
0
1
0
0
0
1
0
0
0
1
Tablica 2.3. Zależność pomiędzy wejściem i wyjściem 4-bitowego dekodera
adresowego
wskazanym przez adres. Do wskazania jednej z 4 możliwych liczb potrzebujemy 2 bitów, zatem układ będzie miał 2 wejścia. Zależności pomiędzy
wejściami i wyjściami zebrano w tabeli 2.3 natomiast schemat układu przedstawiono na ryskunku 2.7
Mamy więc już opracowany dekoder adresowy, a więc układ „wskazujący” jedną, wybraną, komórkę pamięci. Teraz powinniśmy dodać układ
realizujący odczyt wybranej w ten sposób komórki. Wejściem dla takiego
D
układu są wejścia z dekodera iD
1 -i4 oraz wejścia z poszczególnych komóM
M
rek układu pamięci i1 -i4 . Na wyjściu o, które jest tylko jedno, powinien
pojawić się sygnał z wybranej komórki pamięci. Schemat takiego układu
Rys. 2.7. Dekoder adresowy
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
32
Dwie bramki to już układ
Rys. 2.8. Układ realizujący odczyt komórki pamięci wskazanej przez 4-bitowy
dekoder adresowy
Wejście
R S
0
0
0
1
1
0
1
1
Wyjście
Q
Q
bez zmian
0
1
1
0
niedozwolone
Tablica 2.4. Zależność pomiędzy wejściem i wyjściem przerzutnika R-S
przedstawiono na rysunku 2.8.
2.4
Przerzutniki
Przerzutniki posiadają zwykle kilka wejść sterujących i dwa wyjścia o
przeciwnych stanach, oznaczane zwykle Q oraz Q.
2.4.1
Przerzutniki typu R-S
Przerzutniki tego typu posiadają dwa wejścia:
• R – (ang. reset),
• S – (ang. Set)
i dwa wyjścia: Q oraz Q.
Gdy na wejściach R i S podany zostanie sygnał o wartości 0, wówczas
przerzutnik nie zmienia swojego stanu. Podanie na wejście S stanu 1 (przy
jednoczesnym podaniu na wejście R stanu 0) powoduje ustawienie wyjścia
Q na 1. Podanie stanu 0 na wejście S (przy jednoczesnym podaniu na wejście R stanu 1) powoduje ustawienie na wyjściu Q stanu 0. Zauważmy, że
pojawienie się na obu wejściach sygnału o wartości 1 powoduje, że zarówno
wyjście Q jak i Q są w stanie 0 co nie jest dozwolone. Tabelka 2.4 opisuje zależności pomiędzy stanem sygnałów R i S oraz Q i Q. Schemat przerzutnika
R-S oraz jego symbol przedstawiono na rysunku 2.9. Jak widać przerzutnik
Rys. 2.9. Schemat przerzutnika R-S a) oraz jego symbol b)
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
2.4 Przerzutniki
33
Wejście
R S
0
0
0
1
1
0
1
1
Wyjście
Q
Q
niedozwolone
1
0
0
1
bez zmian
Tablica 2.5. Zależność pomiędzy wejściem i wyjściem przerzutnika R-S
Rys. 2.10. Schemat przerzutnika R-S a) oraz jego symbol b)
tpu R-S zbudowany jest w oparciu o bramki NOR. Stosując bramki NAND
również otrzymujemy przerzutnik, oznaczany czasem dla odmiany R-S. W
tym przypadku zależność pomiędzy wejściem i wyjściem opisuje tabela 2.5.
Jak widać zachowanie przerzutnika jest podobne, ale pod wpływem innych
sygnałów. Teraz niedozwolone jest podanie na oba wejścia jednocześnie sygnału 0. Sygnał o wartości 1 na obu wejściach oznacza brak zmiany stanu
przerzutnika. Wyjście Q staje się aktywne, po podaniu sygnału o wartości
0 na wejście S. Wyjście Q przyjmie stan 0 jeśli na wejściu R pojawi się sygnał o wartości 1. Zauważmy, że przerzutnik zbudowany w oparciu o bramki
NAND, przechodzi w stan aktywny (sygnał o wartości 1 na wyjściu Q) gdy
podamy na wejście S sygnał o wartości 0. W takich przypadkach na wejściu
układu będziemy rysować kółeczka podobne do tych przy bramce NOR czy
też NAND. Schemat przerzutnika zbudowanego w oparciu o bramki NAND
oraz jego symbol przedstawia rysunek 2.10.
2.4.2
Hazard
Wszystkie rozważane do tej pory układy były idealne. Ich idealność
polegała na natychmiastowej reakcji każdej bramki; inaczej mówiąc czas reakcji bramki na zmianę sygnałów wejściowych wynosi 0. I nie ma znaczenia
z ilu bramek układ jest zbudowany – podając sygnał na wejście w tym samym momencie otrzymujemy sygnał na wyjściu. Niestety w rzeczywistości
nie jest tak pięknie. Właściwy poziom sygnału na wyjściu każdej bramki
ustala się dopiero po upływie pewnego czasu, tzw. czasu propagacji. W
konsekwencji stan całego układ ustala się dopiero po pewnym czasie. Zanim to nastąpi, stan wyjść nie jest określony żadną funkcją logiczną gdyż
nawet dwa identyczne układy mogą się zachowywać odmiennie z uwagi na
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
34
Dwie bramki to już układ
Rys. 2.11. 3 bramki NOT połączone szeregowo
Rys. 2.12. Czasy propagacji sygnałów w układzie z rysunku 2.11
pewne różnice w parametrach tworzących je układów1 .
Przyjrzyjmy się poniższemu przykładowi.
Przykład 2.1. Propagacja sygnału.
Rozważmy uład składający się z szeregowo połączonych bramek NOT (rysunek 2.11). Z teoretycznego punktu widzenia, trzy bramki NOT powinny dać
w efekcie na wyjściu negację sygnału wejściowego
o = N OT (N OT (N OT (i))) = N OT (i)
Załóżmy, że na wejście układu podajemy sygnał o wartości 1. Zanim nie
minie odpowiedni czas t nic nie możemy powiedzieć o stanie sygnału na
wyjściu bramki g2 oraz g3 . Mówic inaczej, sygnał musi tam dopiero „dopłynąć”. Tak więc oczekiwaną wartość 0 na wyjściu układu otrzymamy dopiero
po czsie 3t (patrz rysunek 2.12).
Dobrze by zatem było aby istniał jakiś mechanizm zapewniający dostęp do „dobrych” sygnałów, a więc tych już ustabilizowanych. Jednym ze
sposobów jest wprowadzenie sygnłu synchronizującego układy. Najczęściej
jest to sygnał, w którym stan 0 i 1 pojawiają się naprzemiennie i trwają
tyle samo czsu – stąd mówimy o nim sygnał zegarowy, lub też mówimy o
taktowaniu. Okres taktu zegarowego2 powinien być oczywiście dobrany w
taki sposób aby zdążyły ustalić się w tym czasie stany wszystkich bramek.
Stan układu analizowany jest dopiero przy końcu taktu zegarowego.
Teraz może łatwiej będzie zrozumieć dlaczego zwiększanie „szybkości
procesora” to taki trudny temat3 . Zwiększanie częstotliwości pracy pociąga
za sobą konieczność skonstruowania układów o mniejszym czasie propagacji. Bez tego, samo zwiększani częstotliwości taktowania doprowadzi nas do
sytuacji gdy sieć nie będzie zdolna do ustabilizowania się w ramach jednego
1
Dodajmy, że mówimy tutaj o różnicach mieszczących się z zakresie tolerancji danego
parametru a więc np. z punktu widzenia producenta układy są identyczne.
2
Czyli czas trwania stanu 0 lub 1. Ilość zmian stanu w ciągu sekundy wyrażamy w
hercach (Hz).
3
Poza tym mamy nadzieję, że w końcu wyjaśniło się po co są te „gigaherce” w komputerze.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
2.4 Przerzutniki
35
Wejście
R S C
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Wyjście
Q
Q
bez zmian
bez zmian
bez zmian
1
0
bez zmian
0
1
bez zmian
niedozwolone
Tablica 2.6. Zależność pomiędzy wejściem i wyjściem synchronicznego
przerzutnika R-S
Rys. 2.13. Przerzutnik synchroniczny typu R-S i jego symbol
taktu zegara. Przy okazji zauważmy, że bramka logiczna pobiera najwięcej
energii w momencie zmiany swojego stanu. Zwiększenie taktowania powoduje zwiększenie liczby zmiany stnów w danej jednostce czsu, czyli większe
zużycie energii, czyli więcej ciepła wydzielanego przez układ. To wyjaśnia
trochę dlaczego niektóre współczesne procesory służyć mogą jako przepływowe ogrzewacze wody.
2.4.3
Synchroniczny przerzutnik typu R-S
Najłatwiejszy sposób na uzyskanie synchronizowanego przerzutnika jest
dodanie, do „zwykłego” przerzutnika typu R-S, dwóch bramek typu NAND,
których zadaniem jest blokowanie sygnałów z wejść R i S tak długo jak
sygnał zegarowy C jest nieaktywny (ma wartość 0). Zależność pomiędzy
wejściem a wyjściem zebrano w tabeli 2.6 natomiast odpowiedni schemat i
symbol przerzutnika przedstawia rysunek 2.13.
Zauważmy, że „zezwolenie” nia działanie układu może zostać przekazana
przez sygnał taktujacy na 4 sposoby:
• przez wysoki stan sygnału taktującego (odpowiedni symbol przerzutnika na rysunku 2.14 a)),
• przez niski stan sygnału taktującego (rysunek 2.14 b)),
• przez narastające zbocze sygnału taktującego (rysunek 2.14 c)),
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
36
Dwie bramki to już układ
Rys. 2.14. Symbole odpowiadające przerzutnikom z 4 sposobami wyzwalania: a)
– stanem wysokim, b) – stanem niskim, c) – narastającym zboczem, d) –
opadającym zboczem
Rys. 2.15. Przerzutnik typu D
• przez opadające zbocze sygnału taktującego (rysunek 2.14 d)).
Przerzutniki wyzwalane stanem sygnału zegarowego nazywamy przerzutnikami statycznimi lub też zatrzaskami (ang. latch); przerzutniki wyzwalane
zboczem sygnału segarowego nazywamy przerzutnikami dynamicznymi.
2.4.4
Przerzutnik typu D
Przerzutnik typu D to kolejna wariacja na temat przerzutnika typu R-S
a dokładnie jego synchronicznej mutacji. Otóż do synchronicznego przerzutnika R-S dodajemy bramkę NOT w taki sposób, że wejście R jest zanegowany sygnałem z wejścia S (patrz rysunek 2.15). Działanie przerzutnika
polega na przenoszeniu stanu z wejścia D na wyjście Q w czasie trwania
stanu aktywnego na wejściu C. Gdy wejście wyzwalające przejdzie w stan
nieaktywny, przerzutnik zapamiętuje ostatnio ustawiony stan. Dokładne
zależności pomiędzy wejściem i wyjściem zawiera tabela 2.7. Jak niebawem
się przekonamy takie działanie wykorzystywane jest np. przy tworzeniu
liczników.
2.4.5
Przerzutnik typu J-K
Przerzutnik typu J-K otrzymujemy z synchronicznego przerzutnika typu
R-S wyzwalanego opadającym zboczem sygnału zegarowego przez dodanie
Wejście
D C
0
0
0
1
1
0
1
1
Wyjście
Q Q
— —
0
1
— —
1
0
Tablica 2.7. Zależność pomiędzy wejściem i wyjściem przerzutnika typu D
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
2.5 Rejestr
37
Wejście
J K
0
0
0
1
1
0
1
1
Wyjście
Q
Q
—
—
0
1
1
0
! — ! —
Tablica 2.8. Zależność pomiędzy wejściem i wyjściem przerzutnika typu J-K
Rys. 2.16. Przerzutnik typu J-K
dwóch bramek AND (rysunek 2.16). Zależność pomiędzy wejściami i wyjściami przedstawia tabelka 2.8.
2.5
Rejestr
Mając odpowiednią bazę w postaci różnych typów przerzutnikow powracamy teraz do układów złożonych. Zadaniem rejestrów jest przede wszystkim przechowywanie danych. Zasadnicze różnice pomiędzy rejestrami skupiają się na sposobie zapisu (równoległy, szeregowy) oraz odczytu danych
a także ilości bitów jakiej jednocześnie operacje te dotyczą. Na rysunku
2.17 przedstawiono schemat rejestru 4-bitowego. Wejściami danych są i1 ,
i2 , i3 oraz i4 . Służą one jak łatwo zgadnąć do wprowadzania danych. Aby
dane zostały zapisane, na wejściu w musi nastąpić zmiana sygnału z 0 na 1
(zapis przy narastającym zboczu). Informację zapisaną w rejestrze możemy
odczytać z wyjść o1 , o2 , o3 , o4 .
2.6
Pamięć
Do zbudowania układu pamięci potrzebny będzie nam dekoder adresowy
wraz z układem realizującym odczyt wybranej przez dekoder komórki pamięci (patrz punkt 2.3) oraz komórki pamięci (patrz 2.5). Jako, że wszystkie
wymagane składniki zostaly już omówione, wystarczy je tylko połączyć w
funkcjonalną całość. Schemat układu pamięci przedstawia rysunek 2.18.
Rys. 2.17. Rejestr zbudowany z przerzutników typu D
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
38
Dwie bramki to już układ
Rys. 2.18. Schemat układu będącego 4-bitową pamięcią
Rys. 2.19. Podstawowy układ zliczający zbudowany w oparciu o przerzutnik typu
D
2.7
Licznik
Licznik jest układem zliczającym w impulsy podawane na jego wejście.
W swej najprostszej postaci, licznik dokonuje zliczania w naturalnym kodzie bitowym. Podstawowym elementem konstrukcyjnym jest układ, zmieniający swój stan na przeciwny przy każdorazowym podaniu sygnału na
jedno z wejść. Pozostając w kręgu poznanych układów, element taki można
skonstruować w oparciu o przerzutnik typu D co pokazano na rysunku 2.19.
Łacząc ze sobą kilka takich układów możemy w prosty sposób uzyskać licznik
zliczające większą ilość wystąpień sygnału. Przykład dla licznika 4-bitowego
przedstawia rysunke 2.20. Wykres czasowy stanów poszczególnych wyjść
przedstawiono na rysunku 2.21. Dodajmy jeszcze, że tak skonstruowane
liczniki nazywać bedziemy asynchronicznymi gdyż poszczególne przerzutniki
nie przełączają się jednocześnie, lecz z pewnym opóźnieniem, wynikającym
z czasu propagacji sygnału w poprzednim przerzutniku.
Rys. 2.20. Licznik 4-bitowy
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
2.7 Licznik
Rys. 2.21. Zmiany stanów poszczególnych wyjść licznika 4-bitowego w czasie
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
39
40
Dwie bramki to już układ
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Rozdział 3
Dlaczego 2+2=5?
I am a HAL Nine Thousand computer
[. . . ]
The quick brown fox jumps over the lazy
dog [. . . ]
Dave – are you still there?
Did you know that the square root of 10
is 3.162277660168379?
Log 10 to the base e is
0.434294481903252. . . correction, that is
log e to the base 10 [. . . ]
2 times 2 is. . . 2 times 2
is. . . approximately 4.10101010. . . I seem
to be having difficulty
HAL, 2001: A Space Odyssey
3.1
Dlaczego?
Ograniczenia jakie niesie ze sobą format IEEE 754 zapisu liczby zmiennoprzecinkowej są widoczne i oczywiste po uważniejszym jemu przyjrzeniu
się. Zasadniczym motywem zbadania jego był to, że kiedyś dodając na komputerze dwie liczby, obie miały część ułamkową dwucyfrową, otrzymałem
liczbę całkowitą. I nie byłoby w tym nic dziwnego gdyby nie to, że części
ułamkowe nie sumowały się do liczby całkowitej. Poirytowany tym faktem
postanowiłem więc przyjrzeć się uważniej wspomnianemu formatowi.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
42
3.2
Dlaczego 2+2=5?
Doświadczenie 1
Tak więc na tapetę wzięty został format IEEE 754 a dokładniej mówiac
jego modyfikacja wykorzystująca 8 bitów. Format taki przedstawiony został
w [3]. Przypominijmy, że przyjmujemy następujące znaczenie bitów: pierwszy bit od lewej oznacza znak liczby, kolejne 3 mantysę zaś ostatnie 4 bity
będą cechą. Jako wartość stałej KC (odejmowanej od cechy) przyjmijmy 7.
Tak więc liczby dające się zapisać w tym formacie są postaci
zm M · 2C−KC ,
gdzie zm to znak mantysy, M – mantysa, C – cecha. Tak przyjęty format
jest dużo protszy do analizy (ze względu na mniejszą ilość bitów) a przy
tym raczej nie fałszuje w sposób istotnych względnych wyników (tj. stosunku poprawnych i błędnych obliczeń). Dla ułatwienia wzięte zostały pod
obserwację tylko liczby dodatnie.
Najpierw stworzony został program generujący wszystkie liczby jakie
można zapisać w tym formacie.
#define K_C 7
[...]
//przyjmuje nastepujaca kolejnosc bitow
//b2 b1 b0 c3 c2 c1 c0
char b2,b1,b0,c3,c2,c1,c0;
int cecha,i=0,j,k,blad=0,zakres=0;
float mantysa;
double t[128];
//przebieg po cesze
for(c3=0;c3<=1;c3++)
for(c2=0;c2<=1;c2++)
for(c1=0;c1<=1;c1++)
for(c0=0;c0<=1;c0++)
{
cecha=c0*1+c1*2+c2*4+c3*8-K_C;
//przebieg po mantysie
for(b2=0;b2<=1;b2++)
for(b1=0;b1<=1;b1++)
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
3.2 Doświadczenie 1
43
for(b0=0;b0<=1;b0++)
{
mantysa=1.0+0.5*b2+0.25*b1+0.125*b0;
t[i]=wypisz(b2,b1,b0,c3,c2,c1,c0,mantysa,cecha);
i++;
}
}
Funkcja Wypisz zdefiniowana została jak poniżej
double Wypisz(char b2,char b1,char b0,char c3,char c2,char c1,
char c0,float mantysa,int cecha)
{
double r;
fprintf(stdout,"%c",b2==0?’0’:’1’);
fprintf(stdout,"%c",b1==0?’0’:’1’);
fprintf(stdout,"%c",b0==0?’0’:’1’);
fprintf(stdout,"%c",c3==0?’0’:’1’);
fprintf(stdout,"%c",c2==0?’0’:’1’);
fprintf(stdout,"%c",c1==0?’0’:’1’);
fprintf(stdout,"%c",c0==0?’0’:’1’);
r=mantysa*pow(2,cecha);
fprintf(stdout," : %f*2^%d=%.10f",mantysa,cecha,r);
fprintf(stdout,"\n");
return r;
}
I tak, zgodnie z oczekiwaniami najmniejszą możliwą do reprezentowania
liczbą jest 0.0078125 zapisane jako 0000000 (1.000000 · 2−7 ), zaś największa
to 480.0 zapisane jako 1111111 (1.875000 · 28 ); łącznie mamy oczywiście 128
różnych liczb.
Teraz przyszedł czas na najważniejszą część tego doświadczenia. Biorąc
oto wszystkie możliwe kombinacje dwóch spośród otrzymanych 128 liczb,
sprawdzamy czy ich suma jest jedną z tych 128 liczb. Mówiąc inaczej sprawdzamy czy suma dwóch spośród owych 128 liczb daje się wyrazić w tym
formacie.
//szukam zlych sum
for(i=0;i<128;i++)
for(j=0;j<128;j++)
{
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
44
Dlaczego 2+2=5?
for(k=0;k<128;k++)
{
if(t[i]+t[j]==t[k])
{
k=255;
break;
}
}
if(k!=255)
{
if(t[i]+t[j]<=t[127])
{
blad++;
fprintf(stdout,"%.10f+%.10f=%.10f",t[i],t[j],
t[i]+t[j]);
fprintf(stdout," ERROR\n");
}
else
{
zakres++;
fprintf(stdout,"%.10f+%.10f=%.10f",t[i],t[j],
t[i]+t[j]);
fprintf(stdout," ZAKRES\n");
}
}
}
fprintf(stdout,"Lacznie bledow %d, poza zakresem %d (%d)\n",
blad,zakres,128*128);
Zauważmy, że łacznie mamy 128·128 = 16384 możliwości. Wyniki nie są
optymistyczne. Otóż 434 sumy są poza zakresem obejmowanym przez tak
przyjęty format (np. 480+480 daje 960). Trudno o to mieć jednak pretensje
– ograniczona ilość bitów skutkuje ograniczonym zakresem. Pozostaje więc
15950 sum. Z tego 14232 nie dają się wyrazić w tym formacie. Oznacza
to, że jedynie 1718 sum jest prawidłowych. Reszta to będą przybliżenia.
Zatem jedynie 9.28% wyników jest poprawna!!!
Gdyby opuścić wszystkie sumy, które się powtarzają, czyli nie rozróżniać
czy dodajemy x1 do x2 czy na odwrót: x2 do x1 , wówczas mamy 8256
różnych sum, z których 221 jest poza zakresem naszego formatu a 7121
nie daje się wyrazić w tym formacie. Oznacza to, że jedynie 914 sum jest
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
3.3 Doświadczenie 2
45
prawidłowych, czyli 11.37%.
Już samo to co napisano powyżej wystarcza do tego aby przenieść się
z prowadzeniem obliczeń na liczydła. Zróbmy jednak jeszcze jeden test.
Bierzmy więc dwie kolejne liczby i liczmy ich różnicę. Otrzymamy w ten
sposób wartość mówiącą nam o dokładności reprezentacji. Wyniki zebrano
w tabeli 3.1. Dla czytelności pominięte zostały różnice dające takie same
wyniki. I tak patrząc na wiersz o liczbie porządkowej 127 mamy tam różnicę
(dwóch kolejnych) liczb 480 i 448 wynoszącą 32. Oznacza to, że żadna liczba
całkowita (nie mówiąc już o rzeczywistych) większa od 448 a mniejsza od
480 nie daje się wyrazić w przyjętym formacie. Każda z takich liczb będzie
zaokrąglona „w górę” do 480 lub „w dół” do 448 w zależności od przyjętych
algorytmów.
3.3
Doświadczenie 2
Z pewnością wszystkim doskonale znany jest przypadek Lorenza i jego
motyla opisany w „Can the flap of a butterfly wing stir up a tornado in
Texas”. Problem dotyczy powstawania i akumulacji błędów zaokrągleń i
związany jest z niemożnością przewidywania w deterministycznych układach
ze sprzężeniem zwrotnym w tym także w matematycznych modelach, które
wykorzystywano do długoterminowych analiz pogody. Jak to zwykle bywa
na problem ten Lorentz natrafił przez przypadek.
Zaczęło się to wszystko gdzieś około roku 1956, kiedy pewne metody
przewidywania [pogody] zostały zaproponowane [. . . ] jako najlepsze z dostępnych, z czym się jednak nie zgadzałem. Zadecydowałem sam wysmażyć
niewielki układ równań symulujących zachowanie atmosfery, rozwiązać go
za pomocą komputerów, które wtedy właśnie zaczęły być dostępne, a następnie potraktować wyniki tak, jakby to były rzeczywiste dane z obserwacji
atmosferycznych, i sprawdzić, czy proponowane metody stosują się do nich.
Prawdziwym problemem było uzyskanie takiego układu równań, który doprowadziłby do wyników nadających się do przetestowania, ponieważ szybko
stało się jasne, że jeśli rozwiązanie tych równań będzie cykliczne, to proponowane metody będą trywialne, a tym samym będą stosowały się idealnie.
Musieliśmy więc otrzymać układ równań, mający rozwiązania niecykliczne,
takie które nie powtarzają się, ale przebiegają nieregularnie i w sposób niezdefiniowany. Znalazłem w końcu układ dwunastu równań, które to spełniały
i sprawdziłem, że proponowane metody nie były odpowiednie. Gdy to robiłem
chciałem sprawdzić niektóre z wyników w sposób bardziej szczegółowy. W
swoim biurze miałem wtedy mały komputer, wpisałem więc kilka pośrednich
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
46
Dlaczego 2+2=5?
L.p.
1
8
9
16
17
24
25
32
33
40
41
48
49
56
57
64
65
72
73
80
81
88
89
96
97
104
105
112
113
120
121
127
x
0.0078125000
0.0146484375
0.0156250000
0.0292968750
0.0312500000
0.0585937500
0.0625000000
0.1171875000
0.1250000000
0.2343750000
0.2500000000
0.4687500000
0.5000000000
0.9375000000
1.0000000000
1.8750000000
2.0000000000
3.7500000000
4.0000000000
7.5000000000
8.0000000000
15.0000000000
16.0000000000
30.0000000000
32.0000000000
60.0000000000
64.0000000000
120.0000000000
128.0000000000
240.0000000000
256.0000000000
448.0000000000
y
0.0087890625
0.0156250000
0.0175781250
0.0312500000
0.0351562500
0.0625000000
0.0703125000
0.1250000000
0.1406250000
0.2500000000
0.2812500000
0.5000000000
0.5625000000
1.0000000000
1.1250000000
2.0000000000
2.2500000000
4.0000000000
4.5000000000
8.0000000000
9.0000000000
16.0000000000
18.0000000000
32.0000000000
36.0000000000
64.0000000000
72.0000000000
128.0000000000
144.0000000000
256.0000000000
288.0000000000
480.0000000000
y−x
0.0009765625
0.0009765625
0.0019531250
0.0019531250
0.0039062500
0.0039062500
0.0078125000
0.0078125000
0.0156250000
0.0156250000
0.0312500000
0.0312500000
0.0625000000
0.0625000000
0.1250000000
0.1250000000
0.2500000000
0.2500000000
0.5000000000
0.5000000000
1.0000000000
1.0000000000
2.0000000000
2.0000000000
4.0000000000
4.0000000000
8.0000000000
8.0000000000
16.0000000000
16.0000000000
32.0000000000
32.0000000000
Tablica 3.1. Różnice pomiędzy kolejnymi wartościami
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
3.3 Doświadczenie 2
47
wartości, które komputer wydrukował, jako nowe warunki początkowe dla
następnych obliczeń, i na chwile wyszedłem. Kiedy wróciłem, zobaczyłem,
że rozwiązania były inne niż przedtem; komputer zachowywał się inaczej.
W pierwszej chwili podejrzewałem, że mam jakieś kłopoty z komputerem,
jednak wkrótce odkryłem, że prawdziwą przyczyną jest to, iż liczby wpisane
przeze mnie różniły się od liczb wyjściowych, które zaokrągliłem, i ta niewielka różnica pomiędzy czymś rozwiniętym do szóstego miejsca po przecinku
i jego zaokrągleniem do trzeciego miejsca w czasie symulacji dwóch miesięcy
pogody stała się tak wielka jak sam sygnał. Wynikało z tego, że jeżeli prawdziwa atmosfera zachowuje się w podobny sposób, to nie jesteśmy po prostu
w stanie przewidzieć pogody na dwa miesiące naprzód. Te małe błędy będą
się powiększać, aż staną się wielkie 1 .
Postanowiłem więc sprawdzić jak to faktczynie z tym motylem jest. Jako
temat dalszych rozważań wybrałem tak zwany model logistyczny a więc rekurencyjne wyrażenie następującej postaci
pn+1 = pn + rpn (1 − pn )
(3.1)
oraz jego „drugą” postać otrzymaną przez zastosowanie elementarnych przekształceń algebraicznych (tak więc z matematycznego punktu widzenia oba
te wyrażenia, jeśli nawet nie są takie same, to dają takie same wyniki)
pn+1 = (1 + r)pn − rp2n .
(3.2)
W powyższych równaniach r jest pewną stałą, natomiast n i n+1 to indeksy
odpowiednio poprzedniego i nowo obliczanego wyrazu. Jako wartość stałej
r przyjęto 3.0 natomiast jako wyraz a1 przyjęto wartość 0.01.
Dla obu wzorów dokonano po 500-set iteracji na dwóch różnych typach
liczbowych: float i double. Kilka przykładowych wyników przedstawiono w
tabeli 3.2. Zamieszczone w niej dane należy czytać w następujący sposób.
W ramach każdej iteracji mamy trzy wiersze: pierwszy to wynik obliczeń
przeprowadzonych na zmiennych typu float, drugi na zmiennych typu double
trzeci zaś to różnica pomiędzy tymi wynikami. Tak więc porównanie wiersza
pierwszego i drugiego daje nam pojęcie o wpływie przyjętej reprezentacji
na prowadzone obliczenia (w ramach tego samego wzoru). Jeśli natomiast
chcemy porównać ze sobą wzory, to interesuje nas pierwsza kolumna od
prawej, w której to zawarto różnice pomiędzy wartościami otrzymanym za
pomocą obu wzorów. I tak na przykład w iteracji 399 mamy, że dla wzoru
3.1 różnica pomiędzy wartościami obliczonymi przy użyciu zmiennych typu
1
W: [4], s. 79.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
48
Dlaczego 2+2=5?
Iteracja
Według wzoru 3.1
Według wzoru 3.2
1
0.009999999776483
0.010000000000000
-0.000000000223517
0.070538848638535
1.189384903904431
-1.118846055265897
0.267228215932846
0.513630266710465
-0.246402050777619
0.099408328533173
0.967600411062598
-0.868192082529425
0.856545627117157
1.298726103232332
-0.442180476115175
0.260175228118896
0.940545426832992
-0.680370198714096
0.009999999776483
0.010000000000000
-0.000000000223517
0.070538848638535
1.189384903904431
-1.118846055265896
0.267228215932846
0.513630266710467
-0.246402050777621
0.099408328533173
0.961800737412491
-0.862392408879318
0.856545627117157
0.008244384236384
0.848301242880773
0.260175228118896
0.257679774120511
0.002495453998385
257
258
300
399
500
Różnice pomiędzy
wzorami
0.000000000000000
0.000000000000000
0.000000000000000
0.000000000000000
0.000000000000000
-0.000000000000000
0.000000000000000
-0.000000000000001
0.000000000000001
0.000000000000000
0.005799673650107
-0.005799673650107
0.000000000000000
1.290481718995948
-1.290481718995948
0.000000000000000
0.682865652712481
-0.682865652712481
Tablica 3.2. Różnice pomiędzy kolejnymi wyrazami otrzymanymi za pomocą
wzorów 3.1 oraz 3.2
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
3.4 Wnioski
49
float i double wynosi −0.442180476115175. Ta sama różnica dla wzoru 3.2
wynosi 0.848301242880773. Zauważmy, że różnice są tego samego rzędu
co obliczane wartości! Jeśli natomiast chodzi o różnice pomiędzy wzorami
to dla typu double wynosi ona 1.290481718995948. Zastanawiający może
być fakt braku różnic dla typu float. tutu W tym momencie nie mam
wiarygodnego wyjaśnienia, choć mam kilka hipotez :) Oba wzory dają takie
same wyniki do 257 iteracji2 .
Na zakończenie jeszcze jeden test – test wrażliwościowy. Sprawdzimy
jaki wpływ na wyniki obliczeń ma zakłócenie warunków początkowych. To
całkiem tak jak przy pogodzie – zrobiliśmy pomiar temperatury powietrza
i „trochę” się pomyliliśmy. Tabela 3.3 prezentuje część wyników. Pierwszy wiersz dla każdej iteracji policzony został dla współczynnika r = 3.0,
drugi dla r = 3.000000000001, trzeci dla r = 3.0000000000001, czwarty
dla r = 3.00000000000001. Zmniejszenie części ułamkowej o następny rząd
wielkości, dawało dobre wyniki przez 20000 iteracji. Powodem tego może
być niemożność odwzorowania liczby 3 z tak małą częścią ułamkową i zaokrąglenie jej do 3.0 lub też błędy na dalszych, niewyświetlanych, pozycjach
co jest raczej wątpliwe bo po tylu iteracjach powinny one stać się widoczne.
3.4
Wnioski
Przedstawione w 3.2 rozważania, mimo iż bardzo uproszczone, ukazują
jednak cechy zmiennopozycyjnego sposobu reprezentacji liczb rzeczywistych
w komputerze. Należy mieć świadomość, że zwiększenie ilości bitów służących do reprezentacji liczby nie wnosi nowej jakości. Owszem, możliwe, że
w takm przypadku zamiast 1718, poprawnych będzie 1 milion sum. Ciągle
będzie to jednak ok 10% wszystkich możliwych kombinacji. Dla większości i tak będziemy zmuszeni użyć przybliżenia. Zwiększenie ilości bitów
skutkuje jedynie przesunięciem pewnych granic, ale nie ich zlikwidowaniem
(np. w rozważanym formacie można przedstawić wszystkie liczby całkowite
z zakresu [1,15]; powyżej bywa już różnie). W szczególności na przykładzie dwóch ostatnich liczb widać, jak duże niedokładności pociąga za sobą
używanie „dużych” (dużych dla danego formatu) liczb3 .
W punkcie 3.3 chcieliśmy natomiast zwrócić uwagę na stabilność obliczeń
numerycznych. Oto okazuje się, że nie ma nic bardziej niepewnego niż
2
3
Mówiąc dokładniej: wyniki są takie same biorąc pod uwagę 15 miejsc po przecinku.
Podobnie sprawa wygląda w przypadku „małych” liczb.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
50
Dlaczego 2+2=5?
Iteracja
1
2
3
4
5
6
7
51
Współczynnik
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
3.0+10E
3.0+10E-12
3.0+10E-13
3.0+10E-14
3.0+10E-15
Wyniki
0.039700000000000
0.039700000000010
0.039700000000001
0.039700000000000
0.039700000000000
0.154071730000000
0.154071730000075
0.154071730000008
0.154071730000001
0.154071730000000
0.545072626044421
0.545072626044783
0.545072626044457
0.545072626044425
0.545072626044422
1.288978001188801
1.288978001189313
1.288978001188852
1.288978001188806
1.288978001188801
0.171519142109176
0.171519142106890
0.171519142108948
0.171519142109153
0.171519142109174
0.597820120107100
0.597820120100453
0.597820120106437
0.597820120107033
0.597820120107094
1.319113792413797
1.319113792411292
1.319113792413548
1.319113792413772
1.319113792413795
0.074892694909774
0.462398200088556
0.056394912819080
1.280547749402646
0.178875826166109
Tablica 3.3. Wpływ niedokładności na otrzymywane wyniki
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
3.4 Wnioski
51
obliczenia przeprowadzone na komputerze. Ponownie „winę” za taki stan
rzeczy ponosi przyjęty format zapisu liczb.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
52
Dlaczego 2+2=5?
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Rozdział 4
Obliczenia numeryczne
4.1
O strukturze pamięci
Podczas pisania programów nie wystarczy myśleć; trzeba też wiedzieć.
Trzeba wiedzieć, dużo pisać. A pisząc bacznie obserwować, bo nie każdy
program choć taki sam działa tak samo. Przyjrzyjmy się oto dwum prawie
identycznym fragmentom kodu. Oba robią to samo a „optyczna” różnica
jest natury ideologicznej — bo to czy ktoś woli przechodzić po elementach
tablicy wierszami czy kolumnami, to nic innego jak ideologia. Czy aby
jednak tylko ideologia?
for(w=0;w<100;w++)
{
for(k=0;k<1000;k++)
{
tab[w][k]+=tab[w][k];
}
}
for(k=0;k<1000;k++)
{
for(w=0;w<100;w++)
{
tab[w][k]+=tab[w][k];
}
}
Gdy umieścimy te linie w kodzie jakiegoś programu i uruchomimy go to
ponownie nic nie zauważymy. Współczesne komputery osobiste są za szybkie aby coś zauważyć. Skoro nic nie widać, to powtórzmy ten fragment
kodu kilkanaście razy w pętli. Kilkanaście, czyli na przykład 5000 razy. A
powtarzając, zmierzmy czas potrzebny na wykonanie tych 5000 powtórzeń.
timestart();
for(p=0;p<5000;p++)
{
timestart();
for(p=0;p<5000;p++)
{
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
54
Obliczenia numeryczne
Real
6,610
6,130
6,150
6,130
6,120
6,140
6,120
6,130
6,120
6,150
Program 1
User System
6,570
0,000
6,090
0,000
6,110
0,000
6,100
0,000
6,100
0,000
6,110
0,000
6,090
0,000
6,100
0,000
6,090
0,000
6,110
0,000
Real
8,200
8,150
8,140
8,180
8,180
8,160
8,160
8,170
8,160
8,160
Program
User
8,140
8,130
8,130
8,150
8,150
8,140
8,140
8,150
8,140
8,140
2
System
0,000
0,000
0,010
0,000
0,000
0,000
0,000
0,000
0,000
0,000
Tablica 4.1. Czasy potrzebne na wykonanie programu 1 i programu 2.
for(w=0;w<100;w++)
{
for(k=0;k<1000;k++)
{
tab[w][k]+=tab[w][k];
}
}
}
timestop();
for(k=0;k<1000;k++)
{
for(w=0;w<100;w++)
{
tab[w][k]+=tab[w][k];
}
}
}
timestop();
W tabeli 4.1 przedstawiam część wyników jakie udało mi się zebrać (wszystkie otrzymane wyniki wyglądały podobnie) Uśredniony czas „User” (to on
informuje nas ile czasu procesora faktycznie zabrał nasz program) wynosi
dla programu 1: 6,15 s, natomiast dla programu 2: 8,14 s. Jak więc widać,
zależnie od tego, czy przebiegamy po tablicy wierszami czy kolumnami,
możemy zanotować 30% spowolnienie programu. Czary czy magia? Nie,
rzeczywistość. A rzeczywistość wygląda tak. . .
Język C (bo w nim ten test był robiony) ma to do siebie, że każda tablica
jednowymiarowa zajmuje ciągły obszar pamięci o rozmiarze odpowiednim
do wymiaru tablicy i typu danych w niej przechowywanych. Tak więc tablica taka zajmuje ilość_elementów * rozmiar_elementu_w_bajtach komórek pamięci. Każda tablica dwuwymiarowa, traktowana natomiast jest
jak tablica tablic. Tak więc tablica dwuwymiarowa tak naprawdę jest tablicą, której elementami są tablice. W naszym przypadku, skoro mamy
float tab[100][1000];, więc mamy tablicę 100 elementową, gdzie każdy
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
4.2 O tym co, jak i w czym liczymy
55
element jest z kolei tablicą 1000 elementową a każdy element tejże tablicy
jest liczbą rzeczywistą. Tak więc ta tablica dwuwymiarowa zajmie w pamięci 100*1000*rozmiar_float komórek pamięci. Co ważniejsze, pamięć
zostanie zapisana wierszami. Tak więc najpierw w pamięci będą umieszczone elementy zerowego1 wiersza naszej tabeli, potem pierwszego, drugiego
i tak aż do dziewięćdziesiątego dziewiątego. Dla tradycyjnego systemu komputerowego najlepszą sytuacją jest taka, gdy odczytuje kolejne elementy
z obszaru pamięci w jakim zapisano tablicę. Takie „liniowe zachowanie”
znacznie przyspiesza operacje związane z dostępem do pamięci, bo
• pamieć odczytywana jest blokami, czyli jednocześnie pobierane jest
kilka kolejnych komórek pamięci. Jeśli więc operujemy na kolejnych
komórkach, to taki odczyt konieczny jest tylko raz na jakiś czas.
• układom przewidującym, które obszary pamięci będą odczytywane w
przyszłości, łatwiej wykonać to zadanie gdy nie skoaczemy po niej w
losowy (z punktu widzenia ukłądu) sposób.
Drugi z przedstawionych fragmentów kodu zmusza procesor do skakania po
pamięci; oba te zachowania zostały przedstawione na rysunku ??.
Tak więc myśleć trzeba, ale i trzeba też wiedzieć. A nie pisząc samemu
nawet takich „głupawych” programów jak ten trudno sie czegoś dowiedzieć.
4.2
O tym co, jak i w czym liczymy
Jednym z lepiej znanych przykładów zadania którego lepiej przy pomocy rekurencji nie rozwiązywać jest ciąg Fibonnaciego. Definiujemy go w
następujący sposób: dla n > 1 mamy
f ibn = f ibn−1 + f ibn−2 ,
natomiast wyrazy 1. i 0. przyjmują wartość 1. Drzewo wywołań rekurencyjnych rozrasta się w tym przypadku bardzo szybko, stanowiąc doskonałe
uzasadnienie wyboru innych metod (np. iteracja). Przykład takiego drzewa
dla obliczania szóstego wyrazu zamieszczamy poniżej
FibR(5)
|
+--FibR(4)
1
Tablice w języku C indeksujemy poczynając od 0.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
56
Obliczenia numeryczne
|
|
|
+--FibR(3)
|
|
|
|
|
+--FibR(2)
|
|
|
|
|
|
|
+--FibR(1)
|
|
|
+--FibR(0)
|
|
|
|
|
+--Fib(1)
|
|
|
+--FibR(2)
|
|
|
+--FibR(1)
|
+--FibR(0)
+--FibR(3)
|
+--FibR(2)
|
|
|
+--FibR(1)
|
+--FibR(0)
|
+--FibR(1)
Pewnego dnia przygotowywując materiały na zajęcia postanowiłem pomierzyć zarówno czasy obliczeń jak i liczbę wywołań i otrzymane wartości dla
n = 0, . . . , 40. Jako, że był to czas, gdy pisałem trochę w Pythonie, zaimplementowałem całość w tym właśnie języku. I pewno nic by się nie stało,
gdyby nie fakt, że na Centrino Duo 1,66GHz otrzymałem wyniki o wiele
gorsze niż przed paroma laty na 486 DX4 120 MHz. Postanowiłem więc
lepiej przyjrzeć się innym językom i sposobom implementacji.
Ogólnie test przeprowadziłem w następujących środowiskach (biorąc pod
uwagę system operacyjny i komputer):
• komputer 486 DX 4 120 MHz, środowisko MS-DOS, język C (kolumna:
Czas 1);
• komputer Intel Centrino Duo T2300 1.66GHz 981 MHz, 0.99GB RAM,
środowisko Microsoft WindowsXP SP2,język C (kolumna: Czas 2 i 3);
• komputer Intel Centrino Duo T2300 1.66GHz 981 MHz, 0.99GB RAM,
środowisko Microsoft WindowsXP SP2,język Java (kolumna: Czas 4
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
4.2 O tym co, jak i w czym liczymy
57
i 5);
• komputer Intel Centrino Duo T2300 1.66GHz 981 MHz, 0.99GB RAM,
środowisko Microsoft WindowsXP SP2,język Python (kolumna: Czas
6 i 7);
• komputer Intel Centrino Duo T2300 1.66GHz 981 MHz, 0.99GB RAM,
środowisko Ubuntu Linux 7.04, język Java (kolumna: Czas 8 i 9).
• komputer Intel Centrino Duo T2300 1.66GHz 981 MHz, 0.99GB RAM,
środowisko Ubuntu Linux 7.04, język Python (kolumna: Czas 10 i 11).
Wszystkie parzyste czasy dotyczyły implementacji liczącej tylko wartość i
mierzącej czas obliczeń. Nieparzyste implementacje (z wyjątkiem pierwszej)
liczyły wartość wyrazu, liczbę wywołań oraz czas. Zanim przejdziemy do
prezentacji wyników jeszcze krótkie przedstawienie dwóch wersji programu
zaimplementowanego w Pythonie (wszystkie programy znajdują się w dodatku).
#wersja obliczajaca wartość wyrazu,
#ilość wywołań i czas
from time import *
def fib(n):
if (n==0 or n==1):
return {"wynik":1,"wywolanie":1};
res1=fib(n-1)
res2=fib(n-2)
v=res1["wynik"]+res2["wynik"]
c=res1["wywolanie"]+res2["wywolanie"]+1
return {"wynik":v,"wywolanie":c}
def FibCount(n):
start=clock()
v=fib(n)
stop=clock()
czas=stop-start
print "Wyraz dla n=",n," wynosi ",v["wynik"]," (wywolan: ",v["wywolanie"],", czas: "
for i in range(0,41,1):
FibCount(i)
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
58
Obliczenia numeryczne
#wersja obliczajaca wartość wyrazu i czas
from time import *
def fib(n):
if (n==0 or n==1):
return 1;
return fib(n-1)+fib(n-2)
def FibCount(n):
start=clock()
v=fib(n)
stop=clock()
czas=stop-start
print "Wyraz dla n=",n," wynosi ",v," czas: ",(czas),"s"
for i in range(0,41,1):
FibCount(i)
Wyniki:
OS/L
n
30
31
32
33
34
35
36
37
38
39
40
486
T1
2
2,56
3,54
5,10
7,11
12,67
18,84
29,40
48,12
75,82
>90,0
Win C
T2 T3
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
2
3
4
3
6
6
9
Win J
T4 T5
Win
T6
1,2
2,0
3,2
5,3
8,6
13,9
22,5
36,5
59,0
95,6
154,7
Pyt
T7
8,5
13,3
20,9
33,2
53,2
85,4
—
—
—
—
—
Lin J
T8
T9
0,018 0,225
0,028 0,359
0,046 0,577
0,076 0,929
0,121 1,502
0,19
2,43
0,304
3,90
0,49
6,327
0,791 10,209
1,273 16,572
2,066 26,822
Lin
T10
1,47
2,38
3,85
6,22
10,07
16,36
26,58
42,85
69,25
112,15
182,85
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Pyt
T11
3,78
5,96
9,64
15,63
25,57
41,08
66,43
107,09
173,78
280,43
454,27
Rozdział 5
Architektury równoległe
5.1
Podział
Obliczenia równoległe
5.2
Klasyfikacja architektur równoległych według
Flynna
Na nasze potrzeby, podobnie jak w [2], wprowadzimy pojęcie strumienia.
Strumieniem nazywać będziemy pewną sekwencję (ciąg) obiektów lub akcji. Obiektem mogą być np. dane a akcją instrukcje. Każdy strumień jest
niezależny od innych strumieni. Każdy element strumienia może składać się
z jednego lub więcej obiektu lub akcji. Mając sprecyzowane co rozumiemy
pod pojęciem strumienia, możemy teraz wyszczególnić cztery najbardziej
popularne architektury równoległe:
1. SISD (ang. single instruction stream, single data stream). Najprostszy przypadek, kiedy to zasadniczo nie mamy do czynienia z równoległościa. Odpowiada temu każdy „tradycyjny” procesor. Klasa ta
opisuje architektury typu von Neumanna, gdzie szeregowo (sekwencyjnie) pobierany jest pojedyńczy zestaw rozkazów operujących na
pojedynczych danych.
2. SIMD (ang. single instruction stream, multiple data stream). Systemy,
w których na podstawie pojedynczego strumienia rozkazów wykonuje
się jednocześnie operacje (te same rozkazy) na różnych danych; na
przykład procesory wektorowe.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
60
Architektury równoległe
3. MISD (ang. multiple instruction stream, single data stream). Sztucznie dodana klasa dla kompletności klasyfikacji; nie ma odpowiednich
przykładów takiej architektury.
4. MIMD (ang. multiple instruction stream, multiple data stream). Systemy wieloprocesorowe, w których co najmniej dwa procesory wykonują oddzielne strumienie rozkazów operujące na różnych danych.
Przyjrzymy się teraz bliżej tym czterem klasom.
5.2.1
SISD
Jest to najbardziej rozpowszechniona klasa procesorów, w której zasadniczo nie mamy do czynienia z równoległością. Równoległość w tych
procesorach występuje pod postacią przetwarzania potokowego rozkazów
(instrukcji). Zasadniczą ideą jest przedstawienie cyklu wykonania każdego
rozkazu jako ciągu niezależnych mikrooperacji. Przyjrzyjmy się poniższemu przykładowi
W procesorach typu SISD nie uzyskujemy równoległości wykonania (tj.
nie mamy do czynienia z równoległym wykonaniem kilku akcji), ale równoległość przetwarzania. Największą przeszkodę w efektywnym przetwarzaniu
potokowym stanowią instrukcje skoku. Przyjrzyjmy się poniższemu przykładowi
5.2.2
SIMD
Wyobraźmy sobie, że mamy do dodania dwa 10-cio elementowe wektory
złożone z liczb rzeczywistych
a = [a1 , . . . , a10 ]
b = [b1 , . . . , b10 ]
a wynik będziemy przechowywać w wektorze
c = [c1 , . . . , c10 ].
Naturalny jest następujący sposobem zapisu takiego działania
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
5.3 Klasyfikacja architektur równoległych według Duncana
5.2.3
61
MIMD
Systemy typu MIMD składają się z wielu jednostek przetwarzających
działających niezależnie od pozostałych. Pozwala to na wykonywanie różnych zestawów instrukcji na różnych danych w tym samym czasie. Jest to
najbardziej różnorodna spośród wszystkich kategorii Flynna. Obejmuje bowiem zarówno maszyny złożone z wielu procesorów i niezależnych ukłądów
pamięci specjalnie zaprojektowanych do przetwarzania równoległego jak i
sieć stacji roboczych połączonych siecią lokalną. Rozwijająca się wciąż komunikacja sieciowa wsparta rozwojem oprogramowania pozwalającego na
zdalne wykonywanie procedur i programów (np. RPC - ang. remote procedure call, PVM - ang. parallel virtual machine) a także języków, które w
znacznej mierze ułatwiają pisanie aplikacji rozproszonych i wielowątkowych
(np. Ada), pozwalają niejednokrotnie traktować zespół, nawet jednoprocesorowych a więc typu SISD, stacji roboczych jako system typu MIMD.
Zauważmy, że do tej kategori zaliczymy zarówno maszynę dwuprocesorową
w której każdy procesor wykonuje w tym samym czasie inny program jak
i maszynę, w której w tym samym czasie dwa procesory wykonują różne
instrukcje tego samego programu. W pierwszym przypadku mówimy o paraleriźmie (równoległości) na poziomie zadan (ang. job level parallelism) w
drugim zaś (niewątpliwie dużo bardziej złożonym) o paraleriźmie na poziomie instrukcji tego samego programu (ang. instruction level parallelism).
5.3
Klasyfikacja architektur równoległych według
Duncana
Niestety schemat klasyfikacji przedstawiony w rozdziale 5.2 nie uwzględnia najnowszych dokonań w dziedzinie architektur równoległych. Klasyfikacja Duncana [1] została opracowana jako próba objęcia erchitektur nie
mieszczących sie w podziale Flynna a także w celu wyłączenia architektur
będących w zasadzie szeregowymi, ale wykorzystujących niskopoziomowe
mechanizmy równoległe. Podział Duncana zachowuje częściowo terminologię Flynna i wprowadza rozróżnienie architektur wykonujących operacje
synchronicznie i asynchronicznie. Poniżej przedstawiamy klasyfikację zaproponowaną przez Duncana:
1. Synchroniczne
(a) Wektorowe
(b) SIMD
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
62
Architektury równoległe
i. Macierze procesorów
ii. Pamięć asocjacyjna
(c) Systoliczne
2. MIMD
(a) Pamięć rozproszona
(b) Pamięć wspólna
3. Paradygmat MIMD
(a) MIMD/SIMD
(b) Przepływ danych
(c) Redukcja
(d) Czoło fali
Poniżej opiszemy te z kategorii, których znaczenie nie jest intuicyjnie
jasne lub odbiega od znaczenia nadanego przez taksonomie Flynn’a.
5.3.1
Wektorowe
Znaczenie ”wektorowa”w odniesieniu do maszyny, przy wykorzystywaniu taksonomi Duncana jest odmienne od znaczenia ”wektorowyńadanego
przez taksonomię Flynn’a przy opisie architektury typu SIMD. Otóż procesor wektorowy (ang. vector processors), składa się wielu, połączonych
w potok i działających równolegle jednostek funkcjonalnych odpowiedzialnych za wykonanie operacji arytmetyczno-logicznej zarówno na skalarach
jak i wektorach. Realizacja postulatu równoległości w tych procesorach
odbywa się przez równoległą (jednoczesną) pracę jednostek funkcjonalnych
przetwarzających sekwencyjnie kolejne elementy wektora. Zrozumienie tej
idei ułatwić może rysunek ??. Hmmm... Wątpliwa równoległość :)
5.3.2
SIMD
W taksonomi Duncana architektura typu SIMD, której ideę przedstawiono w podrozdziale 5.2.2 dzielona jest na dwie podkategorie: macierze
procesorów (ang. processor array architectures) oraz pamięć asosjacyjna
(ang. associative memory prosessor architectures).
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
5.3 Klasyfikacja architektur równoległych według Duncana
5.3.3
63
Systoliczne
Architektura systoliczna1 (ang. systolic architectures) zaproponowna została na początku lat ’80 przez H. T. Kunga z Carnegie Mellon University i
miała być rozwiązaniem dla systemów, które muszą dzielić swoją wydajność
pomiędzy obliczenia i liczne operacje wejścia-wyjścia. W systemach systolicznych dane przepływają z pamięci komputera w sposób rytmiczny: po
pobraniu z pamięci dane przechodzą przez wiele elementów przetwarzania
zanim trafią z powrotem do pamięci – podobnie jak krew krążąca w układzie
krwionośnym wypływając i wpływając do serca.
Each processor at each step takes in data from one or more neighbours
(e.g. North and West), processes it and, in the next step, outputs results in
the opposite direction (South and East).
An example of a systolic algorithm might be matrix multiplication. One
matrix is fed in a row at a time from the top of the array and is passed
down the array, the other matrix is fed in a column at a time from the left
hand side of the array and passes from left to right. Dummy values are
then passed in until each processor has seen one whole row and one whole
column. At this point, the result of the multiplication is stored in the array
and can now be output a row or a column at a time, flowing down or across
the array.
5.3.4
MIMD z pamięcią rozproszoną
Zwyczajnie: MIMD, który ma pamięć rozproszoną.
5.3.5
MIMD z pamięcią wspólną
Zwyczajnie: MIMD, który ma pamięć wspólną.
5.3.6
MIMD/SIMD
5.3.7
Przepływ danych
Non-Uniform Memory Access and Non-Uniform Memory Architecture
(NUMA) is a computer memory design used in multiprocessors, where the
memory access time depends on the memory location relative to a processor.
1
Termin systoliczny zapożyczony zapewne został z medycyny, gdzie oznacza skurczowy.
Oznacza ciśnienie krwi jakie osiągane jset podczas skurczu serca. Chyba, bo ja tam słaby
z medycyny jestem :)
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
64
Architektury równoległe
Under NUMA, a processor can access its own local memory faster than nonlocal memory, that is, memory local to another processor or memory shared
between processors.
Symmetric Multiprocessing, or SMP, is a multiprocessor computer architecture where two or more identical processors are connected to a single
shared main memory. Most common multiprocessor systems today use an
SMP architecture.
SMP systems allow any processor to work on any task no matter where
the data for that task is located in memory; with proper operating system
support, SMP systems can easily move tasks between processors to balance
the workload efficiently. On the downside, memory is much slower than
the processors accessing them, and even single-processor machines tend to
spend a considerable amount of time waiting for data to arrive from memory.
SMP makes this worse, as only one processor can access memory at a time;
it is possible for several processors to be starved.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Rozdział 6
Errata
Rozdział ten zawiera poprawki i pewne dodatki związane z [3].
6.1
Poprawki
Zapis: s. 123, w. 12 g (d) oznacza: strona 123 wiersz 12 od góry (dołu).
• s. 7, w. 9 d
jest: nie tyle powodu
powinno być: nie tyle z powodu
• s. 10, w. 12 g
jest: dalszych informacji wymienionych w pozycjach bibliografii
powinno być: dalszych informacji w wymienionych pozycjach bibliografii
• s. 41, przykład 2.1
jest:
w = ...
(2.9,2.7)
=
(x + x0)(x + z)
(2.14,2.7)
=
...
powinno być:
w = ...
(2.9,2.7)
=
(x + x + 0)(x + z)
(2.14,2.7)
=
...
• s. 65, w. 4 g
jest: (Q ∪ {k, t, n} × Σ)
powinno być: (Q ∪ {k, t, n}) × Σ
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
66
Errata
• s. 71, w. 4 d
jest: mikroprocesory
powinno być: mikrokontrolery
• s. 76, rozdział 3.4
jest: opis nie jest wystarczająco precyzyjny i nie odpowiada rysunkowi
powinno być: proponujemy zdanie: „ Zasadniczo w procesorze 8086
wyróżnia się . . . .” zastąpić zdaniem: „Zasadniczo w procesorze 8086
wyróżnia się dwa główne elementy: układ wykonawczy i układ sterowania magistrali.”. Ponadto przy opisie elementów składowych układu
wykonawczego dodać:
EU – jednostka wykonawcza (ang. execution unit), odpowiada za
wykonanie rozkazu;
• s. 106, 3 wiersz tabeli przejść z zadania 6 a) w kolumnie: kierunek
ruchu głowicy
jest: →
powinno być: ←
• s. 127, w. 7 d
jest: odwołanie od konkretnego
powinno być: odwołanie do konkretnego
• s. 132, źle sformatowany pseudokod instrukcji pętli do-while i while
powinno być:
do
begin
... ciąg instrukcji powtarzanych
dopóki warunek jest spełniony
end
while(warunek)
while(warunek)
begin
... ciąg instrukcji powtarzanych
dopóki warunek jest spełniony
end
• s. 143, przykład 5.6 powinno być:
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
6.2 Uzupełnienie literatury
67
fib_r (n)
begin
if (n=1) then
begin
fib_r := 1;
end
if (n=0) then
begin
fib_r := 1;
end
w := fib_r(n-1)+fib_r(n-2);
fib_r := w;
end
• s. 246, odpowiedzi do zadania 8 dla podpunktów a), b), e), f) oraz j)
powinny być następujące:
a)
b)
e)
f)
j)
6.2
C99
2A5
3BC
910
40C
→
→
→
→
→
2853
575
815
2084
844
Uzupełnienie literatury
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
68
Errata
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007
Bibliografia
[1] R.A. Duncan, Survey of Parallel Computer Architectures, IEEE Computer, vol. 23, no. 2, February 1990, s. 5-16.
[2] Michael J. Flynn, Kevin W. Rudd, Parallel Architectures, In ACM
Computer Surveys, March 1996 (materiały znalezione w Internecie).
[3] Piotr Fulmański, Ścibór Sobieski, Wstęp do informatyki. Podręcznik,
Wydawnictwo UŁ, 2005.
[4] H.-O. Peitgen, H. Jurgens, D. Saupe, Granice haosu. Fraktale, tom I,
Wydawnictwo Naukowe PWN, Warszawa, 1997.
[5] Cezary Zieliński, Podstawy projektowania układów cyfrowych, Wydawnictwo Naukowe PWN, Warszawa, 2003.
c
2005
– 2006 by P. Fulmański, Uniwersytet Łódzki. Wersja 0.1 z dnia: 30 listopada 2007

Podobne dokumenty