<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta>
      <journal-title-group>
        <journal-title>Series</journal-title>
      </journal-title-group>
      <issn pub-type="ppub">1613-0073</issn>
    </journal-meta>
    <article-meta>
      <title-group>
        <article-title>Bobolang - jazyk pro systém Bobox</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Zbyneˇk Falt</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Martin Kruliš</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Jakub Yaghob</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Univerzita Karlova</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Praha</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Cˇeská republika</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>krulis</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>yaghob}@ksi.mff.cuni.cz</string-name>
        </contrib>
      </contrib-group>
      <pub-date>
        <year>2013</year>
      </pub-date>
      <volume>1003</volume>
      <fpage>75</fpage>
      <lpage>81</lpage>
      <abstract>
        <p>Abstrakt: Paralelní zpracování dat je v soucˇasné dobeˇ velmi aktuální téma. Jeden z používaných postup˚u je prˇevod vstupních dat na datové proudy a zpracování teˇchto proud˚u pomocí operátor˚u, které mohou být vyhodnocovány paralelneˇ. Protože pro specifikaci vzájemného propojení operátor˚u jsou beˇžné programovací jazyky nevhodné, vznikla pro tento úcˇel celá rˇada doménoveˇ specifických jazyk˚u. Jazyk Bobolang je jedním z nich. Kromeˇ beˇžných vlastností, ale prˇidává navíc neˇkteré syntaktické a sémantické prvky, které znacˇneˇ usnadnˇují intra-operátorovou paralelizaci. Díky tomu je možné snadno vytvárˇet vysoce škálovatelné aplikace zpracovávající proudová data. Paralelní systémy jsou v dnešní dobeˇ témeˇrˇ standardem. Z tohoto d˚uvodu se neustále hledají nové cesty jak co nejefektivneˇji využít tyto prostrˇedky. Bohužel, vývoj paralelních aplikací je nárocˇný a náchylný k chybám. Proto vznikají r˚uzné knihovny, nástroje, systémy a metody, jak tuto cˇinnost maximálneˇ usnadnit a zefektivnit. Neˇkteré tyto nástroje se snaží být co nejobecneˇjší, tzn. programátorovi pomáhají s vytvárˇením a synchronizací vláken [5], neˇkteré poskytují množství knihovních funkcí pro snazší paralelizaci neˇkterých typ˚u algoritm˚u [19], eˇnkteré rozšiˇrují samotný jazyk o direktivy urcˇené pro snazší vývoj [7]. Kromeˇ toho existují doménoveˇ specifické nástroje, které jsou urcˇeny pro konkrétní druhy aplikací. Systémy pro zpracování proudových dat jsou jedním z nich [20, 18, 21, 8, 4, 17, 2]. Tyto systémy pracují s tzv. datovými proudy, tj. v podstateˇ s posloupnostmi n-tic. Tyto proudy jsou pr˚ubeˇžneˇ (tj. tak jak n-tice prˇichází) zpracovávány operátory, které transformují vstupní proudy na výstupní. Vývoj aplikací pro takové systémy se skládá ze dvou fází:</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>1. Implementace potrˇebné množiny operátor˚u, tj. jak
prˇetransformovat vstupní proud/proudy na výstupní
proud/proudy.
2. Vytvorˇení exekucˇního plánu, tj. pospojování
operátor˚u orientovanými hranami, které urcˇují datové
proudy mezi nimi.</p>
      <p>Zatímco implementaci operátor˚u lze provést v témeˇrˇ
libovolném beˇžném programovacím jazyku (C/C++, Java,</p>
      <p>C# apod.), pro specifikaci exekucˇního plánu se tyto
jazyky prˇíliš nehodí. Exekucˇní plán totiž odpovídá
orientovanému grafu, tj. je zadán seznamem vrchol˚u a hran. To
sice lze snadno vyjádrˇit v beˇžných programovacích
jazycích, ale takový kód je obtížneˇ cˇitelný a modifikovatelný.
Proto vznikají jazyky, které vytvárˇení exekucˇního plánu
usnadnˇují, at’ už speciální syntaxí, nebo grafickou
vizualizací plánu.</p>
      <p>Bobolang se zameˇrˇuje na druhou fázi vývoje. Kromeˇ
cˇitelné syntaxe se ale snaží i o pomoc prˇi intra-operátorové
paralelizaci, kdy provádí neˇkteré transformace zvyšující
paralelismus exekucˇního plánu automaticky. Tím se
odlišuje od ostatních podobných jazyk˚u.</p>
      <p>Zbytek cˇlánku je rozdeˇlen následovneˇ: Kapitola 2
prˇedstavuje používané jazyky urcˇené pro systémy
zpracování proudových dat, kapitola 3 popisuje systém Bobox,
pro který vznikla pilotní implementace jazyka Bobolang.
V kapitole 4 rozebíráme možnosti a postupy paralelizace
operátor˚u. Strucˇný popis jazyku Bobolang je uveden v
kapitole 5 a neˇkolik prˇíklad˚u jeho použití uvádíme v
kapitole 6. Celý cˇlánek pak shrnujeme v kapitole 7.</p>
    </sec>
    <sec id="sec-2">
      <title>2 Související práce</title>
      <p>Soucˇasné jazyky zameˇrˇující se na proudové zpracování dat
se dají rozdeˇlit do neˇkolika skupin podle jejich zameˇrˇení.</p>
      <p>
        Brook [
        <xref ref-type="bibr" rid="ref3 ref4">3, 4</xref>
        ], StreaMIT [
        <xref ref-type="bibr" rid="ref20">20</xref>
        ] a StreamC [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ] se zameˇrˇují
na vývoj vysoce výkonných aplikací pracujících prˇevážneˇ
s multimediální daty (kodeky, filtry, transformace apod.).
Tyto jazyky jsou založeny na syntaxi jazyka C/C++ a
pokrývají jak fázi implementace jednotlivých operátor˚u, tak
jejich vzájemné propojení ve výsledné aplikaci.
Prˇekladacˇe teˇchto jazyk˚u provádeˇjí neˇkteré optimalizace, které
zvyšují výkon nebo nebo mapují operátory na urcˇité
výpocˇetní jednotky systému (CPU, GPU, FPGA1).
      </p>
      <p>
        Lucid [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] je další jazyk urcˇený pro programování
proudových aplikací. Tento jazyk sám o sobeˇ není urcˇen
pro paralelní aplikace, proto vznikl jazyk Granular Lucid
(GLU) [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ], který umožnˇuje do plánu zarˇadit operátory
implementované v jazyku C, které mohou být poušteˇny
paralelneˇ.
      </p>
      <p>
        Jazyk X-Language [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ] je moderní jazyk vyvinutý pro
systém Auto-Pipe [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ]. Tento jazyk slouží pro vzájemné
propojení již prˇipravených operátor˚u. Svým charakterem
je tedy podobný jazyku GLU, ale propojení operátor˚u
1Field-programmable gate array
vyjádrˇeno explicitneˇji (syntaxe je podobná jazyku
Bobolang). Podporuje rovneˇž vytvárˇení operátor˚u z již
existujících operátor˚u. Na rozdíl od Bobolangu ale nedochází
k automatické modifikaci plánu za úcˇelem zvýšení
paralelismu.
3
      </p>
    </sec>
    <sec id="sec-3">
      <title>Bobox</title>
      <p>Systém Bobox je jedna z implementací systému pro
zpracování proudových dat. Bobox poskytuje beˇhové prostrˇedí
pro vyhodnocování exekucˇních plán˚u v paralelním
prostrˇedí. Systém podporuje jak acyklické exekucˇní plány, tak
i plány obsahující cykly. Protože jazyk Bobolang je
navržen práveˇ pro Bobox a využívá neˇkteré jeho vlastnosti,
uvádíme v této kapitole neˇkteré technické detaily tohoto
systému.</p>
      <p>Datové proudy v Boboxu jsou reprezentované jako
proud tzv. datových obálek. Každá obálka obsahuje
seznam tzv. datový sloupc˚u. Tyto datové sloupce obsahují
samotná data. Každý sloupec musí obsahovat data pouze
jednoho typu, ale jedna obálka m˚uže obsahovat sloupce
r˚uzných typ˚u. Dále platí, že všechny sloupce v jedné
obálce mají vždy stejnou délku, takže se m˚užeme na
obálku dívat jako na posloupnost n-tic. Kromeˇ datových
obálek existují tzv. otrávené obálky, jejichž úkolem je
signalizovat konec datového proudu.</p>
      <p>V soucˇasné dobeˇ podporuje Bobox pouze
sharedmemory systémy, takže operátory si mohou vzájemneˇ
posílat pouze ukazatele na obálky. Tato implementace
znacˇneˇ urychluje operátory jako naprˇ. broadcast (viz
kapitola 4), nebot’ data nejsou nijak klonována a v pameˇti se
nacházejí pouze v jedné instanci. Navíc je celkový pocˇet
ˇrádk˚u v obálce je zvolen s ohledem na velikost
vyrovnávacích pameˇtí v procesoru, tak aby komunikace mezi
operátory probíhala bez nutnosti prˇístupu do hlavní pameˇti.</p>
      <p>Každý exekucˇní plán, musí obsahovat dva speciální
operátory:
• init – tento operátor je vždy první v topologickém
usporˇádání exekucˇního plánu. Jeho úkolem je
nastartovat výpocˇet tím, že na sv˚uj výstup odešle otrávenou
obálku.
• term – tento operátor je vždy poslední v
topologickém usporˇádání. Ve chvíli, kdy prˇijme na svém
vstupu otrávenou obálku, oznámí systému, že
exekucˇní plán byl vyhodnocen.</p>
      <p>
        D˚uležitou soucˇástí systému je plánovacˇ, jehož
úkolem je prˇideˇlovat výpocˇetní cˇas jednotlivým operátor˚um.
Obecneˇ se plánovacˇ rˇídí dostupností datových obálek na
vstupech operátor˚u, tj. pokud má operátor neprázdnou
frontu vstupních obálek, je vložen do fronty operátor˚u
prˇipravených ke spušteˇní. Na základeˇ r˚uzných kritérií [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ]
vybírá plánovacˇ z této fronty operátory a spouští jejich kód
v neˇkterém z prˇipravených vláken. D˚uležité je, že jeden
operátor m˚uže být spušetˇn v nejvýše jednom vlákneˇ. Toto
omezení má dva d˚usledky:
• Programátor operátor˚u nemusí rˇešit synchronizaci
vláken, takže vývoj operátor˚u je znacˇneˇ usnadneˇn.
• Pro zpracování jedné obálky nelze použít více než
jedno vlákno, což zdánliveˇ omezuje možnosti
paralelizace.
      </p>
      <p>
        Ale i prˇes jednovláknovost operátor˚u, je možné
dosáhnout paralelního vyhodnocování exekucˇního plánu, nebot’
nezávislé operátory mohou být spoušteˇny paralelneˇ.
Rozlišujeme trˇi typy paralelism˚u [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ]:
• pipelinový paralelismus – zdroj datového proudu
pracuje paralelneˇ s jeho konzumentem
• taskový paralelismus – nezávislé datové proudy jsou
zpracovávány paralelneˇ
• datový paralelismus – nezávislé cˇásti jednoho proudu
mohou být zpracovány paralelneˇ
      </p>
      <p>Taskový paralelismus je pevneˇ zakódovaný v
exekucˇním plánu, takže prˇináší pouze omezenou škálovatelnost.
Datový a pipelinový paralelismus lze ale za urcˇitých
okolností zvýšit a tím zvýšit škálovatelnost celého systému.</p>
    </sec>
    <sec id="sec-4">
      <title>4 Intra-operátorový paralelismus</title>
      <p>Pipelinový paralelismus m˚užeme zvýšit (resp. zavést) tím,
že urcˇitý operátor rozdeˇlíme na posloupnost dílcˇích
operátor˚u, kde každý vykoná nad proudemcˇást práce (viz
Obrázek 1). Bohužel ne všechny operátory lze takto
dekomponovat a u teˇch, u kterých to lze, to m˚uže být nevýhodné
z d˚uvodu zvýšení režie nutné pro prˇenos datového proudu.</p>
      <p>operator
op1
op2
op3
op4
Obrázek 1: Rozklad operátoru pro zvýšení pipelinového
paralelismu.</p>
      <p>Datový paralelismus m˚užeme do plánu zavést tak, že
vstupní proud rozdeˇlíme na neˇkolik dílcˇích proud˚u, ty
zpracujeme paralelneˇ a poté je opeˇt spojíme do výsledného
proudu. V následujících dvou podkapitolách rozebereme
dva postupy, jak toho dosáhnout.</p>
      <sec id="sec-4-1">
        <title>4.1 Bezestavové operátory</title>
        <p>Bezestavové operátory si neudržují vnitrˇní stav. To
znamená, že zpracování jedné n-tice je zcela nezávislé na
ostatních. Typickou ukázkou je naprˇ. operátor filter,
který z proudu n-tic odstraní ty, které nesplnˇují urcˇitou
podmínku, nebot’ vyhodnocení podmínky pro jednu n-tici
nezávisí na jiných n-ticích.</p>
        <p>Protože zpracování jedné n-tice nezávisí na ostatních,
nezávisí ani zpracování celé obálky na ostatních
obálkách. M˚užeme tedy použít schéma naznacˇené na
Obrázku 2. Operátor rr_dispatch jednoduše prˇeposílá
vstupní obálky na své výstupy metodou round-robin,
operátor rr_consolidate metodou round-robin odebírá
výsledné obálky z jednotlivých operátor˚u a vytvárˇí tak
výsledný proud.</p>
        <p>rr_dispatch</p>
        <p>Protože rr_dispatch a rr_consolidate pouze
manipulují se ukazateli na obálky (viz kapitola 3), pracují oba
operátory velmi rychle a celý výpocˇet zpomalují pouze
zanedbatelneˇ.</p>
      </sec>
      <sec id="sec-4-2">
        <title>4.2 Paralelizovatelné operátory</title>
        <p>Se stavovými operátory je situace složiteˇjší, nebot’
abychom zpracovali jednu obálku, musíme znát stav
odvozený z obsahu prˇedchozích obálek. U neˇkterých
operátor˚u m˚užeme použít postup nazncˇaený v této
podkapitole. Prˇedpokládejme, že teˇlo stavového operátoru vypadá
obecneˇ takto:</p>
        <p>S ← iniciální stav
while not konec do</p>
        <p>zpracuj vstupní data pomocí S a zárovenˇ aktualizuj S
end while
Obcˇas ale lze toto schéma upravit do následující podoby:
S ← iniciální stav
while not konec do
zpracuj vstupní data pomocí S
aktualizuj S
end while</p>
        <p>Pokud je aktualizace stavu S rychlejší než zpracování
dat, m˚užeme vytvorˇit N paralelních operátor˚u a ocˇíslovat
je cˇísly 0 až N − 1 (toto cˇíslo budeme v dalším textu
oznacˇovat jako PID – Parallel ID). Každý operátor pak bude
pracovat následujícím zp˚usobem:</p>
        <p>S ← inciální stav
fáze ← 0
while not konec do
if fáze mod N = PID then</p>
        <p>zpracuj cˇást vstupu pomocí S
end if
aktualizuj S
fáze ← fáze + 1
end while</p>
        <p>V tuto chvíli se operátory strˇídají ve zpracování
vstupních dat, takže pro paralelizaci m˚užeme použít schéma
znázorneˇné na Obrázku 3. Efektivita paralelizace závisí
na složitosti aktualizace stavu. Je zrˇejmé, že by meˇla být
alesponˇ N-krát rychlejší než zpracování dat. Problém
nastává, pokud je aktualizace stavu netriviální, nebot’ v
takovém prˇípadeˇ se pocˇítá N-krát totéž. Rˇ ešením je dedikovat
samostatný operátor pro aktualizaci stavu, který by všem
ostatním posílal aktuální stav.</p>
        <p>
          operator[0]
operator[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
operator[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
operator[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
broadcast
Jazyk Bobolang vznikl pro úcˇely pohodlneˇjšího zápisu
exekucˇních plán˚u. Tomu odpovídá syntaxe, kdy
programátor vyrobí instance operátor˚u (podobneˇ jako se vytvárˇí
promeˇnné v jazycích C/C++) a poté je pomocí operátoru
-&gt; vzájemneˇ pospojuje.
        </p>
        <p>Pomocí jazyka je rovneˇž možné z množiny hotových
operátor˚u (naimplementovaných v jazyku C++ nebo v
jazyku Bobolang) poskládat samostatný operátor, který lze
poté použít v exekucˇním plánu. K tomu slouží následující
syntaxe:
o p e r a t o r p r o c e s s ( i n t ) − &gt;( i n t )
{
p r e p r o p c e s s ( i n t ) − &gt;( i n t ) p r e ;
p o s t p r o c e s s ( i n t ) − &gt;( i n t ) p o s t ;
i n p u t −&gt; p r e ;
p r e −&gt; p o s t ;
p o s t −&gt; o u t p u t ;</p>
        <p>Rˇ ádek operator process(int)-&gt;(int) rˇíká, že
chceme vytvorˇit operátor se jménem process, který
transformuje proud celých cˇísel na proud celých cˇísel.
Následuje teˇlo operátoru, které se skládá z instancí
operátor˚upreprocess a postprocess. Kromeˇ explicitneˇ
uvedených instancí operátor˚u (pre a post), obsahuje každé
teˇlo implicitneˇ operátory input a output. Ty
reprezentují vstup/výstup celého operátoru. Takže rˇádek input -&gt;
pre rˇíká, že vstup operátoru process je prˇeposílán na
vstup operátoru pre. Podobneˇ funguje operátor output.</p>
        <p>Exekucˇní plán se specifikuje stejnou syntaxí. Jak bylo
uvedeno v kapitole 3, exekucˇní plán se skládá ze dvou
speciálních operátor˚uinit a term a teˇla exekucˇního plánu.
Na teˇlo exekucˇního plánu se tedy m˚užeme dívat jako na
operátor, který má jeden vstup (k neˇmu je prˇipojen
operátor init) a jeden výstup (k neˇmu je prˇipojen operátor
term).</p>
        <p>Aby interpretr jazyka poznal, který operátor
reprezentuje exekucˇní plán, musí být vždy pojmenován jako main.</p>
        <p>Pokud bychom chteˇli vyrobit aplikaci, která zpracovává
posloupnost celých cˇísel, napíšeme následující kód:
s o u r c e () − &gt;( i n t ) s o u r c e ;
p r o c e s s ( i n t ) − &gt;( i n t ) op ;
s i n k ( i n t ) − &gt;() s i n k ;
}
i n p u t −&gt; s o u r c e ;
s o u r c e −&gt; op ;
op −&gt; s i n k ;
s i n k −&gt; o u t p u t ;</p>
        <p>Pokud prˇedáme systému Bobox tento kód, interpretr
Bobolangu instanciuje operátor main, vytvorˇí operátory
init a term a vytvorˇí exekucˇní plán, který je znázorneˇný
na Obrázku 4.</p>
        <p>
          Pokud má operátor více vstup˚u/výstup˚u, jsou tyto
operátory cˇíslovány od nuly a cˇíslo vstupu/výstupu musí být
uvedeno. Pokud má vstup/výstup pouze jeden, nemusí být
toto cˇíslo uvedeno. Viz naprˇ. použití operátoru merge, kdy
main
process
init
source
pre
post
sink
term
Obrázek 4: Ukázka plneˇ instanciovaného exekucˇního
plánu.
navíc musí rozeslat otrávenou obálku z operátoru init do
operátor˚usource (viz Obrázek 5).
b r o a d c a s t ( ) − &gt; ( ) , ( ) b c a s t ;
s o u r c e () − &gt;( i n t ) s r c 1 , s r c 2 ;
merge ( i n t ) , ( i n t ) − &gt;( i n t ) merge ;
s i n k ( i n t ) − &gt;() s i n k ;
i n p u t −&gt; b c a s t ;
b c a s t [ 0 ] −&gt; s r c 1 −&gt; [ 0 ] merge ;
b c a s t [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] −&gt; s r c 2 −&gt; [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] merge ;
merge −&gt; s i n k ;
s i n k −&gt; o u t p u t ;
src2
src1
        </p>
        <p>main
init
bcast
merge
sink
term
Obrázek 5: Ukázka práce s operátory, které mají více
vstup˚u/výstup˚u.
5.2</p>
      </sec>
      <sec id="sec-4-3">
        <title>Násobnost vstup ˚u/výstup ˚u</title>
        <p>Každý operátor m˚uže mít libovolný nenulový pocˇet vstup˚u
a výstup˚u. Kromeˇ toho ale m˚uže být každý vstup/výstup
tzv. násobný. Implicitneˇ je každý vstup/výstup
jednonásobný, násobnost se musí zapisovat explicitneˇ, tj. naprˇ.:
b r o a d c a s t ( ) − &gt; ( ) {N} b c a s t ;</p>
        <p>kde N znacˇí násobnost. N m˚uže být bud’ prˇirozené cˇíslo
nebo znak *. Cˇ íslo N prˇesneˇ urcˇuje násobnost
vstupu/výstupu, zatímco * nechává toto rozhodnutí na Bobolangu,
který dosadí vhodné cˇíslo (v pilotní implementaci shodné
s pocˇtem vláken v systému).</p>
        <p>Bobolang umožnˇuje vzájemneˇ propojit výstup
libovolné násobnosti na vstup libovolné násobnosti, pokud
taková operace nevede k logické chybeˇ.</p>
        <p>Pokud je prˇipojen vícenásobný výstup na jednonásobný
vstup, dojde k automatické replikaci cílového operátoru
podle násobnosti výstupu a prˇipojení výstup˚u na jednotlivé
vstupy replikovaných operátor˚u.</p>
        <p>Spojení jednonásobného výstupu s jednonásobným
vstupem zp˚usobí, že cílový operátor je replikovaný práveˇ
tolikrát, kolikrát je replikovaný zdrojový operátor a
jednotlivé výstupy jsou napojeny na jednotlivé vstupy.</p>
        <p>Aby spojení jednonásobného výstupu na vícenásobný
vstup bylo korektní, musí být zdrojový operátor
replikovaný. Pokud je tato podmínka splneˇna, je vytvorˇena jedna
instance cílového operátoru a jednotlivé výstupy jsou
prˇipojeny na vstup tohoto operátoru.</p>
        <p>Spojení vícenásobného výstupu a vícenásobného vstupu
je rovneˇž povoleno, pokud je zdrojový operátor
replikovaný. V takovém prˇípadeˇ je cílový operátor replikovaný
tolikrát, kolikrát je replikovaný zdrojový operátor. V
prˇípadeˇ operátoru -&gt; je 1. operátor napojen na 1. podvstup
cílových operátor˚u, 2. operátor na 2. podvstup, atd.</p>
        <p>
          Následující zdrojový kód, který pokrývá všechny
uvedené možnosti, bude interpretován tak, jak je znázorneˇno
na Obrázku 6.
op ( ) − &gt; ( ) { ∗ } op1 ;
op ( ) − &gt; ( ) op2 ;
op ( ) − &gt; ( ) { ∗ } op3 ;
op ( ) { ∗ } − &gt; ( ) op4 ;
op ( ) { ∗ } − &gt; ( ) op5 ;
}
}
i n p u t −&gt; op1 −&gt; op2 −&gt; op3 ;
op3 −&gt; op4 −&gt; op5 −&gt; o u t p u t ;
op2[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
op2[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
op2[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
op2[0]
main
op3[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
op3[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
op3[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
op3[0]
op4[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
op4[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
op4[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
op4[0]
init
op1
op5
term
Obrázek 6: Ukázka exekucˇního plánu s násobnými
vstupy/výstupy.
5.3
        </p>
      </sec>
      <sec id="sec-4-4">
        <title>Klícˇové slovo typename</title>
        <p>Aby bylo možné vytvárˇet znovupoužitelné operátory
(naprˇ. operátor trˇídící celá a desetinná cˇísla bude mít
pravdeˇpodobneˇ identickou vnitrˇní strukturu), obsahuje
Bobolang klícˇové slovo typename. To je inspirované stejným
slovem v jazyku C++ a je možné jej použít v deklaraci
operátoru naprˇ. v prˇípadeˇ trˇídeˇní takto:
o p e r a t o r s o r t ( typename T) − &gt;(T )
{
s o m e _ o p e r a t o r ( T) − &gt;(T ) op ;
. . .</p>
        <p>V teˇle operátoru pak m˚užeme používat typT, jako
jakýkoliv jiný beˇžný typ. Pokud instanciujeme tento operátor
naprˇ. následujícím zp˚usobem:</p>
        <p>dosadí se za T typ (int,int), tj. dvojice celých cˇísel.
Pokud by vstupní a výstupní typ byl r˚uzný, dojde k chybeˇ
prˇi vyhodnocování.</p>
      </sec>
      <sec id="sec-4-5">
        <title>5.4 Intra-operátorová paralelizace</title>
        <p>Zápis intra-operátorové paralelizace je nyní snadný.
Pokud máme bezestavový operátor, stacˇí zapouzdrˇit jej
následovneˇ:
o p e r a t o r p a r a l l e l _ s t a t e l e s s
( typename T) − &gt;( typename U)
r r _ d i s p a t c h ( T) − &gt;(T ) { ∗ } d i s p ;
s t a t e l e s s _ o p e r a t o r ( T) − &gt;(U) op ;
r r _ c o n s o l i d a t e (U){∗} − &gt;(U) c o n s ;
i n p u t −&gt; d i s p −&gt; op ;
op −&gt; c o n s −&gt; o u t p u t ;</p>
        <p>Instanciací operátoru dostaneme stejné schéma jako
v podkapitole 4.1 (viz Obrázek 2).</p>
        <p>Paralelizovatelný operátor má identické schéma,
jenom místo operátoru rr_dispatch, použijeme operátor
broadcast. Aby programátor nemusel bezestavové a
paralelizovatelné operátory takto paralelizovat rucˇneˇ,
provádí tuto úpravu Bobolang sám. Stacˇí oznacˇit operátor
jako bezestavový (klícˇovým slovem stateless) nebo
paralelizovatelný (klícˇovým slovem parallel). V ostatních
prˇípadech se žádná modifikace neprovádí.</p>
        <p>Pokud se jedná o komplexneˇjší paralelizaci operátoru, je
nutné zapsat schéma operátoru rucˇneˇ, nicméneˇ Bobolang
tuto cˇinnost znacˇneˇ usnadnˇuje, viz kapitola 6.
6
6.1</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>Prˇíklady aplikací</title>
      <sec id="sec-5-1">
        <title>Nested-loops join</title>
        <p>Nested-loops join je velmi snadný algoritmus pro
paralelizaci. Máme-li naimplementovaný operátor, který
vykonává nested-loops join nad vstupními daty, m˚užeme
paralelizovat operátor tak, že vytvorˇíme N instancí toho
operátoru a do jednoho vstupu operátor˚u prˇepošleme celý
první vstup, zatímco do druhého pouze jednu N-tinu
druhého vstupu (N-tiny musí být samozrˇejmeˇ disjunktní).
Výsledný proud pak získáme jako sjednocení výsledku
replikovaných operátor˚u.</p>
        <p>
          V Bobolangu tento algoritmus zapíšeme následujícím
zp˚usobem (dispatch má z úkol rozdeˇlit proud na N cˇástí,
union spojit N proud˚u do jednoho)
{
b r o a d c a s t ( L) − &gt;(L ) { ∗ } b c a s t ;
r r _ d i s p a t c h ( R) − &gt;(R) { ∗ } d i s p ;
n e s t e d _ l o o p s _ j o i n ( L ) , ( R) − &gt;(T ) j o i n ;
u n i o n ( T){∗} − &gt;(T ) u n i o n ;
i n p u t [ 0 ] −&gt; b c a s t −&gt; [ 0 ] j o i n ;
i n p u t [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] −&gt; d i s p −&gt; [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] j o i n ;
j o i n −&gt; u n i o n −&gt; o u t p u t ;
        </p>
        <p>
          Instanciovaný operátor je zobrazen na Obrázku 7. Více
detail˚u vcˇetneˇ experiment˚u lze nalézt vcˇlánku [
          <xref ref-type="bibr" rid="ref10">10</xref>
          ].
disp
bcast
parallel_join
join[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
join[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
join[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
join[0]
union
        </p>
        <p>
          Obrázek 7: Paralelizovaný nested-loops join.
}
}
6.2 Trˇídeˇní
Problémem trˇídeˇní v systémech proudového zpracování
dat jsme se zabývali v prˇedchozí práci [
          <xref ref-type="bibr" rid="ref11">11</xref>
          ]. Základní ideou
algoritmu je rozdeˇlit vstupní proud na neˇkolik podproud˚u,
ty setrˇídit paralelneˇ a tyto setrˇídeˇné podproudy paralelneˇ
slít. Tato myšlenka vede k následujícímu kódu:
o p e r a t o r p a r a l l e l _ s o r t ( typename T) − &gt;(T )
{
r r _ d i s p a t c h ( T) − &gt;(T ) { ∗ } d i s p ;
s o r t ( T) − &gt;(T ) s o r t ;
p a r a l l e l merge ( T){∗} − &gt;(T ) merge ;
i n p u t −&gt; d i s p −&gt; s o r t ;
s o r t −&gt; merge −&gt; o u t p u t ;
        </p>
        <p>Protože je merge oznacˇen jako parallel, vloží
se prˇed tento operátor automaticky broadcast a za
neˇj rr_consolidate. Pokud použijeme operátor
parallel_sort v exekucˇním plánu, rozvine se do tvaru
znázorneˇného na Obrázku 8.</p>
        <p>
          sort[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
sort[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
sort[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
sort[0]
        </p>
        <p>
          parallel_sort
broadcast[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
broadcast[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
broadcast[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
broadcast[0]
merge[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
merge[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
merge[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
merge[0]
disp
Základní myšlenkou paralelního merge joinu pro systém
Bobox je modifikovat a vzájemneˇ párovat vstupní obálky
tak, aby bylo možné spojovat tyto páry paralelneˇ. To vede
k následujícímu schématu:
p r e p r o c e s s ( L ) , ( R) − &gt;(L ) , ( R ) p r e p ;
p a r a l l e l j o i n ( L ) , ( R) − &gt;(T ) j o i n ;
i n p u t [ 0 ] −&gt; [ 0 ] p r e p [ 0 ] −&gt; [ 0 ] j o i n ;
i n p u t [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] −&gt; [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] p r e p [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] −&gt; [
          <xref ref-type="bibr" rid="ref1">1</xref>
          ] j o i n ;
j o i n −&gt; o u t p u t ;
        </p>
        <p>
          Instanciovaný operátor je znázorneˇn na Obrázku 9.
Bližší podrobnosti vcˇetneˇ detailní implementace operátoru
preprocess a join lze nalézt v cˇlánku [
          <xref ref-type="bibr" rid="ref12">12</xref>
          ].
        </p>
        <p>
          broadcast
broadcast
parallel_join
join[
          <xref ref-type="bibr" rid="ref3">3</xref>
          ]
join[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]
join[
          <xref ref-type="bibr" rid="ref1">1</xref>
          ]
join[0]
prep
V tomto cˇlánku jsme prˇedstavili jazyk Bobolang, který je
urcˇený pro použití v systémech pro zpracování
proudových dat. Kromeˇ specifikace exekucˇních plán˚u má
vlastnosti, které umožnˇují snadno popsat vnitrˇní strukturu
paralelizovaných operátor˚u. Interpret jazyka na základeˇ teˇchto
popis˚u instanciuje exekucˇní plán tak, aby prˇi jeho
vyhodnocování v paralelním prostrˇedí k maximálnímu využití
hardwarových prostrˇedk˚u. Uvedli jsme i neˇkolik prˇíklad˚u
jeho reálných aplikací.
        </p>
        <p>Do budoucna plánujeme rozšírˇit Bobolang tak, aby
podporoval rovneˇž distribuované systémy. Bude tedy možné
snadno specifikovat, jak rozdistribuovat exekucˇní plán
mezi více uzl˚u, prˇípadneˇ nechat interpret jazyka
rozdistribuovat plán automaticky.</p>
      </sec>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>E.A.</given-names>
            <surname>Ashcroft</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.A.</given-names>
            <surname>Faustini</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Jagannathan</surname>
          </string-name>
          , and
          <string-name>
            <given-names>W.W.</given-names>
            <surname>Wadge</surname>
          </string-name>
          .
          <article-title>Multidimensional programming</article-title>
          . Oxford University Press,
          <year>1995</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>David</given-names>
            <surname>Bednarek</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Jiri</given-names>
            <surname>Dokulil</surname>
          </string-name>
          , Jakub Yaghob, and
          <string-name>
            <given-names>Filip</given-names>
            <surname>Zavoral</surname>
          </string-name>
          .
          <article-title>Bobox: Parallelization Framework for Data Processing</article-title>
          .
          <source>In Advances in Information Technology and Applied Computing</source>
          ,
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>Ian</given-names>
            <surname>Buck</surname>
          </string-name>
          .
          <article-title>Brook: A streaming programming language</article-title>
          ,
          <year>2001</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>Ian</given-names>
            <surname>Buck</surname>
          </string-name>
          , Tim Foley, Daniel Horn, Jeremy Sugerman, Kayvon Fatahalian, Mike Houston, and Pat Hanrahan.
          <source>Brook for GPUs: Stream Computing on Graphics Hardware. ACM Transactions on Graphics.</source>
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <surname>David</surname>
            <given-names>R</given-names>
          </string-name>
          <string-name>
            <surname>Butenhof.</surname>
          </string-name>
          <article-title>Programming with POSIX threads</article-title>
          .
          <string-name>
            <surname>Addison-Wesley Professional</surname>
          </string-name>
          ,
          <year>1997</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <surname>Roger</surname>
            <given-names>D</given-names>
          </string-name>
          <string-name>
            <surname>Chamberlain</surname>
            , Mark A Franklin, Eric J Tyson, James H Buckley, Jeremy Buhler, Greg Galloway, Saurabh Gayen, Michael Hall, EFBerkley Shands, and
            <given-names>Naveen</given-names>
          </string-name>
          <string-name>
            <surname>Singla</surname>
          </string-name>
          .
          <article-title>Auto-pipe: Streaming applications on architecturally diverse systems</article-title>
          .
          <source>Computer</source>
          ,
          <volume>43</volume>
          (
          <issue>3</issue>
          ):
          <fpage>42</fpage>
          -
          <lpage>49</lpage>
          ,
          <year>2010</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>R.</given-names>
            <surname>Chandra</surname>
          </string-name>
          .
          <article-title>Parallel programming in OpenMP</article-title>
          . Morgan Kaufmann,
          <year>2001</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>Charles</given-names>
            <surname>Consel</surname>
          </string-name>
          , Hedi Hamdi, Laurent Réveillère, Lenin Singaravelu,
          <string-name>
            <given-names>Haiyan</given-names>
            <surname>Yu</surname>
          </string-name>
          , and
          <string-name>
            <given-names>Calton</given-names>
            <surname>Pu</surname>
          </string-name>
          .
          <article-title>Spidle: A DSL approach to specifying streaming applications</article-title>
          .
          <source>In Proceedings of the 2nd international conference on Generative programming and component engineering</source>
          ,
          <source>GPCE '03</source>
          , pages
          <fpage>1</fpage>
          -
          <lpage>17</lpage>
          , New York, NY, USA,
          <year>2003</year>
          . Springer-Verlag New York, Inc.
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>Abhishek</given-names>
            <surname>Das</surname>
          </string-name>
          ,
          <string-name>
            <surname>William J. Dally</surname>
            , and
            <given-names>Peter</given-names>
          </string-name>
          <string-name>
            <surname>Mattson</surname>
          </string-name>
          .
          <article-title>Compiling for stream processing</article-title>
          .
          <source>In Proceedings of the 15th international conference on Parallel architectures and compilation techniques</source>
          ,
          <source>PACT '06</source>
          , pages
          <fpage>33</fpage>
          -
          <lpage>42</lpage>
          , New York, NY, USA,
          <year>2006</year>
          . ACM.
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <surname>Zbynek</surname>
            <given-names>Falt</given-names>
          </string-name>
          , David Bednarek,
          <string-name>
            <given-names>Miroslav</given-names>
            <surname>Cermak</surname>
          </string-name>
          , and
          <string-name>
            <given-names>Filip</given-names>
            <surname>Zavoral</surname>
          </string-name>
          .
          <article-title>On Parallel Evaluation of SPARQL Queries</article-title>
          .
          <source>In DBKDA 2012, The Fourth International Conference on Advances in Databases, Knowledge, and Data Applications</source>
          , pages
          <fpage>97</fpage>
          -
          <lpage>102</lpage>
          . IARIA,
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <surname>Zbynek</surname>
            <given-names>Falt</given-names>
          </string-name>
          , Jan Bulanek, and
          <string-name>
            <given-names>Jakub</given-names>
            <surname>Yaghob</surname>
          </string-name>
          .
          <article-title>On Parallel Sorting of Data Streams</article-title>
          .
          <source>In ADBIS 2012 - 16th East European Conference in Advances in Databases and Information Systems</source>
          ,
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <surname>Zbynek</surname>
            <given-names>Falt</given-names>
          </string-name>
          , Miroslav Cermak, and
          <string-name>
            <given-names>Filip</given-names>
            <surname>Zavoral</surname>
          </string-name>
          .
          <article-title>Highly Scalable Sort-Merge Join Algorithm for RDF Querying</article-title>
          .
          <source>In The Second International Conference on Data Management Technologies and Applications</source>
          ,
          <year>2013</year>
          . [accepted].
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>Zbynek</given-names>
            <surname>Falt</surname>
          </string-name>
          and
          <string-name>
            <given-names>Jakub</given-names>
            <surname>Yaghob</surname>
          </string-name>
          .
          <article-title>Task scheduling in data stream processing</article-title>
          .
          <source>In Proceedings of the Dateso 2011 Workshop</source>
          , pages
          <fpage>85</fpage>
          -
          <lpage>96</lpage>
          . Citeseer,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>M.A.</given-names>
            <surname>Franklin</surname>
          </string-name>
          ,
          <string-name>
            <given-names>E.J.</given-names>
            <surname>Tyson</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Buckley</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Crowley</surname>
          </string-name>
          , and
          <string-name>
            <given-names>J.</given-names>
            <surname>Maschmeyer</surname>
          </string-name>
          .
          <article-title>Auto-pipe and the X language: A pipeline design tool and description language</article-title>
          .
          <source>In Parallel and Distributed Processing Symposium</source>
          ,
          <year>2006</year>
          .
          <source>IPDPS</source>
          <year>2006</year>
          .
          <article-title>20th International</article-title>
          . IEEE,
          <year>2006</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          [15]
          <string-name>
            <surname>Michael</surname>
            <given-names>I. Gordon</given-names>
          </string-name>
          ,
          <string-name>
            <given-names>William</given-names>
            <surname>Thies</surname>
          </string-name>
          , and
          <string-name>
            <given-names>Saman</given-names>
            <surname>Amarasinghe</surname>
          </string-name>
          .
          <article-title>Exploiting coarse-grained task, data, and pipeline parallelism in stream programs</article-title>
          .
          <source>In Proceedings of the 12th international conference on Architectural support for programming languages and operating systems</source>
          , ASPLOS-XII, pages
          <fpage>151</fpage>
          -
          <lpage>162</lpage>
          , New York, NY, USA,
          <year>2006</year>
          . ACM.
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          [16]
          <string-name>
            <surname>Rangaswamy</surname>
            <given-names>Jagannathan</given-names>
          </string-name>
          , Chris Dodd, and
          <string-name>
            <given-names>Iskender</given-names>
            <surname>Agi</surname>
          </string-name>
          .
          <article-title>Glu: A high-level system for granular data-parallel programming</article-title>
          .
          <source>Concurrency - Practice and Experience</source>
          ,
          <volume>9</volume>
          (
          <issue>1</issue>
          ):
          <fpage>63</fpage>
          -
          <lpage>83</lpage>
          ,
          <year>1997</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          [17]
          <string-name>
            <surname>Ujval</surname>
            <given-names>J.</given-names>
          </string-name>
          <string-name>
            <surname>Kapasi</surname>
            ,
            <given-names>William J</given-names>
          </string-name>
          .
          <string-name>
            <surname>Dally</surname>
            , Scott Rixner,
            <given-names>John D.</given-names>
          </string-name>
          <string-name>
            <surname>Owens</surname>
            , and
            <given-names>Brucek</given-names>
          </string-name>
          <string-name>
            <surname>Khailany</surname>
          </string-name>
          .
          <article-title>Programmable stream processors</article-title>
          .
          <source>IEEE Computer</source>
          ,
          <volume>36</volume>
          :
          <fpage>282</fpage>
          -
          <lpage>288</lpage>
          ,
          <year>2003</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          [18]
          <string-name>
            <surname>William</surname>
            <given-names>R.</given-names>
          </string-name>
          <string-name>
            <surname>Mark</surname>
            ,
            <given-names>R.</given-names>
          </string-name>
          <string-name>
            <surname>Steven</surname>
            , Glanville Kurt, Akeley Mark, and
            <given-names>J.</given-names>
          </string-name>
          <string-name>
            <surname>Kilgard</surname>
          </string-name>
          .
          <article-title>Cg: A system for programming graphics hardware in a c-like language</article-title>
          .
          <source>ACM Transactions on Graphics</source>
          ,
          <volume>22</volume>
          :
          <fpage>896</fpage>
          -
          <lpage>907</lpage>
          ,
          <year>2003</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>
          [19]
          <string-name>
            <given-names>J.</given-names>
            <surname>Reinders</surname>
          </string-name>
          .
          <article-title>Intel threading building blocks</article-title>
          .
          <source>O'Reilly</source>
          ,
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref20">
        <mixed-citation>
          [20]
          <string-name>
            <given-names>William</given-names>
            <surname>Thies</surname>
          </string-name>
          , Michal Karczmarek, and Saman Amarasinghe.
          <article-title>StreamIt: A language for streaming applications</article-title>
          .
          <source>In Compiler Construction</source>
          , pages
          <fpage>179</fpage>
          -
          <lpage>196</lpage>
          . Springer,
          <year>2002</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref21">
        <mixed-citation>
          [21]
          <string-name>
            <surname>Dan</surname>
            <given-names>Zhang,</given-names>
          </string-name>
          <article-title>Zeng zhi Li, Hong Song, and Long Liu. A programming model for an embedded media processing architecture</article-title>
          .
          <source>In SAMOS</source>
          , pages
          <fpage>251</fpage>
          -
          <lpage>261</lpage>
          ,
          <year>2005</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>