Pro pochopeni teto skolicky je nutne znat
zaklady lispu, zaklady common lispu a navrh Connection machine.
Vic informaci najdete
take na Thinking machines homepage
(budu se tu drzet skvele knizky the connection machine od Hillise kterou v ceske verzi vydala grada. Kazdemu ji doporucuju)
Takze CM lisp je lisp upraveny tak aby svoji strukturou se co nejvice podobal hardwaru cm. Jako normalni lisp odpovida normalnimu hardwaru. Jak pise Hillis:"CmLisp je rozsireni Common Lispu, navrzene pro podporu paralelnich operaci na pocitaci CM. Ma byt pro pocitac CM tim, cim je lisp pro seriovy pocitac: vyrazem podstatnych rysu architektury, ktera vypousti detaily implementace. Cmlisp je abstraktni verzi pocitace CM ve stejnem smyslu, jako jsou fortran nebo lisp abstraktimi verzemy konvencniho pocitace" Cm lisp je konzervativni paralelni jazyk. Stejne jako clos je konzervativni objektovy jazyk-spojuje vyhody struktorovaneho a objektoveho jazyka narozdil treba od smalltalku. Tak i cmlisp spojuje vyhody sekvencniho a paralelniho programovani-to vychazi z toho ze cm je rizena klasickym nadrazenym pocitacem takze cast toho programu je interpretrovana rovnou na tom pocitaci a cast na cm. Pro takovy nekonzervativny jazyk si prostudujte dokumentaci APL nebo FP. Je ale zvlastni ze programy v cmlispu se pisou snadneji a jsou vykonejsy nez programy psane v APL.
Proc lisp?
Byly dva duvody: prvni ze cm byl vyvinut pro cleny komunity umele
inteligence kde vsichni uz lisp znali protoze lisp byl vyvinut pro ne.
Ten druhy dulezitejsi je protoze lisp je rozsiritelny, ma dynamickou
alokaci pameti a je vseobecne dobry pro symbolicke manipulace. A
existuji programova prostredi pro lisp. Vetsina myslenek je na lispu
nezvyslych a proto byly pozdeji vyvinuty i dalsi jazyky: C* lisp* a
fortran*. Lisp* je uz trochu brutalnejsi rozsireni lispu ktere se
poucilo z nekolika nedostatku cmlispu. A to ze cmlisp pouzival znaky
mimo asci kod-alpha beta a puntik. Ale vzdasade je to to samy pouze
umoznije nektere figly jako pametove indukovane site. Ostatni jazyky
jako C* jsou upravami klasickych jazyku ale nedopadly moc dobre. Proto
se stejne vesele pouziva lisp.
Xektory
Protoze nadrazeny pocitac je ten co provadi program pouze obcas si
nejaka data odhodi do pocitace cm kde snima neco robi je jasne ze je
treba nejaky typ pomoci neho by se dalo do cm ukladat. Kdyz se koukneme
na cm je to vlastne fura procesoru kde kazdy ma vsobe jeden objekt a ty
se muzou navzajem propojovat a shlukovat se do nejakych mnozin. Od toho
byl vytvoren typ xektor. Vsechna data ulozena v xektoru jsou v cm. Takze
se nad nimi daji provedet paralelni operace jako ruct sectete se nebo
najdete mi ahoj. Samozdrejme ze by to slo delat i na normalnim pocitaci
ale bylo by to pomaly. Xektor tedy muze obsahovat mnozinu objektu. Ale
navic umi zaznamenat spoje mezi nima. Xektor se zapisuje takto:
{SKY->BLUE GRASS->GREEN APPLE->RED}Takze je tu mnozina prcku ulozenych v cm a xektor udava mezi nima spoje neboli asociace. Xektor trochu pripomina asociovane pole nebo hasovaci tabulku. Ma mnozinu indexu-SKY,GRASS,RED ty se rika jako u funkci definicni obor(domain). Ma take monzinu prvku - obor hodnot(range) a zobrazeni mezi nimi.
Xektor nema dane poradi prvku. takze se muze vypisovat prehazene. Na pocitaci CM je kazdy prvek ve zvlastim procesoru a indexem je adresa jineho procesoru. Xektor ma i jine zapisy:
{A->A 1->1 2->2} je stejne jako {A 1 2} Take lze psat jako pole: {0->A 1->B 2->C 3->D} je [A B C D] Taky tu je konstantni xektor co vsechno zobrazuje do jedne hodnoty {->2}
(SETQ COLOR-OF '{SKY->BLUE APPLE->RED GRASS->GREEN}) => {APPLE->RED GRASS->GREEN SKY->BLUE}Vypisovani xektoru je vzdy nejak usporadano-abecedne,rostouci cisla apod. Funkci xref muzeme zjistovat hodnoty indecu:
(XREF COLOR-OF `APPLE) => REDStejne muzeme hodnoty nastavovat XSETEM
(XSET `BLUE COLOR-OF `GRASS) COLOR-OF => {APPLE->RED GRASS->BLUE SKY->BLUE}XSET nepridava novy index to se dela funkxi XMOD. Protoze xektory jsou vlastne funkce cmlisp snimi tak umi pracovat treba delat inverzni xektory. Ma tedy funkce RANGE co vybere jen indexy,DOMAIN co vybere prvky a INVERZE co xektor obrati. Taky samozdrejme umi prevadet xektory do listu, asociovanych listu apod. Dale je umi brat jako sekvence a delat nad nima bezne operace jako nad polema,alisty,listy a hasovacima tabulkama tedy treba search a delete. Ty ale probihaji paralelne takze jsou rychlejsi:
Tabulka casovych zavislosti: Operace Vektor List Xektor ELT 1 N 1 LENGTH 1 N logN SUBSEQ 1 N logN COPY-SEQ N N 1 FILL N N 1 REMOVE N N 1 DELETE N N 1 REPLACE N N logN COUNT N N logN REVERSE N N logN POSITION N N 1 REDUCE N N logN SORT NlogN NlogN logN*logN SEARCH N N 1tady vydite ze mimo sortu jsou slozitosti bud 1 nebo logn. Ty co maj 1 jsou jednoduche-proste vsechny prvky udelaji nejakou operaci-treba se vynuluji u fill. LogN spociva vtom ze treba kdyz vsechny chceme secist secteme nejprve vsechny dvojice tim vznikne N/2 vysledku ty po dvojicich taky secteme. Tedy jedeme po binarnim strome a cosova slozitost se rovna hloubka stromu je dvojkovy logaritmus tedy 65536 cisel mame secteno na 16ti scitanich. To je fofr co? Trideni je slozitejsi mozna ho taky popisu.
Jak se takove funkce delaji? verte nebo ne pomoci dvou hloupych operatoru:
Alfa notace
No a uz zacneme paralelnit. Alfa notace je to co umoznije psat operace co
maji slozitost 1 tedy vsichni udelame to a to. Cmlisp alpha pise jako
recke pismeno a pouziva ji asi jako lisp ' tedy misto aby se psalo
(alpha 1) napise se recka alpha 1. To tu psat nemuzu takze misto neho
budu psat A a kdyz by se to pletlo tak pekne alpha. Alpha se pouziva na
konverzi hodnoty na konstantni xektor tedy A1 je {->1} kdyz je alpha pred
vyrazem vyraz se vyhodnoti a potom se zneho udela konstantni xektor.
A3 => {->3} A(+ 1 2) => {->3} A+ => {->+}Tim se moc paralelizmu neudela a tak je tu figl. Kdyz na miste funkce je xektor funkce tedy A+ misto + je pri vyhodnocovani paralelne funkce mapovana na jednotlive indexy xektoru:
(A+ '{a->1 b->2} '{a->3 b->3} provedou se paralelne dva vypocty a vyjde: {a->4 b->5}Jak vidite pomoci alpha notace jsou udelat vsechny funkce tabulky co maji casovou slozitost 1. Alpha ma zajimave vlastnosti. Da se hodit pred vyraz: A(+ 1 2) je stejne (A+ A1 A2)
Vzdycky vyjde {->3}. Tohle vytykani nam ale vetsinou blokujou xektory pred ktery se alpha nepise. Proto lisp ma dalsi znak-puntik co alphu rusi-stejne jako ` a , u maker. Puntik budu psat jako < > priklady:
A(+ < > x 1) je (A+ x A1) Kdyz a je xektor [a b c] a X je [x y z] pak: (CONS A X) => ([a b c] . [x y z]) A(CONS < > A < > X) => [(a.x) (b.y) (c.z)]Muzeme ale provedst i ruzny operace na ruznych indexech:
(FUNCALL '[+ - - +] '[1 2 3 4] A1) => [ 2 1 2 5 ]A to uz je peknej paralelizmus.
(B+ `{A->1 B->2 C->3}) => 6 (Band `[T T NIL T]) => NILA takhle jde zjistit delka xektoru:
(DEFUN DELKA (x) (B+ A(PROG2 < > X 1))nebo:
(DEFUN VELIKOST (x) (SQRT (B+ (a* x x)))) (DEFUN VSE-SHODNE (x y) (Band (A= x y))tedy treba vse-schodne nejpre pomoci alphy udela novy xektor ktery bude obsahovat true na ntem miste kdyz n.prvek x bude shodny z n.prvkem y. No a potom uz jenom zbyva zjistit jestli je tam nekde false-tose udela pomoci bety a and.
Muzeme betu pouzit i na konstrukci nevoho xektoru z oboru hodnot a definicniho oboru:
(B `(a->1 b->2) `{a->x b->y}) {x->1 y->2}To se zda trochu odlisne ale je to to samy hned vysvetlim proc: Beta je trochu obecnejsi. Ona vlastne beta presne odpovida smerovacum zprav (stejne jako alpha odpovida procesorum). Pomoci bety toho udelate opravdu hodne.
Zobecnena beta ma tri parametry: slucovaci funkci a dva xektory. Beta je zkombinuje jak jsme uz rikaly. Veme hodnoty prvniho xektoru a udela znich indexy pro hodnoty druheho xektoru a vrati vznikly xektor tedy vlastne predratuje spoje. To se provede v jednotkovem case. Slucovaci funkce rika jak resit kolize-tedy kdyz v prnim xektoru jsou dve nebo vice stejnych hodnot musi se hodnoty z druheho xektoru nejak zkombinovat. To dela slucovaci funkce. Kdyz zadnou slucovaci funkci nedate kolize hlasi chybu:
(B '[1 2 5] '[x y z]) => {x->1 y->2 z->5} (B '[1 2 5] '[x z z]) => errorA se slucovaci funkci:
(B+ '[1 2 5] '[x z z]) => {X->1 Z->5}Kdybychom chteli secist vsechny prvky xektoru udelame:
(B+ '[1 2 5] '{->3}) => {3->8}Muzem ale druhy xektor vynechat a potom je vysledek normalni hodnota. A je to ta situace co byla popsana na zacatku. Tady je priklad inverze xektoru:
(DEFUN INVERZE (X) (B (DOMAIN X) X))
(DEFSTRUCT (PIXEL :CM) RED GREEN BLUE)Kazdy pixel ma pak svuj vlastni procesor. Tedy misto do vektoru da strukturu do xektoru.
(DEFSTRUCT (VERTEX :CM) LABEL NEIGHBORS)LABEL je hodnota a NEIGHBORS je xektor z cestama.
A ted algoritmus:
(DEFUN DELKA_CESTY (a b g) A(SETF (LABEL < > g) +INF) ; provede bod 1 tedy nastavi vsechny labely na +INF tedy nekonecno (SETF (LABEL a) 0 ;bod a na nula (LOOP UNTIL (> < (LABEL b) +INF) ;opakuj dokud label od becka je +INF DO A(SETF (LABEL > < (REMOVE A G)) ;pro vsechny labely v G mimo bodu A (1+ (Bmin A(LABEL < > NEIGHBORS < > G)))))) ;najdi minimum a zvec o 1 (LABEL B)) ;navratova hodnota.Jediny co je trochu zmatenejsi je treti radek tedy ten cyklus. Ten je proveden k krat. Kde k je delka. Pro graf z 10 na 4 vrcholy a 10 na 6 hranami je k priblizne 3. Cyklud se ukonci a bod b bude neco jinyho nez + inf. V tele smycky je kazdy vrchol krome A=to dela to REMOVE A G tedy vytvori v case 1 novy xektor co uz neobsahuje bod A. Pro vsechny tyto vrcholy se pomoci alphy provede vyhledani minima-pomoci bety a zvetseni o jedna. Ohodnoceni bodu a zustane 0 protoze ten se nemeni. zmateny je tu jenom vyber minima:
(Bmin A(LABEL < > (NEIGHBORS V)))Sousedi vrcholu V jsou xektor vrcholu a alpha je pouzita pro vyber hodnot operaci label. Tim vznikne xektor co bude obsahovat ohodnoceni. Ten se zredukuje pomoci bety(Bmin) a najde se minimum. V programu je to navic komplikovanejsi tim ze je to aplikovano na xektor vrcholu tedy pomoci alpha na vsechny vrcholy grafu soucasne.
To je zahul co? ale pritom je to jednoduchy :) Tady je videt jak
v lispu jde psat primocare a strucne i kdyz to vypada strasne.
Ted si zpocitejte kolik radek by to melo v cecku
Aktivni datove struktury
To je hlavni vec se kterou v cm pracujeme. Jako na normalnim pocitaci
mame datove struktory-polem,listy a pracujeme snima mame i na cm
struktury ale praci si delaji samy. Takze mame-li mnozinu dat a chceme
aby neco udelaly udelame nad nima datovou strukturu a ty to reknem.
Zakladni tyto struktury jsou:mnoziny,stromy,grafy,pole,stringy, site
typu motyl. Avzdycky si z prvku nejprve sestavi smravnou strukturu co
odpovida problemu:mnozinu kdyz chceme neco provest z kazdym prvkem-alpha
a xektory. Stromy kdyz chceme redukovat- hledat minimum,scitat apod-beta.
Grafy se hodi ne ruzne neuronove site prace snima byla uz ukazana. Motyl
se hodi na trideni. Problem aktivnich datovych struktur je moc zajimavy.
Vsechny tyto struktory se daji udelat xektorama a tedy da se snima pracovat
v cm lispu. Jsou na to moc zajimavy algoritmy ale neveslo by se to sem.
Vpodstate jakekoliv propojeni bunek se take da reprezentovat pomoci
xektorovych poli a bety. Treba takovy graf:
1---2 \ / 5 / \ 3 4se da udelat:
[1 2 2 3 4 a dale obracene pro dvousmerne cesty5 5 1 5 5 ] [5 5 1 5 5 1 2 2 3 4 ] A pomoci bety potom muzeme secist vsechny prvky kolem uzlu (B+ a b)kde a je prvni xektor a b je druhy xektor. A je to rychlejsi nez zapis v predeslem algoritmu. Samozdrejme ze takove xektory jdou velmi rychle nad daty vytvorit a zase je zrusit-treba nad polem je vytvaret podle adres to jsou adresove indukovane struktury. Je to proste svanda.
zaver
Jak je videt lisp zase prosel. Nebyly treba skoro zadne upravy-jeden
datovy typ a dva operatory pro praci snim. A lisp je paralelni.
Pridelani neceho takoveho do cecka je utrpeni. Dejme tomu ze jestli je
objekt ulozen normalne nebo v cm staci pridelat parametr promene neco
jako extern tak cm. Vetsi problem je to ze funkce(treba min) se obcas
provadi na ridicim pocitaci a obcas uvnitr cm. A pokazde je treba jiny
kod. Dalsi problem je vlastni prepis alpha a beto notace do cecka. To
je diky celkem hloupemu ceckarskemu volani funkci skoro nemozne. Taky u
definice funkce se pokazdy musi rict jestli ma byt kompilovana pro cm
nebo ridici pocotac. Dejme tomu ze by cecko melo nejakou funkci beta co
by se volala z dvema xektorama a stejnou funkci alpha potom prepis:
(Bmin A(LABEL < > (NEIGHBORS V)))by vypadal nejak
beta(min,alpha(labela,v.neighbors))Ale to by nestacilo muselo by se udelat funkce min co vezme minimum labela co vezme label z neighborsu takze by tu byly dalsi dve funkce apod. Knihovni funkce by musely byt dvakrat-jednou pro ridici a jednou pro cm. Proste rozhodne by se to neveslo do 10 radek a byl by to strasne slozity a neprehledny program. Rozhodne by nebyl o nic citelnejsi nez ten lispackej. Je prevda ze c* ma nekolik zajimavych konstrukci ktere jsou ale v cmlispu naprosto zbytecne. Treba ma shape kterym se daji usporadat paralelni data do n rozmerne mrizky.
shape[20][30][40] sDeklaruje mrizku. deklarace takove paralelni promene X co bude mit prvky typu t se dela:
t:s x;Ale vidite jak je to omezene? chceme dat prvky do stromu a potrebujeme dalsi jazykovy prostredek a takovych siti je neomezene mnoho! A vsechny ty site jdou udelat pomoci dvou xektoru!
Tento soubor je soucasti rozsahle sbirky skolicek na http://www.ucw.cz/~hubicka/skolicky
Take si muzete prohlidnout jeji puvodni textovou podobu
Nebo mi mailnout na hubicka@ucw.cz
Copyright (C) Jan Hubicka 1995