Projekt Sauron

Transkrypt

Projekt Sauron
Adam Banyś
Mateusz Dykacz
Konrad Gądek
Wojciech Wyczesany
Projekt Sauron
Projekt realizowany w ramach przedmiotu
„Przetwarzanie Danych W Środowiskach Mobilnych” na katedrze Informatyki
Wydziału Informatyki, Elektroniki i Telekomunikacji
na Akademii Górniczo–Hutniczej.
„Jeden serwer, by wszystkimi rządzić,
Jeden, by urządzenia odnaleźć,
Jeden, by wszystkie zasoby zgromadzić
I w ciemności wykorzystać do obliczeń rozproszonych.”
1
Opis projektu
Cel projektu
Celem projektu jest stworzenie systemu umożliwiającego wykorzystanie rosnącej mocy
obliczeniowej obecnych urządzeń mobilnych — te coraz częściej posiadają nawet
czterordzeniowe procesory zdolne do wykonywania rozmaitych obliczeń i do generowania
realistycznych scen w 3D. Warto zauważyć, że ta moc obliczeniowa jest zazwyczaj
marnowana.
Kolejnym z celów projektu jest wykonywanie specjalnych akcji w określonych rejonach
geograficznych. Przykładem takiego zadania jest zbieranie zdjęć przez stacje telewizyjne z
rejonów, w których nie ma ekipy telewizyjnej; zadanie polegać może na dostarczeniu zdjęcia
określonego obiektu lub zdarzenia.
Słownik
●
●
app / appka — aplikacja działająca pod kontrolą systemu Android
SERVER_ADDR — adres IP/nazwa hosta, pod którym appka może komunikować się z
serwerem
● klient — synonim „appki”
● worker — synonim „appki”
● task — zadanie do wykonania przez “appkę”
Użytkownicy
●
klient / użytkownik — właściciel telefonu wyposażonego w system Android i opisywaną
appkę. Po jej uruchomieniu, jego telefon wykonuje zlecenia pochodzące od serwera.
● zleceniodawca — wprowadza do systemu omawiane zadania.
● administrator systemu — zarządza systemem informatycznym.
Wymagania funkcjonalne
●
Możliwość wykonywania zleceń automatycznych w tle. Zadanie takie uruchamiane jest
zaraz po otrzymaniu skryptu z serwera. Po wykonaniu wiadomość odsyłana jest na
serwer. W przyszłości planowane dodanie schedulera pozwalającego użytkownikowi na
ustalenie ram czasowych w których wykonywanie tych zadań będzie możliwe.
● Możliwość wykonywania zadań specjalnych wymagających interakcji użytkownika.
Zadania te mają określony czas, w którym klient może odpowiedzieć oraz wykorzystują
pomiary z sensorów. Przykładem takiego zadania jest np. wykonanie zdjęcia obiektu
znajdującego się w określonych współrzędnych geograficznych w ciągu określonego
czasu.
Wymagania niefunkcjonalne
●
●
●
działanie na systemie Android 2.3 i nowszych;
możliwość implementacji na innych systemach niż Android;
prosty w obsłudze
2
Specyfikacja systemu
Propozycja rozwiązania
Jako platformy dla urządzeń mobilnych zdecydowaliśmy się użyć systemu Android, gdyż
obejmuje on około 80% rynku urządzeń mobilnych1 . Dodatkowo posiadamy już pewne
doświadczenie w tworzeniu aplikacji pod ten system.
W związku z problemem w usystematyzowaniu i zdefiniowaniu ogólnego sposobu
rozwiązywania zadań, zdecydowaliśmy się wykorzystać język skryptowy Lua. Da się go w łatwy
sposób uruchomić na systemie Android oraz bez problemu można mu udostępnić dostęp do
klas systemowych, skąd można pobrać niemal wszystkie potrzebne informacje.
System android będzie również udostępniał metody ułatwiające pisanie skryptów Lua
oraz dostęp do zasobów systemu Android.
1
http://www.engadget.com/2013/10/31/strategy­analytics­q3­2013­phone­share/
3
Użyte technologie
Android
Aplikacja klienta na system Android działa na urządzeniach z minimalnym API = 8
(Android 2.2). Użyliśmy projektu AndroLua jako implementacji interpretera skryptów Lua. Oprócz
tego aplikacja wykorzystuje bibliotekę google­gson do serializacji i deserializacji obiektów Javy
do formatu JSON.
Serwer
Do implementacji serwera wykorzystany został język Java w wersji 1.6 wraz ze
zdobywającym coraz większą popularnością Play! Framework w wersji 2.2.1. Nikt z nas
wcześniej nie korzystał z Play!, ale zdecydowaliśmy się go użyć ze względu na łatwość użycia
o której można przeczytać w różnych miejscach w internecie, a także ze względu na chęć
rozwijania się. Play! umożliwia stworzenie serwera RESTowego w bardzo prosty sposób, a
następnie pomaga stworzyć GUI korzystając z gotowych szablonów w oparciu o stworzony
wcześniej serwer REST.
Dopuszczalne typy zleceń
W naszym systemie rozróżniamy przede wszystkim dwa typy zleceń:
● background_tasks
Są to de facto skrypty w Lua, które urządzenie mobilne wykonuje w tle
natychmiast po odebraniu. Wraz ze skryptami, przekazywane są metadane niezbędne
do działania systemu.
Do serwera zwracana jest odpowiedź, którą zwróci skrypt. Skrypty mogą
zwracać odpowiedź wielokrotnie.
W ramach background_tasks można wyróźnić specjalny typ zadania
opartego na modelu map/reduce. Podaje się w nim dwa skrypty: map który wykona się
na podzielonej na małe fragmenty tablicy wejściowej, oraz reduce który będzie scalał
zwrócone rezultaty.
● special_tasks
Są to zadania wymagające ingerencji użytkownika. W chwili obecnej
zaimplementowany jest tylko jeden typ takiego zadania; jest to zadanie o parametrze
type = 1. Zlecenie to polega na zrobieniu zdjęcia i przesłaniu go na serwer. Zlecenie
zawiera również nazwę i opis zrozumiałą dla użytkownika, oraz współrzędne
geograficzne oraz promień w jakim zdjęcie może zostać wykonane.
4
Protokół komunikacyjny
Protokół oparty jest w całości o zapytania RESTowe. Są trzy rodzaje wiadomości w
systemie do komunikacji z urządzeniem mobilnym: zapytanie klienta, odpowiedź serwera, oraz
rezultat appki.
Wiadomość A: zapytanie klienta
Zapytanie HTTP/POST jest wysyłane na adres SERVER_ADDR/tasks. Przy pomocy
parametrów żądania, przekazywane są wszystkie informacje niezbędne do dalszego
przetwarzania przez serwer. Wysłanie tego zapytania odbywa się co z góry określony czas.
Parametr
lat
lon
sensors
Opis
położenie geograficzne (x≥0 ⇔ N)
położenie geograficzne (x≥0 ⇔ E)
lista dostępnych sensorów
Przykładowa wartość
50.0655
20.019
1,3,2,…
Typ sensora przedstawiono poniżej.
public static final int TYPE_GPS = 0;
public static final int TYPE_ACCELEROMETER = 1;
public static final int TYPE_MAGNETIC_FIELD = 2;
public static final int TYPE_ORIENTATION = 3;
public static final int TYPE_GYROSCOPE = 4;
public static final int TYPE_LIGHT = 5;
public static final int TYPE_PRESSURE = 6;
public static final int TYPE_TEMPERATURE = 7;
public static final int TYPE_PROXIMITY = 8;
public static final int TYPE_GRAVITY = 9;
public static final int TYPE_LINEAR_ACCELERATION = 10;
public static final int TYPE_ROTATION_VECTOR = 11;
public static final int TYPE_RELATIVE_HUMIDITY = 12;
public static final int TYPE_AMBIENT_TEMPERATURE = 13;
public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14;
public static final int TYPE_GAME_ROTATION_VECTOR = 15;
public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16;
public static final int TYPE_SIGNIFICANT_MOTION = 17;
public static final int TYPE_STEP_DETECTOR = 18;
public static final int TYPE_STEP_COUNTER = 19;
public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;
Opis: http://developer.android.com/guide/topics/sensors/sensors_overview.html#sensors­intro
5
Wiadomość B: odpowiedź serwera
W odpowiedzi na wiadomość A, serwer przy pomocy różnego rodzaju strategii wybiera
zadania, które mają zostać wykonane przez danego klienta i te zadania zostają mu zwrócone
przy pomocy formatu JSON w HTTP/Content.
{
background_tasks: [ // ­ lista zadań, które uruchomi telefon
{
id:1, // ­ unikalne ID zadania
code: // ­ kod zadania (w języku Lua)
"for i=1,3 do\n android:sleep(2000);\n text =
android:getLatitude()\n android:send(text)\n end\n "
}
],
special_tasks: [ // ­ lista zadań, które wykonuje użytkownik
// (np. zrobienie zdjęcia danego obiektu)
{
id: 2, // ­ unikalne ID zadania (opis poniżej)
type: 1, // ­ Rodzaj zadania. 1 ­ wykonanie zdjęcia
lat: 50.07458525629655, // ­ szerokość geograficzna obiektu
lon: 19.90807487852541, // ­ długość geograficzna obiektu
rad: 1024, // ­ maksymalna odległość w metrach
// od obiektu, z której należy
// zrobić zdjęcie; jeśli odległość
// nie ma znaczenia to wartość: ­1
deadline: 1421429980, // ­ do kiedy ważne jest to zlecenie
name: "Zdję​
cie Centrum Informatyki",
// ­ nazwa miejsca jaka będzie się
// pojawiać na liście w appce
description: "Zdję​
cie CI AGH od ul. Czarnowiejskiej"
// ­ opis miejsca jaki będzie się
// pojawiać w appce
}
]
}
6
Wiadomość C: odpowiedź klienta
Aplikacja kliencka, po wykonaniu każdego z zadań, zwraca wyniki do serwera. Wysłane
zostaje zapytanie HTTP/POST na adres SERVER_ADDR/result zawierające poniższe
parametry.
Parametr
id
time
lat
lon
result
Opis
identyfikator zadania
kiedy został wyznaczony wynik
położenie geograficzne (x>0 ⇔ N)
położenie geograficzne (x>0 ⇔ E)
wynik działania programu w Lua
rezultat działań użytkownika
Przykładowa wartość
123
1421429980
20.019
50.0655
"[1,1,2,3,5,8]"
<<zdjęcie base64>>
Należy zwrócić uwagę na pole result, które — zależnie od wykonywanego zadania — ma
różną zawartość.
Zarządzanie zadaniami
Zlecenie zadania
Zlecenie zadania odbywa się poprzez wysłanie zapytania HTTP/POST na adres
SERVER_ADDR/tasks/add zawierającego poniższe parametry.
{
background_tasks: [ // ­ lista zadań, które uruchomi telefon
{
code: // ­ kod zadania (w języku Lua)
"for i=1,3 do\n android:sleep(2000);\n text =
android:getLatitude()\n android:send(text)\n end\n "
verification_strategy // ­ rodzaj weryfikacji dla zadania
code_verify // ­ opcjonalny kod weryfikujący
poprawność wykonania zadania
task_id : 1 // ­ opcjonalny parametr określający że dany
task powinien być skojarzony z innym taskiem
sensors: [1,0,2,4] // ­ wymagane sensory
points:
[{"x":50081005,"y":19890157},{"x":50078885,"y":19889385},
{"x":50080504,"y":19890058}]} // opcjonalny paremetr do
wyznaczania obszaru w którym ma być wykonane zadanie
}
],
special_tasks: [ // ­ lista zadań, które wykonuje użytkownik
// (np. zrobienie zdjęcia danego obiektu)
{
7
task_id : 1 // ­ opcjonalny parametr określający że dany
task powinien być skojarzony z innym taskiem
type: 1, // ­ Rodzaj zadania. 1 ­ wykonanie zdjęcia
lat: 50.07458525629655, // ­ szerokość geograficzna obiektu
lon: 19.90807487852541, // ­ długość geograficzna obiektu
rad: 1024, // ­ maksymalna odległość w metrach
// od obiektu, z której należy
// zrobić zdjęcie; jeśli odległość
// nie ma znaczenia to wartość: ­1
deadline: 1421429980, // ­ do kiedy ważne jest to zlecenie
name: "Zdję​
cie Centrum Informatyki",
// ­ nazwa miejsca jaka będzie się
// pojawiać na liście w appce
description: "Zdję​
cie CI AGH od ul. Czarnowiejskiej"
// ­ opis miejsca jaki będzie się
// pojawiać w appce
}
]
}
W odpowiedzi serwer odsyła id tasków.
Pobranie wyników
Pobranie wyników zadania odbywa się poprzez wysłanie zapytania HTTP/GET na adres
SERVER_ADDR/tasks/:id/result . Odpowiedź zawiera następujące parametry
Parametr
id
time
lat
lon
result
Opis
identyfikator zadania
kiedy został wyznaczony wynik
położenie geograficzne (x>0 ⇔ N)
położenie geograficzne (x>0 ⇔ E)
wynik działania programu w Lua
rezultat działań użytkownika
Przykładowa wartość
123
1421429980
20.019
50.0655
"[1,1,2,3,5,8]"
<<zdjęcie base64>>
Skasowanie zadania
Skasowania zadania odbywa się poprzez wysłanie zapytania HTTP/POST na adres
SERVER_ADDR/tasks/:id/delete.
8
Aplikacja na Androida
Aplikacja pobiera z serwera listę zadań do wykonania za pomocą zapytania HTTP.
Jeśli w odpowiedzi serwera znajduje się background_task, aplikacja natychmiast go uruchamia.
Zadanie jest przekazywane do osobnego serwisu.
Użytkownik widzi na pasku powiadomień powiadomienie o wykonywanych obliczeniach.
Pokazanie powiadomienia gwarantuje nam, że proces obliczający zadanie nie zostanie zabity
przez system.
Po wykonaniu się skryptu wysyłana jest odpowiedź na serwer. Wszystko dzieje się bez
ingerencji użytkownika, jest on jedynie informowany przez pojawiające się na ekranie Toasty o
skończeniu obliczeń.
Jeśli serwer zwróci jakiekolwiek special_tasks, pojawiają się one w głównym ekranie
aplikacji. Użyty kolor informuje użytkownika, czy znajduje się w odpowiedniej odległości od
miejsca wykonania zadania.
W tej chwili jedynym typem special_tasku jest zrobienie zdjęcia, więc po kliknięciu w
zadanie na liście odpalana jest aplikacja kamery. Jeśli użytkownik zrobi zdjęcie i je zaakceptuje,
jest ono wysyłane wraz z odpowiedzią na serwer.
Lua
Skrypty Lua są wykonywane przy użyciu projektu AndroLua w osobnym serwisie.
Aby ułatwić pisanie skryptów i komunikacje z systemem Android, udostępnione są następujące
metody, do których skrypt Lua ma łatwy dostęp.
●
●
●
●
●
public void sleep(long millis) — zatrzymuje działanie skryptu na podaną
liczbę milisekund
public String getLatitude() — pobiera aktualną szerokość geograficzną
użytkownika
public String getLongitude() — pobiera aktualną długość geograficzną
użytkownika
public Long getTime() — pobiera aktualny czas systemowy
public void send(String send) — wywołanie tej metody wysyła na serwer
rezultat zadania (może być wywoływana wiele razy w ciągu działania skryptu)
Do środowiska Lua przekazany jest obiekt o nazwie android, na którym można
wywoływać powyższe metody. Przykładowo, aby wstrzymać działanie skryptu na 5 sekund,
należy w kodzie dodać: android:sleep(5000).
9
Serwer
Serwer podzielony jest na 4 główne moduły.
CMS
Po stronie serwera udostępniony został interfejs graficzny, który w prosty sposób
umożliwia użytkownikowi generowanie nowych zadań oraz podzadań które będą rozsyłane do
poszczególnych workerów. Skorzystano tutaj z konwencji CMS(Content Management System),
wg której dostarcza się interfejs do rozwijania systemu oraz modyfikowania bazy danych.
GUI udostępnia następujące pola:
● type ­ definicja typu zadania, (w tle, zdjęcie)
● verification strategy ­ rozwijalna lista ze strategiami weryfikacji
● code ­ pole tekstowe do wpisania treści skryptu
● verification ­ pole tekstowe do wpisania treści skryptu weryfikującego
● code for map ­ pole tekstowe do wpisania skryptu do zadań prostych w map reduce
● code for reduce ­ pole tekstowe do wpisania skryptu do scalania rezultatów w map
reduce
● geolocation polygon ­ pole w którym można wprowadzić współrzędne punktów, które
mają wyznaczyć obszar wewnątrz którego zadanie musi zostać wykonane
● input for map reduce ­ tablica wejściowa dla problemu typu map reduce
● name ­ nazwa miejsca jakie będzie się pojawiać na liście w appce
● description ­ opis miejsca jakie będzie się pojawiać na liście w appce
● lat, lon ­ odpowiedzialne za wprowadzanie współrzędnych geograficznych zadania,
● rad ­ odległość od lat i lon w jakiej zadanie może być wykonane,
● deadline ­ czas w miliesekundach do którego trzeba zrealizować zadanie (liczony od
01.01.1970)
● subtask_id ­ id taska z którym task jest powiązany
10
Baza danych
tasks ­ tabela przechowuje zadania
subtasks ­ tabela przechowuje podzadania należące do zadania, te zadania są wysyłane
aplikacji.
● run_count ­ do ilu urządzeń chcemy wysłać dane zadanie
● lat, lon ­ współrzędne geograficzne dla danego zadania
● rad ­ odległość od w.w współrzędnych dla której zadanie może być wykonane.
Wyrażone w metrach. Wartość ­1 oznacza dowolne miejsce.
● valid_until ­ czas ważności zadania
● lua_code ­ kod lua który klient ma wykonać
special_task ­ jeśli zadanie jest zadaniem specjalnym istnieje wpis w tej tabeli odpowiadający
wpisowi w tabeli ‘subtask’
special_task_type ­ tabela słownikowa, typ zadania specjalnego. Na chwilę obecną tylko jedna
wartość: 1 ­ PHOTO.
sensors ­ tabela słownikowa, możliwe sensory
required_sensors ­ określa które sensory są niezbędne do wykonania danego zadania
11
delegated_task ­ przechowuje informacje o zwróconych przez serwer zadaniach. Na jej
podstawie interpreter wyników może określić które wyniki pochodzą z tego samego urządzenia.
Serwer zwraca urządzeniu id z tej tabeli.
result ­ tabela przechowuje wyniki, które zwróciły urządzenia mobilne
● result ­ wynik wysłany przez skrypt lua, lub zakodowane w base64 (URL friendly) zdjęcie
w przypadku zlecenia specjalnego
● date ­ data wykonania zadania
● lat,lon ­ miejsce wykonania zadania
Scheduler
Obecna implementacja SimpleScheduler wybiera pierwszy task który nie ma jeszcze
rezultatu (lub nie ma wymaganej ilości udzielonych odpowiedzi), sprawdza czy urządzenie
mobilne spełnia warunki zadania (sensory, odpowiednia lokalizacja, nie upłynął deadline), a
następnie ustawia go na końcu kolejki.
Sprawdzanie czy urządzenie jest w odpowiedniej lokalizacji jest opcjonalne i możliwe do
zrealizowania na 2 sposoby, albo użytkownik zlecający zadanie określa punkt i promień w
którym zadanie od tego punktu należy wykonać, albo użytkownik zleca wiele punktów które
tworzą Polygon wewnątrz którego urządzenie mobilne musi się znaleźć.
Result
Moduł odpowiedzialny jest za weryfikację wyników oraz specjalną obsługę tasków typu
map reduce. Zostały zaimplementowane trzy strategie weryfikacji :
● brak weryfikacji ­ wyniki są od razu rozumiane jako poprawne
● weryfikacja przez skrypt ­ przydatne gdy sprawdzenie poprawności zadania jest
trywialne, a rozwiązanie było heurystyką
● weryfikacja przez większość ­ zadanie zostało zlecone kilku urządzeniom, a następnie
sprawdzany jest odsetek powtarzających się odpowiedzi w celu znalezienia najczęściej
powtarzającej się
Zadania typu map reduce są najpierw rozbijane przez ten moduł na subtaski (input jest
dzielony), które będą wysyłane do urządzeń mobilnych w celu wykonania kodu map. Gdy
zakończy się faza map, rozpoczyna się faza reduce. Moduł z uzyskanych wcześniej rezultatów
tworzy kolejne subtaski, z kodem reduce, które będą scalajać wyniki. Gdy wszystkie wyniki
zostaną scalone w jeden następuje przypisanie wyniku do całego taska.
12
Analiza przedstawionego rozwiązania
Cechy systemu
Protokuł komunikacyjny polegający na wysyłaniu dokumentów jsonowych przy użyciu
zapytań http, znacząco wpływa na możliwości rozbudowy systemu jako całości. Pozwala to
tworzyć nowych klientów zarówno dla urządzeń mobilnych jak i stacjonarnych. Serwer został
zaprojektowany tak, aby w łatwy sposób można go było rozbudowywać, dodawać nowe
funkcjonalności, a także gdy zajdzie taka potrzeba zupełnie wymieniać niektóre komponenty.
Problemem może być skalowalność systemu, przy bardzo dużej ilości zadań i klientów ciągle
odpytujących się serwer o nowe zadania, jednak dobrze zaplanowane i zaprojektowane
rozproszenie aplikacji mogło by ten problem zminimalizować lub nawet całkowicie
wyeliminiować.
Problemy
Propozycja dalszego rozwoju systemu
●
●
●
●
●
●
●
●
●
●
●
rozważenie wprowadzenia powiadomień PUSH dla aplikacji mobilnej (jakie miałoby to
korzyści?)
dodanie większej ilości funkcji które Android udostępnia środowisku Lua
poprawa interfejsu użytkownika aplikacji mobilnej
wprowadzenie opcji konfiguracji aplikacji mobilnej (np. pory w których automatycznie
przyjmujemy zlecenia od serwera)
dodanie do aplikacji mobilnej możliwości dodawania własnych zadań
dodanie większej ilości typów specjalnych zadań
implementacja innych strategii działania dla modułów schedulera i modułu
interpretującego wyniki
implementacja na inne platformy
poprawa graficznego interfejsu do zlecania zadań
rozproszenie serwera na wiele node’ów
implementacja serwera na urządzenie mobilne
13
Przykłady
Mierzenie średniej prędkości na danej ulicy.
W celu wykonania takiego zadania przy pomocy naszego systemu, należy utworzyć
poligon opisujący ulicę. W tym celu podajemy poprzez CMS
listę punktów w formacie JSON:
{
"points": [
{"x":50081005,"y":19890157},
{"x":50080504,"y":19890058}
// ...
]
}
Dla każdego otrzymanego zgłoszenia serwer sprawdza
czy zgłaszające się urządzenie należy do wyznaczonego przez podane punkty obszaru. Jeśli
tak ­ serwer zwraca to zadanie danemu urządzeniu.
Samo mierzenie prędkości jest kwestią tylko i wyłącznie podanego kodu w Lua. Zamiast
prędkości możemy mierzyć dowolne rzeczy na które pozwala nam technologia. Poniżej
przykładowy kod programu mierzący średnią prędkość z 10 sekund
math = require "math"
function degrees_to_radians(deg) return deg * math.pi / 180.0 end
function coordinates_to_distance(lat1, lon1, lat2, lon2)
R = 6378137
dLat, dLon = degrees_to_radians(lat2­lat1), degrees_to_radians(lon2­lon1)
lat1, lat2 = degrees_to_radians(lat1), degrees_to_radians(lat2)
a = math.sin(dLat/2) * math.sin(dLat/2)
+ math.sin(dLon/2) * math.sin(dLon/2) * math.cos(lat1) * math.cos(lat2)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1­a))
d = R * c
return tostring(d)
end
local lat1, lon1 = android:getLatitude(), android:getLongitude()
android:sleep(10000)
local lat2, lat2 = android:getLatitude(), android:getLongitude()
android:send(coordinates_to_distance(lat1, lon1, lat2, lon2))
14
Rozproszony merge–sort
W celu wykonania tego zadania, stworzyliśmy infrasktrukturę pod model obliczeń
map–reduce. Model ten zakłada:
1. zadanie zostaje podzielone na (równe) kawałki, te zostają wysłane do urządzeń;
2. (map) urządzenia obliczają pewną funkcję na uzyskanym kawałku;
3. (reduce) w kolejnym kroku, wyniki działania z poprzedniego kroku są wysyłane
do urządzeń w celu ich połączenia w całość;
4. koniec następuje, gdy uzyskamy jeden kawałek.
W wypadku sortowania przy pomocy rozproszonego algorytmu merge–sort, map polega
na wywołaniu funkcji identycznościowej, natomiast reduce polega na łączeniu dwóch
posortowanych tablic w jedną (da się to zrobić w czasie liniowym na węźle2 ).
function domap(xs)
table.sort(xs)
­­ tu jest sort, ponieważ
­­ * dla chunków rozmiaru 1
­­ jest to f. identyczn.
­­ * dla chunków rozmiaru >1
­­ jest konieczne dla
­­ poprawnego działania
return xs
end
function reduce(xs, ys)
local res = {}
while next(xs) ~= nil
and next(ys) ~= nil do
if xs[1] <= ys[1] then
table.insert(res,
table.remove(xs, 1))
else
table.insert(res,
table.remove(ys, 1))
end
end
if next(xs) == nil then
for k,v in pairs(ys) do
table.insert(res,v)
end
elseif next(ys) == nil then
for k,v in pairs(xs) do
table.insert(res,v)
end
end
return res
end
W efekcie uzyskujemy algorytm równoległy, który dla odpowiedniej ilości procesorów ma w
modelu PRAM złożoność O(log n).
2
15

Podobne dokumenty