Poprzedni livestream był bardzo ciekawy (przynajmniej dla mnie ;>) - miałem okazję zaprezentować prostą implementacje rozproszonego raytracingu, oraz poprosić widzów, by Ci wsparli rendering mocą obliczeniową. Założeniem było, że coś pójdzie "nie tak", a to z uwagi na absolutny brak mechanizmów weryfikacji poprawności wyników (co jest tematem kolejnego streama - w czwartek o 20). I na szczęście się udało, tj. coś faktycznie poszło "nie tak" i wynikowe sceny wyglądały jak przysłowiowa sztuka nowoczesna. W tym krótkim poście chciałem wskazać kilka oddzielnych klas rzeczy, które wpłynęły na ostateczny wygląd renderingu (patrz obraz po prawej).

Założenie livestreamu było proste - rozdać binarki workera raytracera (w tym miejscu podziękowania dla KrzaQ za przygotowania binarki pod Linuxa) lub poprosić o skompilowanie jej we własnym zakresie (kod jest otwarty), a następnie zlecić na dostępnych workerach wyrenderowanie sceny (co zostało przez widzów humorystycznie określone jako "kopanie gyncoinów") przesyłając pozycję kamery, rozdzielczość całkowitą, oraz fragment do wyrenderowania; sama scena musiała być już obecna na dysku z powodów rożnych, o których za chwilę. A w trakcie renderingu poopowiadać o samym kodzie, jego konstrukcji, etc. Dodam, że w eksperymencie wzięły udział przynajmniej 24 workery od różnych osób (nie posiadam niestety kompletnych logów, więc mogło być odrobinę więcej), a wyrenderowaliśmy ostatecznie 3 obrazy bazując na tej samej scenie (ale z różnymi rozdzielczościami / pozycjami kamery).

Przechodząc do wynikłych problemów, zacznę od przedmiotu renderingu, który sam w sobie przyczynił się do jednego z problemów, czyli darmowej sceny autorstwa ufukufuka pobranej z cgtrader. Genezą problemu jest fakt, iż wiele edytorów 3D ma najwyraźniej problem z eksportem do OBJ+MTL, tj. definicje materiałów w pliku MTL są szczątkowe, niekompletne, i z jakiegoś powodu odzwierciedlają robocze kolory z edytora, a nie finalne materiały ze sceny. Początkowo (po kupieniu/ściągnięciu trzech scen) myślałem, że problemem jest sama metoda konwersji sceny na OBJ+MTL używana na cgtrader, ale po skontaktowaniu się z jednym z autorów scen okazało się, że nawet OBJ+MTL wyeksportowane w programie z którego korzystał nie zawiera prawidłowych definicji (co zresztą potwierdził znajomy grafik wykonując na moją prośbę prostą scenę testową w posiadanym edytorze, i eksportując ją do OBJ+MTL). Oczywiście, czego pewnie nie muszę dodawać, mój raytracer ma zaimplementowaną obsługę jedynie OBJ+MTL.

Z uwagi na powyższe, o czym wspominałem również podczas streamów, poświęciłem któryś wieczór i poprawiłem posiadane OBJ+MTL. Niestety, z uwagi na ograniczenia licencyjne darmowej sceny, nie mogłem udostępnić widzom zmodyfikowanej. W związku z czym byłem zmuszony poprosić widzów o założenie konta na cgtraderze i pobranie darmowej sceny, rozpakowanie jej (ale bez podmieniania dostarczonego przeze mnie pliku MTL) a następnie zaaplikowania patcha, który sprowadza ją do wersji używanej przeze mnie (patcher został przygotowany przez KrzaQ - podziękowania!).

I tu pojawił się pierwszy problem - część workerów nie miała zaaplikowanego patcha na scene (ale zaskakująco chyba wszystkie korzystały z mojego MTL), co objawiło się przełączeniem się niektórych workerów w domyślny tryb "kolory na podstawie iloczynu skalarnego wektora normalnego i promienia" - stąd rozpoznawalne szare fragmenty obrazu na poniższych screenshotach (widać również wielkość fragmentu zlecaną workerom), lub korzystały z innego materiału niż powinny dla danego obiektu (patrz ostatni obrazek, w którym poduszki są fragmentami z tego samego materiału co kanapy; problem dotyczy również przezroczystego stolika).


Drugi problem związany był z celową ingerencją w scene niektórych workerów, tj. w pierwszym renderingu ktoś z poczuciem humoru wpadł na pomysł, żeby podmienić oryginalny obraz Marka Spaina znajdujący się w centrum sceny na coś innego, co w kolejnych renderingach bardzo się spopularyzowało (naliczyłem 4 różne tekstury, pomijając oryginalny obraz):


Ostatni problem na 50% jest efektem buga w moim kodzie, ale równie dobrze mógł być celowym działaniem, więc i tu go opiszę. O ile oba powyższe problemy były de facto ograniczone przez moc obliczeniową problematycznych workerów, o tyle ostatni problem nie jest posiada tego ograniczenia. Konkretniej, raytracer master odpowiedzialny za przydzielanie pracy zlecał rendering jednego fragmentu (np. o rozdzielczości 100x100) danemu workerowi, a następnie czekał na wynik, i do momentu jego otrzymania dany worker nie mógł "zostać właścicielem" kolejnego fragmentu sceny - a więc jeżeli ktoś chciał wpłynąć np. na 50% sceny, to musiał posiadać ~50% mocy obliczeniowej. Ograniczenie to jednak się nie stosuje, jeśli dany worker by po prostu nie wykonywał żadnych zleconych obliczeń, tylko odsyłał od razu np. czarną klatkę. Efektem tego jest zapełnienie większości finalnego renderingu (poza fragmentami "zajętymi" przez inne workery z uwagi na algorytm FCFS) czarnymi fragmentami przy użyciu minimalnej ilości mocy obliczeniowej:


Przyznaję, że bardzo mi się podobało, że podczas odcinka udało się w tak obrazowy sposób pokazać problemy z obliczeniami rozproszonymi na niezaufanych węzłach :)

W kolejnym odcinku (standardowo w czwartek o 20) pokaże kilka metod zabezpieczenia obliczeń przed "złymi" workerami. Z kilkoma widzami już zresztą dyskutowałem o różnych pomysłach (m.in. dostałem kilka świetnych pomysłów od Karola Augustyniuka - kudos), więc w sumie i tu zapytam - czy i Wy macie jakieś pomysły lub przemyślenia jak można by zabezpieczyć rendering w niezaufanym środowisku? Zachęcam do dyskusji w komentarzach.

I tyle.

Comments:

2017-07-23 14:15:42 = akrasuski1
{
Streama co prawda nie oglądałem, ale czy jakimś sposobem na weryfikację poprawności przysłanego rozwiązania nie byłoby wyrywkowe sprawdzanie kilku pikseli? Master miałby do wykonania setki razy mniej pracy niż workery, a mógłby sprawdzać całkiem sensownie.

Naturalnie nadal możliwe byłoby wstawianie obrazka wielkości np. 1% przydzielonej pracy w nadziei że akurat się żaden sprawdzony piksel tam nie znajdzie, ale przynajmniej nie byłoby takich wielkich połaci z zamienionym całym obrazem ;)
}
2017-07-23 15:51:33 = abc
{
Można lekko zmodyfikować oczywisty pomysł liczenia danego fragmentu dwa razy w ten sposób, że do workerów wysyłane byłby żądania renderowania fragmentu przesuniętego o +/- połowę rozmiaru pojedynczego fragmentu. Plusem takiego rozwiązania jest konieczność zebrania większej liczby osób potrzebnych do przejęcia obrazu, ponieważ wtedy weryfikujemy 4 fragmenty na raz (zakładam tutaj, że master nie przydzieli sprawdzania danego fragmentu workerowi, który go wyrenderował).

Inny pomysłem jest zapisywanie workerów, która wysyłają źle wyrenderowane fragmenty i ich ukaranie np. poprzez nieprzydzielanie pracy przez jakiś czas albo po prostu disconnect.
}
2017-07-23 16:50:33 = Lgeras
{
Problem z obj nie wynika z tego że są problemy z eksportem, tylko z tego że to archaiczny format, który szczególnie przy animacji zabiera monstrualne ilości danych - w porównaniu np. z alembic. Mtl nie supportuje też każdego materiału, a każdy przemysłowy renderer ma własną implementację. Z tego względu wszędzie są pliki .max i tyle;)
}
2017-08-16 08:54:16 = hit02
{
Chyba coś jest nie tak z powiadomieniem o nastepnym streamie na yt. Wyswietla, że to dopiero za 22 dni będzie. :)
}
2017-08-16 10:13:29 = Gynvael Coldwind
{
@hit02
Niestety, powiadomienie jest prawidłowe - przez kilka najbliższych tygodni nie będę w stanie zrobić livestreamów (przerwa wakacyjna), więc kolejny stream dopiero we wrześniu.

@Lgeras
Nie no, bzdura - OBJ/MTL obsługuje wystarczająco dużo ficzerów, żeby scena wyglądała podobnie. Problemem nie jest format, tylko to, że eksportery są źle zrobione.
}

Add a comment:

Nick:
URL (optional):
Math captcha: 6 ∗ 9 + 2 =