Optymalizacja aplikacji użytkowych z wykorzystaniem Parallel Extensions

Wielkość: px
Rozpocząć pokaz od strony:

Download "Optymalizacja aplikacji użytkowych z wykorzystaniem Parallel Extensions"

Transkrypt

1 Politechnika Łódzka Wydział Fizyki Technicznej, Informatyki i Matematyki Stosowanej Marcin Biegała Optymalizacja aplikacji użytkowych z wykorzystaniem Parallel Extensions (Optimizing software applications using Parallel Extensions) Praca dyplomowa magisterska (inżynierska) Promotor: dr inż. Dariusz Puchała Dyplomant: Marcin Biegała nr albumu Łódź, wrzesień 2010

2

3 Spis treści 1 Wstęp 5 Cel pracy Konwencje Podziękowania I Część teoretyczna 9 2 Wielowątkowość Słowo wstępu System operacyjny NET Framework Notka historyczna Czym jest.net Framework? Wersje.NET Framework MSIL System.Threading Klasa Thread Współdzielenie danych Klasa ThreadPool Parallel Extensions Klasa Task Współdzielenie danych Dodatki Planista - Task Scheduler II Część praktyczna 39 4 Parallel Image Effects Opis aplikacji Funkcjonalności Budowa projektu Technologie i narzędzia

4 4 SPIS TREŚCI Budowa projektu Diagram UML Szczegóły implementacji Testy Operacje na drzewie binarnym Zbiory Mandelbrota Filtry graficzne Bibliografia 71 Spis rysunków 73 Spis tabel 75 Listingi 78

5 Rozdział 1 Wstęp Stwierdzenie, że komputery są obecne w każdym aspekcie naszego życia nie jest niczym odkrywczym. Poza komputerami, procesory, lub pokrewne układy elektroniczne, pełniące funkcję centralnych jednostek obliczeniowych odnajdziemy chociażby w telefonach komórkowych, sprzęcie AGD/RTV, czy samochodach. Wraz z zajmowaniem kolejnych gałęzi przemysłu i życia codziennego, rośnie moc obliczeniowa jednostek sterujących. Powszechnie znane (choć odrobinę przejaskrawione) jest powiedzenie, iż komputer w chwili zakupu jest już przestarzały. W 1965 roku Gordon Moore 1 na podstawie obserwacji sformułował tezę, zwaną dziś Prawem Moora[2], która określa, że liczba tranzystorów w układzie scalonym podwaja się co 12 miesięcy. W kolejnych latach, liczba ta była korygowana i obecnie przyjmuje się, że liczba tranzystorów podwaja się co 24 miesiące. Rysunek 1.1 obrazuje w/w tezę. Prawo Moora, choć powstało w latach sześćdziesiątych ubiegłego wieku, jest zadziwiająco trafne do dnia dzisiejszego. Jednak dziś, wiemy już, że prawo to przestanie obowiązywać w przeciągu 2-3 lat. Wzrastająca liczba tranzystorów implikuje ich coraz mniejszy rozmiar. Obecnie dominującą technologią jest 45nm, podczas gdy w latach dziewięćdziesiątych ubiegłego wieku procesory tworzono w technologii 500nm. Malejący rozmiar tranzystora, prowadzi do oczywistej konkluzji: aby Prawo Moora wciąż obowiązywało, w niedługim czasie rozmiar tranzystora powinien być mniejszy od rozmiarów atomu. Docieramy zatem do fizycznej granicy mocy obliczeniowaj procesora. Skoro wydajność jednego procesora jest już nie wystarczająca, oczywistym jest próba wykorzystania dwóch i więcej jednostek obliczeniowych. Tak powstał pomysł procesorów wielordzeniowych - w jednej obudowie zamknięto wiele rdzeni odpowiedzialnych za obliczenia. Bardzo ważnym i wymagającym podkreślenia jest fakt, iż procesor dwurdzeniowy nie jest dwa razy szybszy od swojego jednordzeniowego odpowiednika o takim samym taktowaniu. Jego przewagą jest możlwiość wykonania dwóch operacji jednocześnie, dokładnie w tej samej chwili. Bardzo do- 1 Gordon Earle Moore (ur. 3 stycznia 1929), współzałożyciel korporacji Intel.[1]

6 6 Rozdział 1. Wstęp brym porównaniem może poszczycić się tu Dan Reed 2 opisując różnicę między procesorem jedno i wielordzeniowym: Różnica jest taka jak między szybkim sportowym autem, a autobusem szkolnym. Pierwszy szybko przewiezie dwie osoby, a drugi, choć trochę wolniej czterdzieści. Rysunek 1.1: Ilustracja prawa Moora[2] Cel pracy Praca ta powstała w odpowiedzi na obecnie panujące trendy w dziedzinie inżynierii oprogramowania. Zdecydowana większość obecnie produkowanych procesorów, wytwarzana jest w technologii wielordzeniowej. Mimo to, duża część powstającego oprogramowanie nie potrafi wykorzystać pełni ich potencjału. Zauważył to przytaczany już Dan Reed: Już niedługo zabraknie programistów z doświadczeniem w tworzeniu aplikacji wykorzystujących przetwarzanie równoległe. To już ostatni dzwonek, aby przekonać młodych programistów o wartości przetwarzania równoległego. Celem pracy jest analiza przydatności nowego rozwiązania zapropowanego przez Microsoft - Parallel Extension i porównanie go z dotychczas dostępnymi narzędziami z przestrzeni nazw System.Threading. Porównanie zostanie przeprowadzone zarówno pod kątem możliwości, wydajności jak również efektywności, co rozumiem przez ilość pracy włożonej by uzyskać satysfakcjonujący efekt. 2 Dan Reed - wiceprezes działu Extreme Computing w firmie Microsoft[3]

7 7 Pracy nie kieruję do grona programistów, którzy na co dzień zajmują się problemami przetwarzania równoległego, a do szerokiego spektrum programistów, którzy dzień po dniu tworzą rozwiązania informatyczne w oparciu o platformę.net Framework. Mam nadzieję, że w przedstawionym materiale uda mi się zawrzeć kilka prostych zabiegów, które pozwolą tworzonym aplikacjom wykorzystać całą moc drzemiącą w procesorach wielordzeniowych. Podziękowania Z tego miejsca chciałbym złożyć gorące podziękowania na ręce promotora niniejszej pracy, dr Dariusza Puchały, za poświęcony czas, cierpliwość i cenne wskazówki. Chciałbym także podziękować panu Tomaszowi Kopaczowi z firmy Microsoft Polska, za użyczenie materiałów wykorzystywanych w jego prezentacjach na temat Parallel Extensions.

8 8 Rozdział 1. Wstęp

9 Część I Część teoretyczna

10

11 Rozdział 2 Wielowątkowość 2.1 Słowo wstępu W pierwszych słowach tego rozdziału chciałbym wyjaśnić pewną kwestię nazewniczą. Problem tkwi w określeniach programowanie, czy też wykonywanie współbieżne i równoległe. Mimo, z pozoru podobieństwa znaczeniowego, nie można w/w wyrażeń stosować zamiennie. Wykonywanie współbieżne dotyczy przetwarzania instrukcji aplikacji przez jeden procesor. Kolejne wątki, zarządzane przez system operacyjny wykonywane są naprzemiennie. Zmiany wykonywanych wątków dokonywane są tak często i szybko, że sprawiają wrażenie jednoczesnego wykonywania operacji. Praca równoległa dotyczy systemów wyposażonych w więcej niż jeden procesor (bądź rdzeń), a instrukcje, w kolejnych wątkach wykonywane są dokładnie w tym samym momencie, na oddzielnych jednostkach obliczeniowych. 2.2 System operacyjny Choć wykonanie kolejnych instrukcji podzielonych na wątki jest zadaniem procesora, programista z reguły korzysta w tej kwestii z funkcji udostępnianych przez system operacyjny. To on stanowi warstwę pośredniczącą, pomiędzy kodem aplikacji, a centralną jednostką obliczeniową. To system dba o przełączanie procesów, przydzielanie odpowiednich obszarów pamięci, pozwalając programiście skupić się jedynie na działaniu jego aplikacji. Cechą jaką powinien wyróżniać się system operacyjny jest wielozadaniowość, czyli zdolność do uruchomienia i obsłużenia wielu aplikacji jednocześnie, co pozwala użytkownikowi edytować dokument, podczas gdy w tle kopiowane są pliki, a z głośników sączy się przyjemna muzyka. Początki komputerów PC to procesory z rodziny Intel 8088, jednak nie zostały ona zaprojektowane pod kątem wielozadaniowości. Dużym problemem była obsługa przenoszenia obszarów pamięci, tak aby zagospodarować jak najwięcej wolnej przestrzeni podczas uruchamiania i zamykania aplikacji. Kolejnym krokiem w historii komputerów osobistych było wprowadzenie do użytku sytemu operacyjnego DOS (Disk Operating System). Choć nie wprowadzał on funkcjonalności dla aplikacji wielowątkowych, dzięki różnego rodzaju trikom, możliwe było stworzenie programu, który dawał

12 12 Rozdział 2. Wielowątkowość użytkownikowi złudzenie działania współbieżnego. Najpopularniejszym podejściem było wykorzystanie sprzętowego licznika przerwać. Aplikacje tego typu określano mianem TSR (terminate-andstay-resident). DOS zyskał ogromną popularność, co zaowocowało wieloma aplikacjami będącymi nakładkami na prosty interfejs systemu i rozszerzającymi jego funkcjonalność. Należały do nich między innymi systemy z rodziny Microsoft Windows. Windows 1.0 był na tyle rozwiniętą aplikacją(w porównaniu do DOSa, na którym się opierał), że potrafił przemieszczać bloki danych w pamięci operacyjnej (co jak zostało wcześniej nadmienione, jest warunkiem do zapewnienia obsługi wielozadaniowości). Choć obsługa nie była w pełni transparentna dla programisty, pozwalała na wykorzystywanie udogodnień oferowanych przez istniejące już systemy wielozadaniowe, jak np. UNIX. Sama obsługa wielu aplikacji w Windows była zupełnie odmienna, niż ta prezentowana w UNIXie. Systemy z rodziny UNIX implementowały wielozadaniowość z wywłaszczaniem (preemptive multitasking), gdzie moc obliczeniowa była dysponowana pomiędzy aplikacjami na podstawie sygnałów z licznika procesora. W Windows zastosowano mechanizm wielozadaniowości bez wywłaszczania, nie operujący czasem procesora, a korzystający z systemu komunikatów, krążących pomiędzy aplikacjami. Dany program obsługiwał przekazany doń komunikat (co z reguły skutkowało pewną operacją widoczną dla użytkownika), po czym kontrola wracała do systemu. Stąd, ten typ obsługi wielozadaniowości zwany był wielozadaniowością kooperacyjną, gdyż wymagał od autorów aplikacji uwzględnienia równoczesnego działania innych programów w systemie.

13 Rozdział 3.NET Framework 3.1 Notka historyczna Wiele plotek głosi, że Microsoft tworząc.net Framework po prostu przepisał Javę tworzoną przez firmę SUN. I choć w samym frameworku można dostrzec wiele analogii do Javy, to jednak jego korzeni należy szukać w zupełnie innych rozwiązaniach. Podwaliną dla przyszłej technologi były prace trzech niezależnych zespołów programistycznych zajmujących się: - COM ASP Next-Generation Windows Services 3 Początków.Net Framework należy szukać w opracowanym w latach dziewięćdziesiątych ubiegłego wieku języku Microsoft J++, który to miał być zgodny z oryginalną implementacją Javy firmy Sun, i rozszerzać ją o szereg funkcjonalności wymaganych przez programistów środowiska Windows, m.in. obsługę obiektów COM. Choć początkowo Sun licencjonował kolejne wersje J++, nie przeszkodziło mu to wytoczyć w 1998 roku pozwu o naruszenie patentów. To posunięcie ze strony Sun, było impulsem do stworzenia.net Framework. Microsoft zebrał dokonania wokół nowej wersji interfejsu COM, ASP oraz kod maszyny wirtualnej OmniVM 4, by 13-tego lutego 2002 roku światło dzienne ujrzała nowa platforma programistyczna. 1 Component Object Model - opracowany przez Microsoft interfejs pozwalający na towrzenie i interakcję obiektów niezależnie od języka programowania 2 Active Server Pages - technologia Microsoft służąca do tworzenia dynamicznych stron WWW 3 projekt znany był także pod nazwą Project Lightning lub Project 42, we wstępnej fazie dotyczył rozwinięcia istniejącego standardu COM 4 OmniVM była maszyną wirtualną stworzoną przez Stevena Lucco z Carnegie Mellon University. W 1994 roku Lucco założył firmę Colusa Software, która dwa lata później została wykupiona przez Microsoft, wraz z prawami do OmniVM

14 14 Rozdział 3..NET Framework 3.2 Czym jest.net Framework?.NET Framework jest platformą programistyczną wprowadzającą zupełnie nową jakość tworzenia aplikacji w systemach z rodziny Windows, w porównaniu do WIN32 API. Struktura.NET Framework (zilustrowana na rysunku ) składa się z następujących głównych elementów CLR(Common Language Runtime) - stanowi środowisko uruchomieniowe dla aplikacji napisanych w.net (pewnego rodzaju maszyna wirtualna). Pozwala tworzyć aplikację nie zastanawiając się nad konfiguracją sprzętową maszyny, na której aplikacja będzie uruchamiana, czy zainstalowanymi tam bibliotekami. Jednocześnie zwalnia programistę z zarządzania uprawnieniami aplikacji, czy alokowania pamięci (poprzez mechanizm odśmiecania pamięci - Garbage Collecting GC). CLR jest również pomocny w obsłudze sytuacji wyjątkowych(exceptions). CLR w.net jest środowiskiem uruchomieniowym dla wielu języków (w przeciwieństwie do Javy, gdzie JVM jest wspólnym środowiskiem uruchomieniowym dla różnych platform). Base Class Library - kolekcja zawartych w.net Framework typów i algorytmów, które wykorzystujemy podczas tworzenia aplikacji. Kolekcja jest w pełni obiektowa i pozwala w łatwy sposób rozszerzać zawarte w niej rozwiązania. Biblioteka standardowa zawiera m.in. implementację podstawowych typów, kolekcji, algorytmy kryptograficzne, czy gotowe kontrolki wykorzystywane do budowania interfejsów użytkownika. Rysunek 3.1: Struktura.NET Framework 2.0[9] Całości dopełnia środowisko programistyczne - Microsoft Visual Studio.NET 5 5 Istnieją także inne środowiska programistyczne, jak np. SharpDevelop, lecz niekwestionowanym liderem na platformie Windows jest Visual Studio i to z jego pomocą tworzony był kod towarzyszący niniejszej pracy

15 3.3 Wersje.NET Framework Wersje.NET Framework Przez siedem lat istnienia.net Framwerk na rynku, pojawiło się wiele kolejnych wersji. Podsumowanie najważniejszych zmian w kolejnych wersjach[10] zostało zebrane w tabeli 3.1. Tabela 3.1: Wersje.NET Framework Wersja Data wydania Opis Pierwsza wersja.net Framework Zespół poprawek do wersji 1.0 m.in. roszerzona obsługa zabezpieczeń w aplikacjach WinForms, obsługa IPv6, wprowadzenie.net Framework CF (Compact Framework). Pierwsza wersja frameworka zintegrowana z systemem operacyjnym(windows Server 2003) Wprowadzenie klas generycznych, typów nullowalnych (nullable types), klas partial, metod anonimowych, rozszrzenie kontrolek ASP.NET Wprowadzenie Windows Presentation Foundation(WPF), Windows Comunication Foundation(WCF), Windows Workflow Foundation(WF). Integracja z systemami Windows Vista i Windows Server Dodanie wyrażeń lambda, extension methods, obsługi AJAX do ASP.NET, LINQ Wprowadzenie Parallel Extension, słowo kluczowe dynamic, pełna obsługa IronPython, IronRuby, F# Od wersji 2.0 Microsoft nie wproawdzał znaczących zmian do kodu maszyny uruchomieniowej, a wersja ta stała się trzonem kolejnych wydań.net Framework. 3.4 MSIL Aplikacje napisane w oparciu o.net Framework kompilowane są do języka pośredniego(tzw. bytecode), który nazwano Microsoft Intermediate Language - MSIL. MSIL jest językiem składającym się z niezależnych od procesora instrukcji, które łatwo mogę zostać przekształcone do kodu natywnego. W składni MSIL przypomina assemblera. Listing 3.1 przedstawia kod pośredni wygenerowany dla prostej aplikacji typu Hello World 6.. method private hidebysig static void Main ( string [] args ) cil managed. entrypoint. maxstack 8 L_0000 : ldstr " Hello World " L_0005 : call void [ mscorlib ] System. Console :: WriteLine ( string ) L_000a : ret 6 Kod otrzymany za pomocą narzędzia Reflector firmy Red Gate

16 16 Rozdział 3..NET Framework Listing 3.1: Przykład kodu MSIL 3.5 System.Threading Choć będące tematem niniejszej pracy Parallel Extension stało się częścią.net Framework dopiero od wersji 4.0, framework udestępniał wcześniej narzędzia do tworzenia aplikacji wielowątkowych - przestrzeń System.Threading. Postaram się teraz pokrótce przedstawić pracę z klasami w niej zawartymi i możliwości jakie oferują Klasa Thread Głównym elementem przestrzeni System.Threading jest klasa Thread. Pozwala ona tworzyć i zarządzać kolejnymi wątkami. Obiekty klasy Thread odzwierciedlają pojedyncze wątki. Tabele 3.2 i 3.3 prezentują podstawowe właściwości i metody charakteryzujące te obiekty. Tabela 3.2: Podstawowe właściwości obiektów klasy Thread Nazwa Opis IsAlive Określa, czy dany wątek jest aktualnie wykonywany IsBackground Określa, wątek wykonywany jest w tle (z niższym priorytetem) IsThreadPoolThread Określa czy wątek należy do ThreadPool ManagedThreadId Indeks przydzielany wątkowi przez CLR Name Opcjonalna nazwa wątku Priority Priorytet z jakim wykonywany jest wątek ThreadState Określa stan danego wątku Nazwa Abort Interrupt Join Start Tabela 3.3: Podstawowe metody obiektów klasy Thread Opis Wysyła do wątku żądanie przerwanoa Zgłasza ThreadInterruptException, jeżeli wątek jest zablokowany Blokuje wywoływany wątek, póki inny wątek nie zakończy działania Ustawia wątek w kolejce do wykonania Każdy wątek określony jest enumeracją ThreadState, której kolejne elementy przedstawia tabela 3.4. Aby w.net Framework wykonać zadany kod w wątku innym niż główny, musimy wykonać dwa kroki. Pierwszym jest stworzenie metody, zawierajacej kod do wykonania. Listing 3.2 zawiera przykładowy kod takiej metody. Wykorzystano w nim statyczną właściwość CurrentThread, klasy Thread

17 3.5 System.Threading 17 Tabela 3.4: Wartości enumeracji ThreadState Nazwa Opis Aborted Wykonanie wątku zostało przerwane AbortRequested Żądanie przerwania zostało wysłane, lecz sam wątek wciąż pracuje Background Wątek pracuje w tle Running Wątek jest uruchomiony Stopped Wykonanie wątku zostało zatrzymane StopRequested Żądanie zatrzymania wątku zostało wysłane Suspended Wykonanie wątku zostało zawieszone 7 SuspendRequested Żądanie zawieszenia wątku zostało wysłane Unstarted Wątek został stworzony, lecz nie został jeszcze uruchomiony WaitSleepJoin Wątek jest zablokowany w oczekiwaniu na Monitor.Wait, Thread.Sleep lub Thread.Join zawierającą wskazanie na aktualnie wykonywany wątek. Drugim krokiem jest stworzenie obiektu ThreadStart opakowującego naszą metodę i samego obiektu Thread reprezentującego nasz wątek. Listing 3.3 przedstawia przykładowy kod. private void DoWork () // wypisujemy w konsoli krótki tekst, wraz z identyfikatorem wątku nadanym // przez CLR Console. WriteLine (" Ciężko pracuje. Wątek : 0 ", Thread. CurrentThread. ManagedThreadId ); Listing 3.2: Przykładowy kod metody wykonywanej w wątku pobocznym ThreadStart methodref = new ThreadStart ( DoWork ); \\ parametrem jest nazwa metody, zawierającej \\ kod do wykonania w wątku Thread thread = new Thread ( methodref ); \\ tworzymy wątek thread. Start (); \\ uruchamiamy wątek Listing 3.3: Przykładowy kod tworzący wątek Po uruchomieniu takiego kodu, naszym oczom powinien ukazać się napis Ciężko pracuje. Wątek: 3. Nic nie stoi na przeszkodzie, by rozwinąć nasz przykład i stworzyć np 10 nowych wątków. Wymagane zmiany przedstawia listinig 3.4. ThreadStart methodref = new ThreadStart ( DoWork ); \\ parametrem jest nazwa metody, zawierającej \\ kod do wykonania w wątku for ( int i =0; i <10;++ i)

18 18 Rozdział 3..NET Framework Thread thread = new Thread ( methodref ); \\ tworzymy wątek thread. Start (); \\ uruchamiamy wątek Listing 3.4: Tworzenie i uruchamianie wielu wątków Po uruchomieniu powinniśmy otrzymać mniej więcej taki rezultat: Ciężko pracuje. Wątek: 3 Ciężko pracuje. Wątek: 4 Ciężko pracuje. Wątek: 5 Ciężko pracuje. Wątek: 6 Ciężko pracuje. Wątek: 7 Ciężko pracuje. Wątek: 8 Ciężko pracuje. Wątek: 9 Ciężko pracuje. Wątek: 10 Ciężko pracuje. Wątek: 11 Ciężko pracuje. Wątek: 12.NET Framework umożliwia także uruchamianie wątków z zadanym parametrem. Przedstawia to listing 3.5. private void DoWork ( object param ) // wypisujemy w konsoli krótki tekst, wraz z identyfikatorem wątku nadanym // przez CLR Console. WriteLine (" Ciężko pracuje. Wątek : 0. Parametr : 1 ", Thread. CurrentThread. ManagedThreadId, ( param is String )? ( string ) param : ""); public void Main () ParameterizedThreadStart methodref = new ParametrizedThreadStart ( DoWork ); Thread thread = new Thread ( methodref ); \\ tworzymy wątek thread. Start (" Ala ma kota "); \\ uruchamiamy wątek Listing 3.5: Uruchamianie wątku z parametrem Bardzo często wykorzystywaną funkcjonalnością podczas tworzenia aplikacji wielowątkowych jest możliwość wstrzymiania wykoniania jednego wątku, do czasu zakończenia pracy przez inny wątek. W przestrzeni System.Threading służy do tego metoda Thread.Join. Przykład wykorzystania przedstawia listing 3.6.

19 3.5 System.Threading 19 ThreadStart methodref = new ThreadStart ( DoWork ); \\ parametrem jest nazwa metody, zawierającej \\ kod do wykonania w wątku \\ tablica przechowująca referencje do tworzonych wątków Thread [] threads = new Thread [10]; for ( int i =0; i <10;++ i) \\ tworzymy wątek threads [ i] = new Thread ( methodref ); threads [ i]. Start (); \\ uruchamiamy wątek // wstrzynujemy główny wątek, do czasu wykonania // każdego z nowoutworzonych wątków foreach ( var thread in threads ) thread. Join (); Listing 3.6: Wykorzystanie Thread.Join System.Threading udostępnia także możliwość zatrzymania wykonywania wątku, służy do tego wspomniana wyżej metoda Thread.Abort. Jednak wykorzystanie jej jest bardziej zawiłe niż wykorzystanie przedstawionych do tej pory funkcjonalności. Wywołanie Thread.Abort skutkuje wyrzuceniem wyjątku ThreadAbortException po aktualnie wykonywanej instrukcji wątku. Takie rozwiązanie pozwala przechwycić i obsłużyć wyjątek zapewniając integralność stanu aplikacji. Wspomniany problem integralności stanu aplikacji wielowątkowej prowadzi do dwóch kolejnych metod zawartych w przestrzeni System.Threading, a mianowicie Thread.BeginCriticalRegion() i Thread.EndCriticalRegion(). Jak można wywnioskować z ich nazw, służą one do wydzielania sekcji krytycznych, czyli fragmentów kodu, którego wykonanie nie może zostać przerwane poprzez przekazanianie czasu procesora do innego wątku, czy procesu. Listing 3.7 przedstawia przykład metody zawierającej sekcję krytyczną. private void Sample () Thread. BeginCriticalRegion (); // poniższy kod nie zostanie przerwany // przez wykonywanie innego wątku bool result = PerformCalculations (); if( result == true ) this. IsValid = true ; else

20 20 Rozdział 3..NET Framework this. IsValid = false ; Thread. EndCriticalRegion (); Listing 3.7: Przykład sekcji krytycznej Rysunek 3.2 ilustruje zasadę działania sekcji krytycznych w aplikacjach wielowątkowych. Rysunek 3.2: Ilustracja sekcji krytycznych[15] Współdzielenie danych Choć problemy współbieżnego dostępu do zasobów nie są tematem niniejszej pracy, nie można rozpatrywać wielowątkowości, nie poruszając tego zagadnienia. Ale gdzie tu problem? Za przykład posłuży nam poniższy kod: public class Program // zmienna statyczna - mamy pewność // że istnieje tylko jedna instancja private static int _ counter ; // interesująca nas akcja public static class Increment ()

21 3.5 System.Threading 21 for ( int i =0; i <=10000; ++i) _ counter = _ counter + 1; public static void Main () Increment (); Console. WriteLine ( _counter ); Listing 3.8: Przykładowe odwołanie do zmiennej - jeden wątek Listing 3.8 przedstawia kod, który wykonany dowolną ilość razy, zawsze zwróci ten sam wynik: na konsoli wyświetlona zostanie liczba Dokonajmy teraz drobnej modyfikacji i wprowadźmy element wielowątkowości zgodnie z listingiem 3.9. public static void Main () ThreadStart entry = new ThreadStart ( Increment ); // tworzymy i uruchamiamy 10 wątków Thread [] threads = new Thread [10]; for ( int i =0; i <10; i ++) threads [i] = new Thread ( entry ); threads [i]. Start (); // czekamy na zakończenie // każdego z wątków foreach ( var thread in threads ) thread. Join (); // tu spodziewamy się wyniku // 10* = Console. WriteLine ( _counter ); Listing 3.9: Przykładowe odwołanie do zmiennej - wiele wątków

22 22 Rozdział 3..NET Framework Wynik działania powyższego kodu może być zaskakujący, a na domiar złego, różny przy każdym uruchomieniu. Owszem, zdarza się, że program poda prawidłowo , ale wyświetla także 99997, czy Przedstawiony kod jest jedynie sztucznym przykładem, nie mającym nic wspólnego z rzeczywistością, ale można sobie wyobrazić, gdyby podobne operacje wykonywane były w systemie bankowym, na koncie jednego z klientów. Co gorsza, z racji losowości występowania, błąd tego typu może nie zostać wychwycony w trakcie testów, a skutki mogą być katastrofalne. Pora zdefiniować źródło błędu, a jest nim poniższa linijka: _counter = _counter + 1; Listing 3.10 przedstawia kod IL wygenerowany dla tego odwołania. // przeniesienie wartości zmiennej statycznej na stos ldsfld int32 ConsoleApplication. Program :: _ counter // wartość całkowita 1 dodawana jest na stos ldc.i4.1 // wstawione wartości zostają dodane add // przeniesienie wartości ze stosu do zmiennej statcznej stsfld int32 ConsoleApplication. Program :: _ counter Listing 3.10: Kod pośredni dla operacji przypisania Jak widać prosta instrukcja inkrementacji zmiennej, rozbita zostaje na cztery kolejne instrukcje. Generalizując, przypisanie wartości do zmiennej możemy opisać w trzech krokach: 1. Pobranie wartości zmiennej 2. Inkrementacja 3. Zapisanie nowej wartości zmiennej Wiemy już, że w trakcie działania aplikacji wielowątkowych, czas procesora przełączany jest pomiędzy wykananiem instrukcji poszczególnych wątków. Może się zatem zdarzyć sytuacja, w której wykonanie dwóch wątków, zostanie przerwane po operacji pobrania wartości zmiennej. Mamy wtedy sytuację, w której oba wątki przetrzymują tą samą wartość zmiennej, którą następnie inkrementują i zapisują z powrotem. Wynikiem czego, zamiast zwiększenia wartości zmiennej o 2, zmienna inkrementowana jest jedynie o 1. Przykład takiego zachowania zaobserwowaliśmy w aplikacji przedstawionej na listingach 3.8 i 3.9. Rozwiązaniem, jest zastosowanie pewnego rodzaju sekcji krytycznej, w której czas procesora nie może zostać przekazany, póki aktualny wątek nie wykona wszystkich powierzonych mu zadań. Tym sposobem jesteśmy pewni, że wątek podczas jednej, nieprzerwanej operacji, odczyta, zmieni i zapisze wartość zmiennej.

23 3.5 System.Threading 23 lock Z pomocą przychodzi oczywiście biblioteka klas.net Framework i przestrzeń nazw System.Threading. Służy do tego słowo kluczowe lock, a poprawiony przykład z jego użyciem wyglądałby następująco: public class Program // zmienna statyczna - mamy pewność // że istnieje tylko jedna instancja private static int _ counter ; // interesująca nas akcja public static class Increment () for ( int i =0; i <=10000; ++i) // sekcja określona słowem kluczowym lock // ograniczona jest tylko do jednego wątku lock ( this ) _ counter = _ counter + 1;... Listing 3.11: Odwołanie do zmiennej z uwzględnieniem wielu wątków Tak poprawiony kod przy każdym uruchomieniu zwróci oczekiwany przez nas wynik Przedstawiona konstrukcja synchronizuje dostęp wątków do obiektu, pozwalając na wejście do sekcji tylko jednemu z nich. Parametrem funkcji lock jest obiekt względem którego synchronizujemy. Wspomniany lock jest najprostszym sposobem synchronizacji wykonania wielu wątków w aplikacji. Jeżeli podejrzymy kod pośredni IL wygenerowany dla wywołania z listingu 3.11 zauważymy następującą instrukcję: call void [mscorlib]system.threading.monitor::enter(object, bool&) Wynika z tego, że lock jest jedynie nakładką (tzw. code sugar ) na wywołanie klasy System.Threading.Monitor. Klasa Monitor Klasa Monitor z przestrzeni nazw System.Threading, jak zostało już wspomniane oferuje możliwość synchronizacji dostępu do zmiennych przez kolejne wątki aplikacji. Udostępnia ona dużo więcej możliwośći niż omawiana już konstrukcja lock. Przyjrzyjmy się podstawowym metodom składającym się na klasę Monitor.

24 24 Rozdział 3..NET Framework Nazwa Enter TryEnter Exit Wait Pulse PulseAll Tabela 3.5: Podstawowe metody obiektów klasy Monitor Opis Uruchamia blokadę na danym obiekcie i rozpoczyna sekcję krytyczną Próbuje przejąć blokadę na danym obiekcie, informując jednocześnie o powodzeniu operacji Zwalnia blokadę na obiekcie i zamyka sekcję krytyczną Zwalnia blokadę na obiekcie i zatrzymuje wykonywanie wątku Powiadamia następny wątek w kolejce, o zmianie stanu obiektu blokowanego Powiadamia wszystkie czekające wątki, o zmianie stanu obiektu blokowanego Listing 3.12 przedstawia podstawowe wykorzystanie klasy Monitor na znanym już przykładzie inkrementacji licznika. public class Program // zmienna statyczna - mamy pewność // że istnieje tylko jedna instancja private static int _ counter ; // obiekt służący do synchronizacji private static object o = new object (); // interesująca nas akcja public static class Increment () for ( int i =0; i <=10000; ++i) Monitor. Enter (o); try // w tej części kodu mamy pewność // że będzie wykonywana przez co // najwyżej jeden wątek _ counter = _ counter + 1; finally // korzystamy z bloku finally, by mieć // pewność zamknięcia sekcji, i uniknięcia // zakleszczeń Monitor. Exit (o);

25 3.5 System.Threading Listing 3.12: Odwołanie do zmiennej z użyciem klasy Monitor Powyższy przykład jest dokładnym odzwierciedleniem kodu, wygenerowanego przez kompilator przy użyciu konstrukcji lock. Klasa Monitor oferuje jednak wiele dodatkowych możliwości. Jedną z nich jest możliwość zareagowania, na sytuację w której inny wątek już blokuje dostęp do zasobów. Ilustruje to listing public static void Sample () // przez 1000 ms( 1 sekunda ) próbujemy // przejąć blokadę i dostać się do sekcji // krytycznej if ( Monitor. TryEnter (o, 1000) ) try // część kodu wymagająca synchronizacji finally Monitor. Exit (o); else // akcja, gdy przejęcie blokady zakończyło się // niepowodzeniem // np komunikat z informacją Listing 3.13: Przykład użycia metody Monitor.TryEnter Klasa ThreadPool Omawiając wielowątkowość na platformie.net Framework, nie można pominąć klasy ThreadPool. ThreadPool jest zbiorem reużywalnych wątków, mogących wykonywać dowolne zadania w aplikacji. Słowo reużywalny jest tu kluczowe, gdyż istotą tej klasy, jest wykorzystywanie wciąż tych samych wątków, eliminując narzut na kosztowne operacje stworzenia i konfiguracji wątku. Tabela 3.6 przedstawia zestawienia metod pozwalający na korzystanie z klasy ThreadPool Omawiany w tym rozdziale przykład inkrementacji licznika z wykorzystaniem ThredPool wyglądałby jak na listingu public class Program // zmienna statyczna - mamy pewność

26 26 Rozdział 3..NET Framework Tabela 3.6: Podstawowe metody statyczne klasy ThreadPool Nazwa Opis GetAvailableThreads Zwraca aktualnie dostępną liczbę wątków GetMaxThreads Zwraca maksymalną liczbę wątków jakie mogą zostać utworzone w puli GetMinThreads Zwraca minimalną ilość wątków jakie muszą być utworzone w puli QueueUserWorkItem Zgłasza kod do wykonania w wątku z puli SetMaxThreads Ustawia maksymalną ilość wątków w puli SetMinThreads Ustawia minimalną ilość wątków w puli // że istnieje tylko jedna instancja private static int _ counter ; private object _ synchronization = new object (); // akcja wykonywana w wątku z puli ; // parametr context służy przekazywaniu parametrów // do metody ( parametr musi być zdefiniowany, lecz // jego wykorzystanie jest opcjonalne public static class Increment ( object context ) for ( int i =0; i <=10000; ++i) lock ( _ synchronization ) _ counter = _ counter + 1; public static void Main () for ( int i =0; i <10; i ++) ThreadPool. QueueUserWorkItem ( new WaitCallback ( Increment )); // nie ma prostego sposobu na określenia zakończenia // zakolejkowanych zadań ; // Czekamy pewien okres czasu, by wątki zakończyły swoje // działanie Thread. Sleep (5000) ; // tu spodziewamy się wyniku // 10* = Console. WriteLine ( _counter );

27 3.5 System.Threading 27 Listing 3.14: Przykład użycia klasy ThreadPool

28 28 Rozdział 3..NET Framework 3.6 Parallel Extensions Parallel Extensions 8 jest biblioteką składającą się na.net Framework 4.0, mającą ułatwić i usprawnić proces tworzenia aplikacji wielowątkowych. Składają się na nią trzy podstawowe elementy: Task Parallel Library(TPL) - biblioteka zawierająca klasy i metody służące do budowania aplikacji wielowątkowych PLINQ - uwzględniającą równoległość, implementację technologii LINQ Coordination Data Structure(CDS) - zespół klas ułatwiających współdzielenie danych Parallel Extensions powstało jako odpowiedź firmy Microsoft na panujące tendencje w dziedzinie inżynierii oprogramowania. Celem było dostarczenie programistom narzędzia, które niewielkim nakładem sił, a przede wszystkim bez ogromnych zmian w kodzie, pozwoli im wykorzystać całą moc dominujących dziś procesorów wielordzeniowych. Parallel Extensions tak naprawdę bazuje na omawianej już klasie Thread. Cała magia rozwiązania opiera się na obiekcie nazwanym planistą zadań(task Scheduler). Obiekt ten na podstawie szeregu algorytmów przydziela zlecone zadania(task), czyli fragmenty kodu mające wykonać się równolegle, do konkretnych wątków systemowych (reprezentowanych przez obiekty klasy Thread). Główny zysk, to brak przełączania kontekstu, ponieważ planista wykorzystuje wciąż te same wątki do wykonywania kolejnych zadań. Prócz czasu, zyskujemy również mniejsze zapotrzebowanie na pamięć operacyjną. Działanie planisty najlepiej zilustruje rysunek 3.3 Rysunek 3.3: Ilustracja pracy planisty zadań Jak widać na ilustracji 3.3 planista tworzy pewną ilość wątków (ilość ta zależna jest od ilości procesorów lub rdzeni), po czym przydziela im konkretne zadania, dbając jednocześnie, by podział 8 Znane również pod nazwą ParallelFX

29 3.6 Parallel Extensions 29 pracy był jak najbardziej równomierny Klasa Task Obiekty klasy Task(należącej do przestrzeni System.Threading.Tasks) reprezentują zbiór instrukcji majacych wykonać się w oddzielnym wątku. Pod względem zapewnianej funkcjonalności można go porównywać z klasą System.Threading.Thread (możliwość ta zostanie skrzętnie wykorzystana w dalszej części rozdziału). Listing 3.15 przedstawia różne sposoby tworzenia zadań. public class TaskExample public static void Main () // tworzymy zadanie z użyciem klasy Action Task task1 = new Task ( new Action ( DoWork )); // zadanie określone za pomocą delegatu Task task2 = new Task ( delegate DoWork (); ); // dwie konstrukcje korzystające // z wyrażeń Lambda Task task3 = new Task (() => DoWork ()); Task task4 = new Task (() => DoWork (); ); // wykorzystanie fabryki zadań // tak stworzony wątek zostaje od razu // zakolejkowany do uruchomienia, // nie mamy do niego referencji Task. Factory. StartNew (() => DoWork ()); // uruchamiamy zadania task1. Start (); task2. Start (); task3. Start (); task4. Start (); // czekamy na reakcję użytkownika Console. ReadLine ();

30 30 Rozdział 3..NET Framework // prosta metoda służąca za przykład // instrukcji wykonywanych w wątku public void DoWork () // nie interesuje nas nic więcej // poza wypisaniem tekstu na konsoli Console. WriteLine (" Hello!"); Listing 3.15: Przykłady tworzenia nowych zadań(task) Listing 3.15 przedstawia różne wariacje tworzenia i określania zadań, ale można z nich wyróżnić dwa podstawowe podejścia: - z użyciem obiektów Task, - z wykorzystaniem fabryki zadań. Oba rozwiązania różni przede wszystkim dostępność referencji do utworzonego zadania. Co jednocześnie predestynuje użycie konstrukcji Task.Factory.StartNew dla zadań o krótkim czasie życia. Prezentowane zadania(task) możemy także tworzyć z określonym stanem(parametrem). Przedstawia to listing public class TaskExample public static void Main () // tworzymy zadanie z użyciem klasy Action Task task1 = new Task ( new Action < object >( DoWork ), " Jaś "); // zadanie określone za pomocą delegatu Task task2 = new Task ( delegate ( object param ) DoWork ( param );, " Staś "); // dwie konstrukcje korzystające // z wyrażeń Lambda Task task3 = new Task (( param ) => DoWork ( param ), " Krzyś "); Task task4 = new Task (( param ) => DoWork ( param );, " Gucio "); // wykorzystanie fabryki zadań // tak stworzony wątek zostaje od razu // zakolejkowany do uruchomienia, // nie mamy do niego referencji Task. Factory. StartNew (() => DoWork ());

31 3.6 Parallel Extensions 31 // uruchamiamy zadania task1. Start (); task2. Start (); task3. Start (); task4. Start (); // czekamy na reakcję użytkownika Console. ReadLine (); // prosta metoda służąca za przykład // instrukcji wykonywanych w wątku public void DoWork ( string name ) // nie interesuje nas nic więcej // poza wypisaniem tekstu na konsoli Console. WriteLine ( String. Format (" Hej! Mam na imię 0 ",name. ToString ())); Listing 3.16: Tworzenia zadań(task) z parametrem Po uruchomieniu aplikacji na konsoli powinien pojawić się następujący tekst: Hej! Mam na imię Jaś Hej! Mam na imię Staś Hej! Mam na imię Krzyś Hej! Mam na imię Gucio W równie prosty sposób mamy możliwość zebrania wyników zadania. Wystarczy, że w ciele metody zadania użyjemy słowa kluczowego return, a następnie skorzystamy z właściwości o nazwie Result z odpowiedniego obiektu Task. Całość przedstawia listing??. public class TaskExample public static void Main () // tworzymy zadanie, określając, że zwracanym // typem wartości jest int Task <int > task1 = new Task <int >( new Action ( DoWork )); // uruchamiamy zadanie task1. Start (); // wypisujemy wynik na konsoli // wykonynanie tej instrukcji, zostanie wstrzymane // dopóki wynik zadania nie będzie dostępny Console. WriteLine ( String. Format (" Wynik : 0 ", task1. Result )); Console. ReadLine ();

32 32 Rozdział 3..NET Framework // prosta metoda służąca za przykład // instrukcji wykonywanych w wątku public int DoWork () int a = 2; int b = 2; int wynik = a + b; return wynik ; Listing 3.17: Przykład pobrania wyniku działania zadania Przerywanie zadań Klasa Task daje nam możliwość przerwania już rozpoczętego zadania. Funkcjonalność ta jest bardziej rozbudowana, niż w klasie Thread, lecz jednocześnie lepiej zorganizowana i bardziej logiczna. Wszystko opiera się o obiekty klasy CancelationToken, które stanowią swego rodzaju żeton krążący między wątkiem głównym, a zadaniem. Listing 3.18 public class TaskExample public static void Main () // tworzymy " fabrykę " żetonów CancellationTokenSource tokensource = new CancellationTokenSource (); // pobieramy obiekt żetonu CancellationToken token = tokensource. Token ; // tworzymy zadanie, jako parametr przekazując // utworzony wcześniej żeton Task task1 = new Task ( new Action < CancellationToken >( DoWork ), token ); // uruchamiamy zadanie task1. Start (); // czekamy 0,5 sekundy Thread. Sleep (500) ; // przerywamy wątek tokensource. Cancel (); Console. ReadLine ();

33 3.6 Parallel Extensions 33 // prosta metoda służąca za przykład // instrukcji wykonywanych w wątku public void DoWork ( CancellationToken token ) // pętla wypisująca tekst w konsoli, póki // działanie wątku nie zostanie przerwane while ( true ) // jeżeli zgłoszono żądanie przerwania zadania if( token. IsCancelationRequested ) // wykonujemy kod zapewniający integralność // aplikacji ( o ile jest wymagany ) // i wyrzucamy poniższy wyjątek, informując // CLR o przerwaniu zadania throw new OperationCanceledException ( token ); Console. WriteLine (" Wciąż pracuję... "); Listing 3.18: Anulowanie zadania Korzystanie z obiektów CancellationToken niesie ze sobą wiele dobrego. Przekazując ten sam obiekt do wielu zadań, możemy jedną istrukcją przerwać wszystkie wykonywane w tym momencie wątki. W prosty sposób możemy także uzależnić działanie zadania od wielu żetonów. Służy do tego statyczna metoda CreateLinkedTokenSource. // tworzymy poszczególne źródła żetonów CancellationTokenSource tsource1 = new CancellationTokenSource (); CancellationTokenSource tsource2 = new CancellationTokenSource (); CancellationTokenSource tsource3 = new CancellationTokenSource (); // tworzymy zbiorczy żeton CancellationTokenSource linkedtoken = CancellationTokenSource. CreateLinkedTokenSource ( tsource1. Token, tsource2. Token, tsource3. Token ); // tak przygotowany obiekt, reaguje na wywołanie przerwania wątku // z każdego ze źródeł tsource CancellationToken token = linkedtoken. Token ; Listing 3.19: Tworzenie złożonych obiektów CancellationToken Współdzielenie danych Jak zostało już zaznaczone, całe Parallel Extensions i obiekty klasy Task z których korzystamy, opierają się na omawianych już obiektach klasy Thread z przestrzeni System.Threading. Z tego

34 34 Rozdział 3..NET Framework powodu, do synchronizacji wątków i dostępu do danych korzystamy z tych samych klas, które zostały omówione w rozdziale Dodatki Rozdział ten równie dobrze mógłby zostać nazwany Wielowątkowość w służbie programisty. Microsoft tworząc API Parallel Extensions starał się ułatwić programistom wykorzystanie mocy drzemiącej w procesorach wielordzeniowych do granic możliwości. W dalszej części rozdziału, postaram się przedstawić szereg konstrukcji, które mają za zadanie uprościć programistom tworzenie aplikacji wielowątkowych. Lazy<T> Podczas tworzenia aplikacji, zdarzają się fragmenty kodu, które są wymagające obliczeniowo, bądź wykorzystują dużą ilość pamięci operacyjnej, lecz rezultat ich wykonania nie jest potrzebny przy każdym uruchomieniu aplikacji lub nie musi być wyświetlany na żądanie w czasie rzeczywistym. W takiej sytuacji, często takie obliczenia zlecane są wątkom w tle i uruchamiane tylko wtedy, gdy rzeczywiście są potrzebne, co oszczędza zasoby systemowe. W.NET Framework 4.0 Microsoft udostępnił konstrukcję przewidzianą dokładnie dla tego typu scenariuszy - klasę Lazy. Podczas inicjalizacji obiektu tej klasy, definiujemy kod, jaki zostanie wykonany w tle podczas pierwszego dostępu do zmiennej. Zwalnia to programistę z pisania kodu odpowiedzialnego za stworzenie wątku i jego synchronizację. Przykład zastosowania klasy Lazy przedstawia listing public class Sample public static void Main ( string [] args ) // tworzymy obiekt klasy Lazy, inicjując go zadaniem // wykonywanym w tle, a zwracającym obiekt typu string Lazy <Task < string >> lazyvariable = new Lazy <Task < string > >( () => Task < string >. Factory. StartNew ( // poniżej definiujemy kod prowadzący do obliczenia // potrzebnej wartości () => // szereg // długotrwałych // obliczeń return " wynik "; )); // w tym momencie wartość zmiennej lazyvariable nie jest określona, // a kod w niej zawarty nie został wykonany Console. WriteLine (" Wynikiem działania aplikacji jest :"); // dopiero wywołanie poniższej instrukcji wykona kod zdefiniowany // podczas tworzenia zmiennej lazyvariable, a niniejszy wątek

35 3.6 Parallel Extensions 35 // zostanie wstrzymany, aż do chwili uzyskania wyniku Console. WriteLine ( lazyvariable. Value. Result ); Listing 3.20: Przykład użycia klasy Lazy Pętle równoległe (Parallel Loops) Pętle równoległe są jednym z najciekawszych elementów wprowadzonych w Parallel Extensions. Zacznijmy od prostego przykładu. public static void Main ( string [] args ) int [] numbers = new int []1,2,3,4,5; for ( int i =0; i< numbers. Lenght ; i ++) PerformLongCalculations ( numbers [ i]); foreach ( var num in number ) PerformLongCalculations ( num ); Parallel. For (0, numbers. Lenght, (i)=> PerformLongCalculations ( numbers [ i]); ); Parallel. Foreach ( numbers, num => PerformLongCalculations ( num ); ); Listing 3.21: Przykład użycia pętli Parallel.For Listing 3.21 przedstawia cztery sposoby przetworzenia elementów tablicy. Pierwsze dwie pętle to standardowe sekwencyjne pętle, podstawa każdej aplikacji. Dwie kolejne, to ich odpowiedniki w świecie ParallelFX. Co zyskujemy przez ich użycie? Tak pożądaną przez Nas wielowątkowość. Małym nakładem sił (różnica w konstrukcji pętli sekwencyjnej i jej wielowątkowego odpowiednika jest doprawdy kosmetyczna), możemy przerobić nasz kod tak, by w pełni wykorzystał moc wielordzeniowych procesorów, a tym samy skrócić czas jego wykonania (ku uciesze użytkowników).

36 36 Rozdział 3..NET Framework Pętle równoległe opierają się na użyciu omawianej już klasy Task. W gruncie rzeczy, każdy programista mógłby napisać taką instrukcję sam, lecz Microsoft już nam ją zapewnił. Istota działania Parallel.For i Parallel.Foreach jest bardzo prosta. W pierwszym kroku, zadanie zostaje podzielone na partycje(chunk lub partition), których ilość zależna jest od ilości wątków, jakie może rónolegle przetworzyć nasz procesor. Następnie, zawartość każdej z partycji zostaje przydzielona do osobnego zadania(task) i wykonana. O resztę dba planista zadań (Task Scheduler), który jak zostało już omówione, rodziela zadania pomiędzy fizyczne wątki. Dzięki temu, możemy w bardzo prosty i szybki sposób przystosować naszą aplikację do współczesnych standardów, nie odwołując się jawnie do tworzenia i zarządzania wątkami. Pamiętać należy, iż przedstawione przykłady dotyczą przypadków, w których każdy element z kolekcji przetwarzany jest niezależnie. W przeciwnym wypadku sami musimy zapewnić synchronizację dostępu do współdzielonych danych. Choć konstrukcja pętli równoległych jest stosunkowo prosta i logiczna, sposób przerwania ich wykonywania wymaga komentarza. Listing 3.22 przedstawia przykład przerwania wykonania sekwencyjnej pętli foreach public static void Main ( string [] args ) int [] numbers = new int []1,2,3,4,5; foreach ( var num in number ) if(num == 3) // w tym momencie wykonanie pętli // zostanie przerwane, a przetworzone // zostaną jedynie elementy 1 i 2 break ; PerformLongCalculations ( num ); Listing 3.22: Przykład przerwania pętli Foreach Odpowiadający kod z użyciem pętli równoległej, wyglądałby mniej więcej jak przedstawiony na listingu 3.23 public static void Main ( string [] args ) int [] numbers = new int []1,2,3,4,5; Parallel. Foreach ( numbers, ( int num, ParallelLoopState state ) => if(num == 3)

37 3.6 Parallel Extensions 37 state. Break (); PerformLongCalculations ( num ); ); Listing 3.23: Przykład przerwania pętli Parallel.Foreach Planista - Task Scheduler Wielokrotnie, zaznaczane było, iż działanie zadań(task) w Parallel Extensions opiera się na wykorzystaniu obiektów klasy Thread znanych od początków.net Framework. Co zatem wyróżnia nowe rozwiązanie Microsoftu? Bo przecież nie kilka udogodnień składniowych, przedstawionych w poprzednim rozdziale. Kluczem jest tu planista zadań(task Scheduler). Planista, stanowi warstwę pośrednią pomiędzy zadaniem(task), a obiektem klasy Thread, reprezentującym wątek systemowy. Jak sama nazwa wskazuje, planuje on wykonanie kolejnych zadań, tak by wykonały się one w jak najszybszym czasie, wykorzystując maksimum dostępnych zasobów. Zmiennymi w tym procesie są między innymi ilość rdzeni, bądź procesorów, co przekłada się na ilość wątków wykonania procesora, długość poszczególnych zadań, parametry określone przez programistę..net Framework 4 zawiera implemenetacje kilku różnych planistów, które możemy wybrać stosownie do potrzeb. Domyślny planista, do dysponowania zadań pomiędzy wątkami, korzysta z algorytmu wspinaczki na szczyt (hill-climbing algorithm) 9. Z omawianym planistą związane są dwie istotne właściwości tworzonych zadań (Task) - TaskCreationOptions i TaskStatus. TaskCreationOptions pozwala wpływać na interpretacje tworzonego zadania przez planistę (możliwe do zdefiniowania wartości przedstawia tabela 3.7). TaskStatus zawiera informacje o aktualnym stanie zadania (każdy status został przedstawiony w tabeli 3.8. Nazwa None PreferFairness LongRunning AttachedToParent Tabela 3.7: Wartości TaskCreationOptions Opis Domyślne ustawienia Sugeruje traktowanie zadania jak najbardziej sprawiedliwie Określa zadanie jako długofalowe Definiuje zadanie jako podległe w hierarchii 9 Algorytm wspinaczki na szczyt można zaliczyć do heurystycznych metod optymalizacji. Algorytm polega na przeszukiwaniu przestrzeni rozwiązań w poszukiwaniu rozwiązania optymalnego, poprzez porównywanie jakości kolejnych rozwiązań

38 38 Rozdział 3..NET Framework Tabela 3.8: Wartości TaskStatus Nazwa Opis Created Zadanie zostało stworzone, lecz jego wykonanie nie zostało zaplanowane WaitingForActivation Zadanie czeka na plan wykonania WaitingToRun Zadanie zostało zaplanowane, ale nie uruchomione Running Zadanie w toku WaitingForChildrenToComplete Zadanie czeka na wykonanie zadań potomnych RanToCompletion Zadanie wykonane bez zastrzeżeń Canceled Wykonywanie zadania zostało przerwane Faulted Wykonanie zadania zakończyło się wystąpieniem wyjątku

39 Część II Część praktyczna

40

41 Rozdział 4 Parallel Image Effects 4.1 Opis aplikacji Parallel Image Effects jest prostą aplikacją ilustującą wykorzystanie omawianiej biblioteki Paralell Extensions w praktyce. Program umożliwia zastosowanie różnego rodzaju filtrów i efektów na wczytanych uprzednio plikach graficznych. Rysunek 4.1 przedstawia ekran główny programu. Rysunek 4.1: Okno główne programu Ekran główny podzielony jest na dwie zasadnicze części: - pasek narzędziowy, - przestrzeń zakładek, - pasek statusu. Pasek narzędziowy zawiera przyciski udostępniające konkretne akcje podzielone na zakładki. Resztę okna stanowi podgląd aktualnie edytowanego obrazka. Aplikacja pozwala operować na wielu plikach graficznych jednocześnie - każdy plik stanowi oddzielną fiszkę. Dla ułatwienia nawigacji, każda zakładka zawiera nazwę wyświetlanego pliku, a pasek statusu pełną

42 42 Rozdział 4. Parallel Image Effects ścieżkę dostępu do pliku na dysku. 4.2 Funkcjonalności Pasek narzędziowy podzielony został na cztery zakładki. Pierwsza - Główne - zawiera grupy funkcji Plik i Podstawowe Operacje. Kolejne trzy zakładki zawierają te same funkcjonalności, jednak realizowane odpowiednio: - przez jeden wątek wykonawczy, - przez wiele wątków z użyciem przestrzeni nazw System.Threading, - przez wiele wątków z użyciem biblioteki Parallel Extensions. Grupa Plik Otwiera nową pustą zakładkę. Nowa zakładka Otwórz Otwiera systemowe okno dialogowe wyboru plików, które pozwala wybrać plik graficzny do edycji w aktualnie zaznaczonej zakładce. Jeżeli żadna zakładka nie została jeszcze otwarta, aplikacja sama ją utworzy i otworzy wskazany plik graficzny. Otwórz w nowej zakładce Otwiera systemowe okno dialogowe wyboru plików, które pozwala wybrać plik graficzny do edycji, a następnie umieszcza go w nowo utworzonej zakładce. Zapisz Zapisuje zmiany jakie zaszły w pliku graficznym.

43 4.2 Funkcjonalności 43 Zapisz jako... Pozwala zapisać obrazek wraz z naniesionymi zmianami w innym pliku na dysku (plik docelowy określamy z pomocą systemowego okna dialogowego). Zapisz wszystkie Zapisuje zmiany we wszystkich otwartych zakładkach. Grupa Podstawowe Operacje Zmień rozmiar Otwiera okno dialogowe pozwalające zmienić rozmiar edytowanego pliku graficznego. Odbicie poziome Dokonuje transformacji obrazka do jego odbicia w poziomie. Odbicie pionowe Dokonuje transformacji obrazka do jego odbicia w pionie. Odbicie skośne Dokonuje transformacji obrazka do jego odbicia w pionie i w poziomie jednocześnie. Grupa Barwy Negatyw Tworzy negatyw z wyświetlanego pliku graficznego.

44 44 Rozdział 4. Parallel Image Effects Negatyw danego obrazka tworzymy zastępując wartości składowych RGB pikseli, na różnicę 255 w, gdzie w stanowi wyjściąwoą wartość danej składowej koloru. Kontrast/Jasność Otwiera okno dialogowe (4.2) pozwalające zmienić kontrast i jasność edytowanego pliku graficznego. Rysunek 4.2: Okno dialogowe Jasność/Kontrast Operacja zmiany jasności sprowadza się do dodania, bądź odjęcia pewnej stałej od każdej składowej koloru (RGB) w każdym pikselu składającym się na przetwarzany plik graficzny. Proces zmiany kontrastu w obrazie prowadzi do zmiany relatywnych wartości pomiędzy sąsiednimi pikselami. W aplikacji Parallel Image Effects do osiągnięcia tego celu w optymalny sposób wykorzystano klasę ColorMatrix. Reprezentuje ona macierz przekształcenia, która zostaje zastosowana na wszystkich pikselach przetwarzanego obrazu. Zastosowana macierz prezentuje się następująco: C C C C w tym przypadku stanowi wartość o jaką chcemy przeskalować wartości pikseli. Aby zachować obrazek w oryginalnym stanie stosujemy C = 1, C < 1 zmniejsza kontrast, C > 1 analogicznie zwiększa kontrast.

45 4.2 Funkcjonalności 45 Filtr alfa-obcięty Otwiera okno dialogowe (rys. 4.3) pozwalające zastosować filtr alfa-obcięty na edytowanym pliku graficznym. Rysunek 4.3: Okno dialogowe obsługi filtru alfa-obciętego Filtr alfa-obcięty służy do reduckcji szumu w pliku graficznym. Jego działanie prezentuje rysunek 4.3. Plik graficzny przetwarzany jest zgodnie ze wzorem 4.1. F (x, y) = 1 mn d (s,t)es xy f(s, t) (4.1) F (x, y) określa wartość piksela w punkcie x, y po przetworzeniu, S xy określa sąsiedztwo przetwarzanego piksela o szerokości m i wysokości n. f(s, t) to wartość piksela w oryginalnym obrazie. Algorytm przetwarza plik graficznym piksel po pikselu, analizując oreślone parametrem sąsiedztwo. Nową wartość piksela stanowi średnia z wartości sąsiednich pikseli, po usunięciu d/2 najmniejszych i d/2 największych wartości. Filtr średniej kontrharmonicznej Otwiera okno dialogowe (rys. 4.4) pozwalające zastosować filtr średniej kontrharmonicznej na edytowanym pliku graficznym. Filtr średniej kontrharmonicznej służy do odszumiania plików graficznych. Jego działanie opiera się na zmianie wartości pikseli bitmapy, na równe średniej kontrharmonicznej określonego sąsiedztwa

46 46 Rozdział 4. Parallel Image Effects Rysunek 4.4: Okno dialogowe obsługi filtru średniej kontrharmonicznej piksela, zgodnie ze wzorem 4.2. F (x, y) = (s,t) S xy f(s, t) Q+1 (s,t) S xy f(s, t) Q (4.2) Q w tym przypadku jest parametrem filtru i nosi miano rzędu filtru. Filtr medianowy Otwiera okno dialogowe (rys. 4.5) pozwalające zastosować filtr medianowy na edytowanym pliku graficznym. Filtr medianowy jest kolejnym sposobem na wyeliminowanie szumu z pliku graficznego. Jego działanie jest stosunkowo proste - wartość danego piksela zamieniana jest na medianę wartości sąsiednich pikseli, zgodnie ze wzorem 4.3. F (x, y) = median (s,t) Sxy f(s, t) (4.3) Wartość mediany wyliczamy ustawiając wartości pikseli z sąsiedztwa w uporządkowanym ciągu, a następnie wybieramy element środkowy. Operator Rozenfelda

47 4.2 Funkcjonalności 47 Rysunek 4.5: Okno dialogowe wywołania filtru medianowego Otwiera okno dialogowe (rys. 4.6) pozwalające określić parametry operatora Rozenfelda, który następnie zostanie nałożony na edytowany plik graficzny. Rysunek 4.6: Okno dialogowe operatora Rozenfelda Operator Rozenfelda może służyć jako narzędzie do wykrywania krawędzi na bitmapach. Wartość każdego piksela obrazka, zamieniana jest na wartość średnią z sąsiadujących pikseli zgodnie ze wzorem 4.4. F (x, y) = (1/P )f(x + P 1, y) + f(x + P 2, y) f(x, y) f(x 1, y) f(x 2, y)... f(x P, y) (4.4)

48 48 Rozdział 4. Parallel Image Effects Szczegóły tła Otwiera okno dialogowe (rys. 4.7) pozwalające zdefniować parametry operacji splotu, dzięki której możemy wydobyć szczegóły tła edytowanego obrazka. Rysunek 4.7: Okno dialogowe operacji wydobywania szczegółów tła Splot definiujemy za pomocą równania 4.5. M M F (x, y) = h(i, j)f(x + i, y + j), x = M, 2,..., P M 1, y = M, 2,..., P M 1 (4.5) i= M j= M W aplikacji zaimplementowane zostały następujące maski splotu h(i, j): Maska południe Maska zachód 4.3 Budowa projektu Technologie i narzędzia h(, ) = h(, ) = Aplikacja Parallel Image Effects została napisana z wykorzystaniem.net Framework 4.0 i technologii Windows Presentation Foundation(WPF). Jako IDE posłużyło Microsoft Visual C# 2010 Express. Dodatkowo do stworzenia paska narzędzi zgodnego z Fluent User Interface (znanego m.in. z pakietu

49 4.3 Budowa projektu 49 Microsoft Office 2007) została wykorzystana biblioteka WPF Ribbon Preview, którą można odnaleźć pod adresem wpf Budowa projektu Kod aplikacji został podzielony na następujące projekty: Common Projekt dostępny w każdym elemencie aplikacji. Zawiera zestaw metod pomocniczych i Extension Methods. Składowe: - Extensions.cs Zbiór Extension Methods ułatwiających operację na plikach graficznych. - Helpers.cs Zbiór metod pomocniczych. - NativeMethods.cs Odwołania do WinAPI. Filters Zawiera szereg interfejsów wywołań filtrów i efektów graficznych, które następnie są implementowane w różnych konfiguracjach obsługi wątków. Zawiera także implementację podstawowych operacji graficznych, jak odbicia, czy zmiana rozmiaru. Filters.ParallelFX Implmentacja filtrów i efektów graficznych w oparciu o Parallel Extensions. Składowe: - AlphaTrimmedFilter.cs Implementacja filtru alfa-obciętego. - ContraharmonicMeanFilter.cs Implementacja filtru średniej kontrharmonicznej. - ConvolutionFilter.cs Implmenetacja operacji splotu i wydobywania szczegółów tła. - MedianFilter.cs Implmenetacja filtru medianowego. - RozenfeldOperator.cs Implementacja operatora Rozenfelda. - SimpleTransforms.cs Implementacja prostych przekształceń (np. zmiana jasności). Filters.Single Projekt zawiera implementację filtrów i efektów bez użycia wielowątkowości, w pełni sekwen-

50 50 Rozdział 4. Parallel Image Effects cyjnie. Na projekt składają się te same elementy, które pokrótce omówiono w powyższym punkcie. Filters.Threads Implementacja filtrów i operatorów z zastosowaniem wielowątkowości w oparciu o elementy przestrzeni nazw System.Threading (m.in. klasa Thread, czy ThreadPool). Elementy składowe zostały omówione w punkcie opisującym Filters.ParallelFX ParallelImage Ten projekt skupia implementację interfejsu aplikacji pozwalającej operować na plikach graficznych z wykorzystaniem wyżej opisanych projektów. Składowe: - App.xaml i App.cs Standardowo generowana klasa reprezentująca całą aplikację. Stanowi jednocześnie punkt wejściowy programu. - MainWindow.xaml i MainWindow.cs Pliki określają wygląd i logikę działania głównego okna aplikacji. - Dialogs Zbiór definicji okien dialogowych pojawiających się w aplikacji. - Dialogs\ConvolutionDialog.xaml i ConvolutionDialog.cs Opis i implementacja logiki okna dialogowego obsługi operacji splotu. - Dialogs\FilterDialog.xaml i FilterDialog.cs Opis i implementacja okna dialogowego obsługującego filtry redukujące szum. - Dialogs\RozenfeldDialog.xaml i RozenfeldDialog.cs Implementacja okna dialogowego określającego parametry wywołania operatora Rozenfelda. - Dialogs\SimpleTransformDialog.xaml i SimpleTransformDialog.cs Opis i implementacja okna podstawowych przekształceń. - Helpers\TabInfo.cs Klasa pomocnicza agregująca informacje o otwarych zakładkach. - Images Zawiera pliki graficzne wykorzystywane w interfejsie. - Localization\UIStrings.resx Słownik par klucz-wartość wykorzystywanych do lokalizacji aplikacji. SynteticTests Ten projekt zawiera klasy i metody służące do testowania rozwiązań w oparciu o przestrzeń nazw System.Threading i Parallel Extensions. Zawiera m.in. implmenetację testu przechodzenia drzewa binarnego, czy rysowania zbioru Mandelbrota opisanych w rozdziale Diagram UML Rysunek 4.8 przedstawia diagram klas implementujących filtry i operatory graficzne.

51 4.3 Budowa projektu 51 Rysunek 4.8: Diagram klas implementujących filtry i operatory graficzne Szczegóły implementacji Poniżej przedstawiam istotniejsze elementy implementacji. Oczekiwanie na zakończenie wątków z puli W wielu miejscach aplikacji, w celu jak najlepszej optymalizacji kodu wykorzystującego przestrzeń nazw System.Threading wykorzystałem wątki z puli ThreadPool. Wadą tego rozwiązania jest brak referencji do wykorzystywanego wątku, przez co nie możemy w prosty sposób oczekiwać zakończenia jego pracy.

52 52 Rozdział 4. Parallel Image Effects Aby rozwiązać ten problem przygotowałem prostą metodę, która w pętli sprawdza, czy wątki z puli wciąż pracują. Przedstawia ją listing 4.1. /// <summary > /// Prosta metoda czekająca na zakończenie wątków w puli /// </ summary > public static void WaitForThreads ( int timeoutiterations ) int maxthreads = 0; int placeholder = 0; int availthreads = 0; while ( timeoutiterations > 0 timeoutiterations < 0) System. Threading. ThreadPool. GetMaxThreads ( out maxthreads, out placeholder ); System. Threading. ThreadPool. GetAvailableThreads ( out availthreads, out placeholder ); if ( availthreads == maxthreads ) break ; System. Threading. Thread. Sleep ( TimeSpan. FromMilliseconds (100) ); -- timeoutiterations ; DoEvents (); Listing 4.1: Implementacja metody WaitForThreads Przetwarzanie plików graficznych Przetwarzanie plików graficznych jest podstawą aplikacji Parallel Image Effects. Wielce istotnym elementem jest sposób dostępu do konkretnych pikseli i składowych kolorów. Podstawowym sposobem operowania na pliku graficznym jest klasa Bitmap i jej metody GetPixel(x,y) i SetPixel(x,y, color). Jednak jest to metoda niezwykle nieefektywna i nie nadaje się do przetwarzania grafiki. Aby uzyskać zadowalające efekty (głównie chodzi o czas wykonania) należy ulokować bitmapę w pamięci operacyjnej i operować na niej za pomocą wskaźników. Listing 4.2 przedstawia przykładową metodę, która operuje na bitmapie ulokowanej w pamięci. public Bitmap Operate ( Bitmap image ) // tworzymy kopię wejściowej bitmapy Bitmap outputbitmap = Helpers. CloneImage ( image ); // LockBits powoduje ulokowanie bitmapy w pamięci operacyjej

53 4.3 Budowa projektu 53 // i zwrócenie informacji potrzebnych do operowania na niej // w postaci obiektu klasy BitmapData BitmapData outputdata = outputbitmap. LockBits ( new Rectangle (0, 0, image. Width, image. Height ), ImageLockMode. ReadWrite, transformedimagepixelformat ); BitmapData inputdata = image. LockBits ( new Rectangle (0, 0, image. Width, image. Height ), ImageLockMode. ReadOnly, transformedimagepixelformat ); // zaznaczamy, że kod wykonywany dalej będzie odwoływał się // bezpośrednio do pamięci operacyjnej omijając mechanizm // GarbageCollector unsafe // właściwość Scan0 wskazuje na adres początku bitmapy // w pamięci operacyjnej byte * outputpointer = ( byte *) outputdata. Scan0 ; byte * inputpointer = ( byte *) inputdata. Scan0 ; // obliczamy jak dużą przestrzeń pamięci zajmuje jeden // wiersz bitmapy ( założyliśmy tu, że obrazek jest // zapisany w 24 bitach, czyli 3 bajtach int addedoffset = inputdata. Stride - image. Width * 3; int sizey = image. Height ; int sizex = image. Width ; // iterujemy po każdym wierszy for ( int y =0; y< sizey ; y ++) // i każdym pikselu w wierszy for ( int x = 0; x < sizex ; x ++) // do wskaźnika możemy odwołać się jak do tablicy. // Indeks 0 to kanał składowa czerwona ( R) // Indeks 1 to kanał składowa zielona ( G) // Indeks 2 to kanał składowa niebieska ( B) // poniżej dokonujemy negacji obrazka, czyli od 255 // odejmujemy każdą składową koloru, i tak otrzymane // wartości zapisujemy w bitmapie wyjściowej outputpointer [0] = ( byte ) (255 - ( int ) inputpointer [0]) ; outputpointer [1] = ( byte ) (255 - ( int ) inputpointer [1]) ; outputpointer [2] = ( byte ) (255 - ( int ) inputpointer [2]) ; // przeskakujemy o 3 bajty, czyli do następnego // piksela inputpointer += 3; outputpointer += 3;

54 54 Rozdział 4. Parallel Image Effects ); // przeskakujemy do kolejnego wiersza outputpointer += addedoffset ; inputpointer += addedoffset ; // po przetworzenie pozostaje jedynie odczytać wynik z // pamięci operacyjnej i " uwolnić " bitmapę image. UnlockBits ( inputdata ); outputbitmap. UnlockBits ( outputdata ); return outputbitmap ; Listing 4.2: Przykład operacji na bitmapie ulokowanej w pamięci operacyjnej

55 Rozdział 5 Testy 5.1 Operacje na drzewie binarnym Drzewo binarne jest strukturą danych opisanych na pewnym skończonym zbiorze węzłów, która: nie zawiera węzłów (mamy wtedy do czynienia z drzewem pustym) składa się z rozłączynych zbiorów węzłów: - korzeni - lewego poddrzewa - prawego poddrzewa. Każdy węzeł zawiera wskazanie do węzła nadrzędnego oraz wzkazania na prawe i lewe poddrzewo.[17] W aplikacjach wykorzystujących drzewa binarne często pojawia się potrzeba dokonania pewnych operacji na każdym węźle drzewa. To zadanie stanowi podstawę niniejszego testu. Listing 5.1 przedstawia przykładową implementację drzewa binarnego. /// <summary > /// Węzeł drzewa binarnego /// </ summary > public class TNode /// <summary > /// Lewe poddrzewo /// </ summary > public TNode LeftNode get ; set ; /// <summary > /// Prawe poddrzewo /// </ summary > public TNode RightNode get ; set ; /// <summary > /// Wartość związana z węzłem /// </ summary > public int Value get ; set ; /// <summary >

56 56 Rozdział 5. Testy /// Statyczna metoda tworząca instację drzewa binarnego. /// Tworzy drzewo o żądanej wysokości, przypisując każdemu /// węzłowi kolejną wartość całkowitą począwszy od określonej /// w parametrze. /// </ summary > /// <param name =" deep "> Wysokość </ param > /// < param name =" start " > Wartość początkowa licznika </ param > /// < returns > Korzeń stworzonego drzewa </ returns > public static TNode CreateTree ( int deep, int start ) TNode root = new TNode (); root. Value = start ; if ( deep > 0) root. LeftNode = CreateTree ( deep - 1, start + 1); root. RightNode = CreateTree ( deep - 1, start + 1); return root ; Listing 5.1: Implementacja drzewa binarnego Dalej zdefiniujmy klasę TreeTravel jak na listingu 5.2. /// <summary > /// Drzewo do przetworzenia /// </ summary > public TNode Tree get ; set ; public TreeTravel () Tree = TNode. CreateTree (9, 1); InitializeComponent (); /// <summary > /// Metoda imitująca długotrwałe obliczenia /// na elemencie drzewa /// </ summary > /// < param name =" value " > Wartość do przetworzenia </ param > /// <returns > Wynik </ returns > public static int ProcessItem ( int value ) Thread. SpinWait ( ) ; return value ; /// <summary >

57 5.1 Operacje na drzewie binarnym 57 /// Przechodzenie drzewa /// </ summary > /// <param name =" node "> Węzeł początkowy </ param > public static void WalkTree ( TNode node ) Listing 5.2: Klasa TreeTravel Klasa TreeTravel składa się z trzech istotnych elementów: konstruktora, w którym tworzymy drzewo binarne o wysokości 4, metody ProcessItem, która imituje przetwarzanie wartości drzewa, metody WalkTree, której zadaniem jest odwiedzenie każdego węzła w drzewie i wywołanie ProcessItem na jego wartości. Najprostszym sposobem implementacji metody WalkTree jest wykorzystanie rekurencji, co przedstawia listing 5.3. /// <summary > /// Rekurencyjne przechodzenie drzewa /// </ summary > /// <param name =" node "> Węzeł początkowy </ param > public static void WalkTreeRecurrent ( TNode node ) if ( node == null ) return ; WalkTreeRecurrent ( node. LeftNode ); WalkTreeRecurrent ( node. RightNode ); ProcessItem ( node. Value ); Listing 5.3: Implementacja WalkTree za pomocą rekurencji Czas wykonania takiego zadania wynosi s.Wadę tego rozwiązania widać od razu po uruchomieniu menadżera zadań - wykorzystuje ono jedynie jedną jednostkę obliczeniową. Aby temu zaradzić, należy wprowadzić obsługę wielowątkowści. Drugie rozwiązanie problemu oparte zostało o obiekty klasy Thread. Prezentuje je listing 5.4. /// <summary > /// Przechodzenie drzewa z wykorzystaniem /// wątków /// </ summary > /// <param name =" node "> Węzeł początkowy </ param > public static void WalkTreeThread ( TNode node )

58 58 Rozdział 5. Testy if ( node == null ) return ; Thread left = new Thread (( o) => WalkTreeThread ( node. LeftNode )); left. Start (); Thread right = new Thread (( o) => WalkTreeThread ( node. RightNode )); right. Start (); left. Join (); right. Join (); ProcessItem ( node. Value ); Listing 5.4: Implmenetacja WalkTree z wykorzystaniem klasy Thread Czas wykonania tej wersji to s. Pozostaje wykorzystać Parallel Extension. Prezentuje to listing 5.5. /// <summary > /// Przechodzenie drzewa z wykorzystaniem /// Tasków /// </ summary > /// <param name =" node "> Węzeł początkowy </ param > public static void WalkTreeTasks ( TNode node ) if ( node == null ) return ; Task left = Task. Factory. StartNew (() => WalkTreeTasks ( node. LeftNode )); Task right = Task. Factory. StartNew (() => WalkTreeTasks ( node. RightNode ) ); left. Wait (); right. Wait (); ProcessItem ( node. Value ); Listing 5.5: Implementacja WalkTree z użyciem obiektów Task Czas wykonania takiego kodu to Tabela 5.1 przedstawia zestawienie czasu przejścia drzewa o wysokości cztery w różnych konfiguracjach sprzętowych.

59 5.2 Zbiory Mandelbrota 59 Tabela 5.1: Czas odwiedzenia każdej gałęzi drzewa Wykonanie rekurencyjne Klasa Thread ParallelFX Procesor jednordzeniowy Procesor dwurdzeniowy Jednostka dwuprocesorowa 5.2 Zbiory Mandelbrota Kolejnym testem jest rysowanie zbioru Mandelbrota[18]. Jest to podzbiór płaszczyzny zespolonej, którego brzeg stanowi jeden z najbardziej znanych fraktali. Nazwę zawdzięcza swemu odkrywcy Benoit Mandelbrot. Zbiór możemy przedstawić jako ciąg opisany wzorem: z 0 = 0 z n+1 = zn 2 + p Sam fraktal stanowi brzeg omawianego zbioru. Odnajdujemy go wyliczając kolejne przybliżenia zbioru, które stanowi zbiór liczb zespolonych odpowiednio: - dla przybliżenia 1: wszystkie punkty - dla przybliżenia 2: z 1 < 2 - dla przybliżenia 3: z 1 < 2i z 2 < dla przybliżenia n: z 1 < 2i z 2 < 2,..., z n 1 < 2 (5.1) Przygotowana aplikacja testowa wyświetla fraktal Mandelbrota dla zadanych wartości parametru p, korzystając ze skali szarości do odróżnienia punktów nie należących do zbioru. Przykładowy, wygenerowany przez aplikację fraktal przedstawia rysunek 5.1. Przygotowane zostały trzy wersje kodu generującego fraktal: - sekwencyjny (listing 5.6) - z wykorzystaniem klasy Thread (listing 5.7) - z wykorzystaniem ParallelFX (listing 5.9) private Image SequentialGetBitmap ( double startx, double starty, double endx, double endy ) Color [] cs = new Color [256]; cs = GetColors (); Bitmap bitmap = new Bitmap ( this. picturebox. Width, this. picturebox. Height );

60 60 Rozdział 5. Testy Rysunek 5.1: Przykładowy fraktal Mandelbrota double x, y, x1, y1, xtemp, xmin, xmax, ymin, ymax = 0.0; int iteration = 0; double delatx, deltay = 0.0; xmin = startx ; ymin = starty ; xmax = endx ; ymax = endy ; delatx = ( xmax - xmin ) / this. picturebox. Width ; deltay = ( ymax - ymin ) / this. picturebox. Height ; x = xmin ; for ( int i = 1; i < this. picturebox. Width ; i ++) y = ymin ; for ( int j = 1; j < this. picturebox. Height ; j ++) x1 = 0; y1 = 0; iteration = 0; while ( iteration < 100 && Math. Sqrt (( x1 * x1) + ( y1 * y1)) < 2) iteration ++; xtemp = (x1 * x1) - (y1 * y1) + x; y1 = 2 * x1 * y1 + y; x1 = xtemp ;

61 5.2 Zbiory Mandelbrota 61 double percent = iteration / (100.0) ; int val = (( int )( percent * 255) ); bitmap. SetPixel (i, j, cs[val ]); y += deltay ; x += delatx ; return ( Image ) bitmap ; Listing 5.6: Sekwencyjne generowanie żuka Mandelbrota Bitmap bitmap = null ; Color [] cs = new Color [256]; private Image ThreadGetBitmap ( double startx, double starty, double endx, double endy ) cs = GetColors (); object padlock = new object (); bitmap = new Bitmap ( this. picturebox. Width, this. picturebox. Height ); ParamDTO parameters = new ParamDTO (); parameters. XMin = startx ; parameters. YMin = starty ; parameters. XMax = endx ; parameters. YMax = endy ; parameters. DeltaX = ( endx - startx ) / this. picturebox. Width ; parameters. DeltaY = ( endy - starty ) / this. picturebox. Height ; Thread [] threads = new Thread [ picturebox. Width ]; ParameterizedThreadStart threadstart = new ParameterizedThreadStart ( ThreadAction ); for ( int i = 1; i < this. picturebox. Width ; i ++) threads [ i] = new Thread ( threadstart ); ParamDTO nparams = ( ParamDTO ) parameters. Clone (); nparams. IterationCount = i; threads [i]. Start ( nparams );

62 62 Rozdział 5. Testy threads [i]. Join (); return ( Image ) bitmap ; /// <summary > /// Akcja wykonywana w wątku /// </ summary > /// < param name =" param " > Parametry aktualnej iteracji </ param > public void ThreadAction ( object param ) ParamDTO parameters = ( ParamDTO ) param ; double x = parameters. XMin + ( parameters. IterationCount - 1) * parameters. DeltaX ; double y = parameters. YMin ; for ( int j = 1; j < this. picturebox. Height ; j ++) double x1 = 0; double y1 = 0; int iteration = 0; while ( iteration < 100 && Math. Sqrt (( x1 * x1) + ( y1 * y1)) < 2) iteration ++; double xtemp = ( x1 * x1) - ( y1 * y1) + x; y1 = 2 * x1 * y1 + y; x1 = xtemp ; double percent = iteration / (100.0) ; int val = (( int )( percent * 255) ); lock ( parameters. Padlock ) bitmap. SetPixel ( parameters. IterationCount, j, cs[val ]); y += parameters. DeltaY ; Listing 5.7: Generowanie żuka Mandelbrota z wykorzystaniem klasy Thread private Image ParallelFXGetBitmap ( double startx, double starty, double endx, double endy ) Color [] cs = new Color [256];

63 5.2 Zbiory Mandelbrota 63 cs = GetColors (); object padlock = new object (); Bitmap bitmap = new Bitmap ( this. picturebox. Width, this. picturebox. Height ); double xmin, xmax, ymin, ymax = 0.0; double deltax, deltay = 0.0; xmin = startx ; ymin = starty ; xmax = endx ; ymax = endy ; deltax = ( xmax - xmin ) / this. picturebox. Width ; deltay = ( ymax - ymin ) / this. picturebox. Height ; Parallel. For (1, this. picturebox. Width, i => double x = xmin + ( i - 1) * deltax ; double y = ymin ; for ( int j = 1; j < this. picturebox. Height ; j ++) double x1 = 0; double y1 = 0; int iteration = 0; while ( iteration < 100 && Math. Sqrt (( x1 * x1) + ( y1 * y1)) < 2) iteration ++; double xtemp = ( x1 * x1) - ( y1 * y1) + x; y1 = 2 * x1 * y1 + y; x1 = xtemp ; double percent = iteration / (100.0) ; int val = (( int )( percent * 255) ); lock ( padlock ) bitmap. SetPixel (i, j, cs[val ]); ); y += deltay ; return ( Image ) bitmap ;

64 64 Rozdział 5. Testy Listing 5.8: Generowanie żuka Mandelbrota z wykorzystaniem ParallelFX Logika przedstawionego kodu, opierając się na wersji sekwencyjnej (listing 5.6) nie jest wyjątkowo zawiła. Dla każdego piksela generowanego obrazka wyliczamy zgodnie z równaniem 5.1 poziom przybliżenia i na jego podstawie wybieramy jeden z poziomów szarości, jakim kolorujemy rozpatrywany piksel. Problem pojawia się przy próbie zrównoleglenia operacji (listing 5.7). Po pierwsze pojawiają nam się dwa dodatkowe elementy: - metoda zawierająca kod do wykonania w oddzielnym wątku, - klasa opisująca parametry przekazywane do wątku. Oczywiście całość można zapisać w postaci bardziej skondensowanej, ale stracimy wtedy wiele z przejrzystości kodu. Ciało metody również zostało zmienione, zapewniając odpowiedni dostęp do współdzielonych danych. Dalej przechodzimy do listingu 5.9, gdzie to samo zadanie zostało wykonane z pomocą Parallel Extensions. Oprócz zapewnienia poprawnego dostępu do danych współdzielonych, zmianie uległa tylko jedna linia kodu. Delikatnie zmienił się sposób wywołania nadrzędnej pętli for. Ta instrukcja, pozwala nam wywołać każdą iterację pętli w osobnym zadaniu, które następnie zostaną rozdysponowane pomiędzy wątkami systemowymi. Poprzez zmianę jednej linijki kodu, wprowadziliśmy do aplikacji obsługę wielowątkowści. Sprawdźmy zatem jaki zysk daje nam zrównoleglenie obliczeń w tym przypadku. Tabela 5.2 zawiera czasy wygenerowania fraktala dla parametrów: - StartX = -2,1 - StartY = -1,3 - EndX = EndY = 1.3 Wielkość generowanego obrazka to 1280 na 748 pikseli. Tabela 5.2: Czas generowania fraktala Mandelbrota Wykonanie sekwencyjne Klasa Thread ParallelFX Procesor jednordzeniowy Procesor dwurdzeniowy Jednostka dwuprocesorowa Pierwsze spojrzenie na zamieszczone wyniki i od razu rzuca się w oczy trzy krotnie dłuższy czas wykonania operacji w oparciu o klasę Thread. Błąd nie leży tu jednak w narzędziu, a w sposobie jego wykorzystania. Listing 5.7 przedstawia kod, który tworzy nowy wątek dla każdego piksela szerokości generowanego obrazka. W omawianym przypadku, daje to ogromną liczbę 1280 wątków.

65 5.2 Zbiory Mandelbrota 65 Każdy z tych 1280 obiektów musi zostać stworzony i zainicjowany. Dodatkowo non stop kontekst procesora przełączany jest pomiędzy wątkami, co również odbija się na czasie wykonania całej operacji. Listing 5.9 przedstawia tą samą koncepcję rozwiązania, ale opartą o pule wątków - ThreadPool. Korzystamy w tym przypadku z pewnej ilości reużywalnych wątków, oszczędzając czas na ich tworzeniu i ograniczając ilość zmian kontekstu wykonania. Czasy generowania zbioru Mandelbrota z uwzględnieniem rozwiązania opartego o ThreadPool przedstawia tabela 5.3. private Image ThreadPoolGetBitmap ( double startx, double starty, double endx, double endy ) cs = GetColors (); object padlock = new object (); bitmap = new Bitmap ( this. picturebox. Width, this. picturebox. Height ); ParamDTO parameters = new ParamDTO (); parameters. XMin = startx ; parameters. YMin = starty ; parameters. XMax = endx ; parameters. YMax = endy ; parameters. DeltaX = ( endx - startx ) / this. picturebox. Width ; parameters. DeltaY = ( endy - starty ) / this. picturebox. Height ; Thread [] threads = new Thread [ picturebox. Width ]; ParameterizedThreadStart threadstart = new ParameterizedThreadStart ( ThreadAction ); for ( int i = 1; i < this. picturebox. Width ; i ++) ParamDTO nparams = ( ParamDTO ) parameters. Clone (); nparams. IterationCount = i; ThreadPool. QueueUserWorkItem ( new WaitCallback ( ThreadAction ), nparams ); WaitForThreads (); return ( Image ) bitmap ; Listing 5.9: Generowanie żuka Mandelbrota z wykorzystaniem ThreadPool Widzimy, że to rozwiązanie jest już konkurencyjne wobec korzystania z ParallelExtensions.

66 66 Rozdział 5. Testy Tabela 5.3: Czas generowania fraktala Mandelbrota (z uwzględnieniem ThreadPool) Wykonanie Klasa Klasa ParallelFX sekwencyjne Thread ThreadPool Procesor jednordzeniowy Procesor dwurdzeniowy Jednostka dwuprocesorowa 5.3 Filtry graficzne Ten test, a raczej zbiór testów ma za zadanie porównanie wydajności filtrów i efektów graficznych zaimplementowanych w oparciu o klasę Thread i Parallel Extensions. Wykorzystane zostały filtry będące składowymi dołączonej do niniejszej pracy aplikacji Parallel Image Effects i zostały już omówione w rozdziale jej poświęconym. Dlatego też, po opis poszczególnych funkcji odsyłam do rozdziału 4, a tu skupię się jedynie na otrzymanych wynikach. Wszystkie testy przeprowadzono na tym samym, przedstawionym niżej obrazku 1 (rys. 5.2) o rozmiarach 512x512. Rysunek 5.2: Obrazek wykorzystywany w testach filtrów i efektów graficznych 1 Obrazek pochodzi z kolekcji obrazków przykładowych dla zadań z przedmiotu Przetwarzanie Obrazu. Można go odnaleźć w internecie pod adresem

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1 Współbieżność i równoległość w środowiskach obiektowych Krzysztof Banaś Obliczenia równoległe 1 Java Model współbieżności Javy opiera się na realizacji szeregu omawianych dotychczas elementów: zarządzanie

Bardziej szczegółowo

SZYBKO ZROZUMIEĆ VISUAL BASIC 2012 Artur Niewiarowski -

SZYBKO ZROZUMIEĆ VISUAL BASIC 2012 Artur Niewiarowski - S t r o n a 2 SZYBKO ZROZUMIEĆ VISUAL BASIC 2012 Artur Niewiarowski - Copyright by Artur Niewiarowski 2013 ISBN: 978-83-937802-0-4 - Artur Niewiarowski Self-Publishing - All rights reserved. Wszelkie prawa

Bardziej szczegółowo

Aplikacje w Javie- wykład 11 Wątki-podstawy

Aplikacje w Javie- wykład 11 Wątki-podstawy 1 Aplikacje w Javie- wykład 11 Wątki-podstawy Treści prezentowane w wykładzie zostały oparte o: Barteczko, JAVA Programowanie praktyczne od podstaw, PWN, 2014 http://docs.oracle.com/javase/8/docs/ http://docs.oracle.com/javase/9/docs/

Bardziej szczegółowo

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1 Wątki 1. Wątki - wprowadzenie Wątkiem nazywamy sekwencyjny przepływ sterowania w procesie, który wykonuje dany program np. odczytywanie i zapisywanie plików Program Javy jest wykonywany w obrębie jednego

Bardziej szczegółowo

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego Wątki Wątek - definicja Ciąg instrukcji (podprogram) który może być wykonywane współbieżnie (równolegle) z innymi programami, Wątki działają w ramach tego samego procesu Współdzielą dane (mogą operować

Bardziej szczegółowo

4. Procesy pojęcia podstawowe

4. Procesy pojęcia podstawowe 4. Procesy pojęcia podstawowe 4.1 Czym jest proces? Proces jest czymś innym niż program. Program jest zapisem algorytmu wraz ze strukturami danych na których algorytm ten operuje. Algorytm zapisany bywa

Bardziej szczegółowo

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku.

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku. Laboratorium 7 Wstęp Jednym z podstawowych własności Javy jest wielowątkowość. Wiąże się to z możliwością współbieżnego wykonywania różnych operacji w ramach pojedynczej wirtualnej maszyny Javy (JVM).

Bardziej szczegółowo

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ Procesy i wątki Proces posiada samodzielne środowisko wykonawcze. Proces posiada własny zestaw podstawowych zasobów w czasie wykonywania; W szczególności, każdy proces ma własną przestrzeń pamięci. W uproszczeniu

Bardziej szczegółowo

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Obliczenia równoległe w Microsoft Visual Basic Środowisko Microsoft Visual Studio 2010 i nowsze umożliwia zrównoleglenie obliczeń na wiele rdzeni procesorów. Służą do tego odpowiednie metody dostępne wraz

Bardziej szczegółowo

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej. Polimorfizm jest filarem programowania obiektowego, nie tylko jeżeli chodzi o język C++. Daje on programiście dużą elastyczność podczas pisania programu. Polimorfizm jest ściśle związany z metodami wirtualnymi.

Bardziej szczegółowo

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu. Zrozumienie funkcji danych statycznych jest podstawą programowania obiektowego. W niniejszym artykule opiszę zasadę tworzenia klas statycznych w C#. Oprócz tego dowiesz się czym są statyczne pola i metody

Bardziej szczegółowo

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Uruchomienie programu powoduje stworzenie nowego procesu przez system operacyjny. Proces wykonywany program wraz

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć

Bardziej szczegółowo

4. Procesy pojęcia podstawowe

4. Procesy pojęcia podstawowe 4. Procesy pojęcia podstawowe 4.1 Czym jest proces? Proces jest czymś innym niż program. Program jest zapisem algorytmu wraz ze strukturami danych na których algorytm ten operuje. Algorytm zapisany bywa

Bardziej szczegółowo

Programowanie wielowątkowe. Tomasz Borzyszkowski

Programowanie wielowątkowe. Tomasz Borzyszkowski Programowanie wielowątkowe Tomasz Borzyszkowski Wątki a procesy Jako jeden z niewielu języków programowania Java udostępnia użytkownikowi mechanizmy wspierające programowanie wielowątkowe. Program wielowątkowy

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu Programowanie obiektowe - zestaw 07 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami tworzenia aplikacji okienkowych w C#. Wprowadzenie teoretyczne. Rozważana w

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu Programowanie obiektowe - zestaw 02 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów z wykorzystaniem dziedziczenia.

Bardziej szczegółowo

Język Java wątki (streszczenie)

Język Java wątki (streszczenie) Programowanie współbieżna Język Java wątki (streszczenie) Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej pawel.rogalinski @ pwr.wroc.pl Języka Java wątki Autor:

Bardziej szczegółowo

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki Dariusz Brzeziński Politechnika Poznańska, Instytut Informatyki Język programowania prosty bezpieczny zorientowany obiektowo wielowątkowy rozproszony przenaszalny interpretowany dynamiczny wydajny Platforma

Bardziej szczegółowo

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz Zagadnienia 1. Delegaty wiązane, właściwości indeksowane 2. Delegaty niewiązane 3. Nowa wersja kalkulatora, delegaty

Bardziej szczegółowo

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut. Wyjątki Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut. Wydaje się, że żaden użytkownik oprogramowania nie lubi, kiedy stosowany program nagle zawiesza się,

Bardziej szczegółowo

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak Java język programowania obiektowego Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak 1 Język Java Język Java powstał w roku 1995 w firmie SUN Microsystems Java jest językiem: wysokiego

Bardziej szczegółowo

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04 Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04 Cel zajęć. Celem zajęć jest zapoznanie się ze sposobem działania popularnych kolekcji. Wprowadzenie teoretyczne. Rozważana w ramach niniejszych

Bardziej szczegółowo

Współbieżność w środowisku Java

Współbieżność w środowisku Java Współbieżność w środowisku Java Wątki i ich synchronizacja Zagadnienia Tworzenie wątków Stany wątków i ich zmiana Demony Synchronizacja wątków wzajemne wykluczanie oczekiwanie na zmiennych warunkowych

Bardziej szczegółowo

msgbox("akcja: Początek, argument: " + argument.tostring()); Thread.Sleep(1000); //opóźnienie msgbox("akcja: Koniec"); return DateTime.Now.

msgbox(akcja: Początek, argument:  + argument.tostring()); Thread.Sleep(1000); //opóźnienie msgbox(akcja: Koniec); return DateTime.Now. Programowanie asynchroniczne. Operator await i modyfikator async Język C# 5.0 wyposażony został w nowy operator await, ułatwiający synchronizację dodatkowych zadań uruchomionych przez użytkownika. Poniżej

Bardziej szczegółowo

C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop Spis treści

C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop Spis treści C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop. 2016 Spis treści Spis rysunków 11 Spis tabel 13 Przedmowa 15 Wprowadzenie 17 Podziękowania 27 O autorach 29 1 Wprowadzenie

Bardziej szczegółowo

LINQ TO XML. Autor ćwiczenia: Marcin Wolicki

LINQ TO XML. Autor ćwiczenia: Marcin Wolicki LINQ TO XML Celem ćwiczenia jest zapoznanie się z możliwościami przetwarzania dokumentów XML na platformie.net. W toku zadania zostaną przedstawione dwie technologie: LINQ TO XML i XPath. Autor ćwiczenia:

Bardziej szczegółowo

Podstawy i języki programowania

Podstawy i języki programowania Podstawy i języki programowania Laboratorium 8 - wprowadzenie do obsługi plików tekstowych i wyjątków mgr inż. Krzysztof Szwarc krzysztof@szwarc.net.pl Sosnowiec, 11 grudnia 2017 1 / 34 mgr inż. Krzysztof

Bardziej szczegółowo

Czym jest Java? Rozumiana jako środowisko do uruchamiania programów Platforma software owa

Czym jest Java? Rozumiana jako środowisko do uruchamiania programów Platforma software owa 1 Java Wprowadzenie 2 Czym jest Java? Język programowania prosty zorientowany obiektowo rozproszony interpretowany wydajny Platforma bezpieczny wielowątkowy przenaszalny dynamiczny Rozumiana jako środowisko

Bardziej szczegółowo

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4 Spis treści 1 Wątki 1 2 Tworzenie wątków 1 3 Synchronizacja 3 4 Dodatki 3 5 Algorytmy sortowania 4 6 Klasa Runnable 4 Temat: Wątki Czym są wątki. Grafika. Proste animacje. Małe podsumowanie materiału.

Bardziej szczegółowo

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main. Część XVI C++ Funkcje Jeśli nasz program rozrósł się już do kilkudziesięciu linijek, warto pomyśleć o jego podziale na mniejsze części. Poznajmy więc funkcje. Szybko się przekonamy, że funkcja to bardzo

Bardziej szczegółowo

Podstawy programowania. Wprowadzenie

Podstawy programowania. Wprowadzenie Podstawy programowania Wprowadzenie Proces tworzenia programu Sformułowanie problemu funkcje programu zakres i postać danych postać i dokładność wyników Wybór / opracowanie metody rozwiązania znaleźć matematyczne

Bardziej szczegółowo

Instrukcja laboratoryjna cz.3

Instrukcja laboratoryjna cz.3 Języki programowania na platformie.net cz.2 2015/16 Instrukcja laboratoryjna cz.3 Język C++/CLI Prowadzący: Tomasz Goluch Wersja: 2.0 I. Utworzenie projektu C++/CLI z interfejsem graficznym WPF 1 Cel:

Bardziej szczegółowo

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz Programowanie obiektowe Literatura: Autor: dr inŝ. Zofia Kruczkiewicz Java P. L. Lemay, Naughton R. Cadenhead Java Podręcznik 2 dla kaŝdego Języka Programowania Java Linki Krzysztof Boone oprogramowania

Bardziej szczegółowo

Programowanie wielowątkowe. Jarosław Kuchta

Programowanie wielowątkowe. Jarosław Kuchta Programowanie wielowątkowe Jarosław Kuchta Procesy i wątki w systemie Windows Windows jest systemem wielowątkowym. Każdy proces ma przynajmniej jeden wątek, chociaż może mieć wiele wątków. Start programu,

Bardziej szczegółowo

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych PAŃSTWOWA WYŻSZA SZKOŁA ZAWODOWA W ELBLĄGU INSTYTUT INFORMATYKI STOSOWANEJ Sprawozdanie z Seminarium Dyplomowego Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Bardziej szczegółowo

Programowanie komputerów

Programowanie komputerów Programowanie komputerów Wykład 7: Programowanie wielowątkowe w Javie dr inż. Walery Susłow Współbieżność Programy współbieżne (concurrent software) aplikacje potrafiące wykonywać kilka operacji w tym

Bardziej szczegółowo

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut. Konstruktory Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut. Rozpatrzmy przykład przedstawiający klasę Prostokat: class

Bardziej szczegółowo

SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE

SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE WINDOWS 1 SO i SK/WIN 006 Wydajność systemu 2 SO i SK/WIN Najprostszym sposobem na poprawienie wydajności systemu, jeżeli dysponujemy zbyt małą ilością pamięci RAM

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Podstawowe cechy i możliwości języka Scala mgr inż. Krzysztof Szwarc krzysztof@szwarc.net.pl Sosnowiec, 2017 1 / 32 mgr inż. Krzysztof Szwarc Programowanie obiektowe Informacje

Bardziej szczegółowo

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę.

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę. Języki C i C++ to bardzo uniwersalne platformy programistyczne o ogromnych możliwościach. Wykorzystywane są do tworzenia systemów operacyjnych i oprogramowania użytkowego. Dzięki niskiemu poziomowi abstrakcji

Bardziej szczegółowo

SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE

SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE WINDOWS 1 SO i SK/WIN 007 Tryb rzeczywisty i chroniony procesora 2 SO i SK/WIN Wszystkie 32-bitowe procesory (386 i nowsze) mogą pracować w kilku trybach. Tryby pracy

Bardziej szczegółowo

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003 Obliczenia równoległe i rozproszone w JAVIE Michał Kozłowski 30 listopada 2003 Wątki w JAVIE Reprezentacja wątków jako obiektów Uruchamianie i zatrzymywanie wątków Realizacja wątków Ograniczenia Mechanizmy

Bardziej szczegółowo

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków mgr inż. Maciej Lasota Version 1.0, 13-05-2017 Spis treści Wyjątki....................................................................................

Bardziej szczegółowo

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost; Klasy w C++ są bardzo ważnym narzędziem w rękach programisty. Klasy są fundamentem programowania obiektowego. Z pomocą klas będziesz mógł tworzyć lepszy kod, a co najważniejsze będzie on bardzo dobrze

Bardziej szczegółowo

Java jako język programowania

Java jako język programowania Java jako język programowania Interpretowany programy wykonują się na wirtualnej maszynie (JVM Java Virtual Machine) Składnia oparta o język C++ W pełni zorientowany obiektowo (wszystko jest obiektem)

Bardziej szczegółowo

Języki i paradygmaty programowania - 1

Języki i paradygmaty programowania - 1 doc. dr inż. Tadeusz Jeleniewski e-mail: t.jeleniewski@neostrada.pl tadeusz.jeleniewski@pwr.edu.pl http://www.tjeleniewski.wstt.edu.pl Cele przedmiotu Umiejętność zastosowania i oceny przydatności paradygmatów

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu - zestaw 02 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów z wykorzystaniem dziedziczenia. Wprowadzenie teoretyczne.

Bardziej szczegółowo

Microsoft IT Academy kurs programowania

Microsoft IT Academy kurs programowania Microsoft IT Academy kurs programowania Podstawy języka C# Maciej Hawryluk Język C# Język zarządzany (managed language) Kompilacja do języka pośredniego (Intermediate Language) Kompilacja do kodu maszynowego

Bardziej szczegółowo

REFERAT PRACY DYPLOMOWEJ

REFERAT PRACY DYPLOMOWEJ REFERAT PRACY DYPLOMOWEJ Temat pracy: Projekt i implementacja środowiska do automatyzacji przeprowadzania testów aplikacji internetowych w oparciu o metodykę Behavior Driven Development. Autor: Stepowany

Bardziej szczegółowo

1 Podstawy c++ w pigułce.

1 Podstawy c++ w pigułce. 1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,

Bardziej szczegółowo

Wprowadzenie do języka Java

Wprowadzenie do języka Java WSNHiD, Programowanie 2 Lab. 1 [ część 1 ] Wprowadzenie do języka Java Wprowadzenie Język programowania Java jest obiektowym językiem programowania. Powstał w 1995 i od tej pory był intensywnie rozwijany.

Bardziej szczegółowo

Rozdział 4 KLASY, OBIEKTY, METODY

Rozdział 4 KLASY, OBIEKTY, METODY Rozdział 4 KLASY, OBIEKTY, METODY Java jest językiem w pełni zorientowanym obiektowo. Wszystkie elementy opisujące dane, za wyjątkiem zmiennych prostych są obiektami. Sam program też jest obiektem pewnej

Bardziej szczegółowo

Języki i paradygmaty programowania doc. dr inż. Tadeusz Jeleniewski

Języki i paradygmaty programowania doc. dr inż. Tadeusz Jeleniewski Języki i paradygmaty programowania doc. dr inż. Tadeusz Jeleniewski e-mail: t.jeleniewski@neostrada.pl tadeusz.jeleniewski@pwr.wroc.pl http://www.tjeleniewski.wstt.edu.pl Treści kształcenia: Paradygmaty

Bardziej szczegółowo

Pętle. Dodał Administrator niedziela, 14 marzec :27

Pętle. Dodał Administrator niedziela, 14 marzec :27 Pętlami nazywamy konstrukcje języka, które pozwalają na wielokrotne wykonywanie powtarzających się instrukcji. Przykładowo, jeśli trzeba 10 razy wyświetlić na ekranie pewien napis, to można wykorzystać

Bardziej szczegółowo

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Część XXII C++ w Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Ćwiczenie 1 1. Utwórz nowy projekt w Dev C++ i zapisz go na

Bardziej szczegółowo

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji. JAVA Java jest wszechstronnym językiem programowania, zorientowanym obiektowo, dostarczającym możliwość uruchamiania apletów oraz samodzielnych aplikacji. Java nie jest typowym kompilatorem. Źródłowy kod

Bardziej szczegółowo

Programowanie obiektowe zastosowanie języka Java SE

Programowanie obiektowe zastosowanie języka Java SE Programowanie obiektowe zastosowanie języka Java SE Wstęp do programowania obiektowego w Javie Autor: dr inŝ. 1 Java? Java język programowania obiektowo zorientowany wysokiego poziomu platforma Javy z

Bardziej szczegółowo

Wprowadzenie do projektu QualitySpy

Wprowadzenie do projektu QualitySpy Wprowadzenie do projektu QualitySpy Na podstawie instrukcji implementacji prostej funkcjonalności. 1. Wstęp Celem tego poradnika jest wprowadzić programistę do projektu QualitySpy. Będziemy implementować

Bardziej szczegółowo

Podstawy Programowania 2

Podstawy Programowania 2 Podstawy Programowania 2 Laboratorium 7 Instrukcja 6 Object Pascal Opracował: mgr inż. Leszek Ciopiński Wstęp: Programowanie obiektowe a programowanie strukturalne. W programowaniu strukturalnym, któremu

Bardziej szczegółowo

Task Parallel Library

Task Parallel Library Task Parallel Library Daan Leijen, Wolfram Schulte, and Sebastian Burckhardt prezentacja Michał Albrycht Agenda O potrzebie zrównoleglania Przykłady użycia TPL Tasks and Replicable Tasks Rozdzielanie zadań

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Wykład 2 Marcin Młotkowski 4 marca 2015 Plan wykładu 1 2 3 4 5 Marcin Młotkowski Programowanie obiektowe 2 / 47 Krótki opis C Obiektowy, z kontrolą typów; automatyczne odśmiecanie;

Bardziej szczegółowo

Rozdział 3. Zapisywanie stanu aplikacji w ustawieniach lokalnych

Rozdział 3. Zapisywanie stanu aplikacji w ustawieniach lokalnych Rozdział 3. Zapisywanie stanu aplikacji w ustawieniach lokalnych Jacek Matulewski Materiały dla Podyplomowego Studium Programowania i Zastosowania Komputerów, sekcja Projektowanie i tworzenie aplikacji

Bardziej szczegółowo

Multimedia JAVA. Historia

Multimedia JAVA. Historia Multimedia JAVA mgr inż. Piotr Odya piotrod@sound.eti.pg.gda.pl Historia 1990 rozpoczęcie prac nad nowym systemem operacyjnym w firmie SUN, do jego tworzenia postanowiono wykorzystać nowy język programowania

Bardziej szczegółowo

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak Java: otwórz okienko Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak PLAN WYKŁADU klasy wewnętrzne, lokalne i anonimowe biblioteka AWT zestaw Swing JFrame JPanel komponenty obsługa zdarzeń

Bardziej szczegółowo

WPROWADZENIE DO JĘZYKA JAVA

WPROWADZENIE DO JĘZYKA JAVA WPROWADZENIE DO JĘZYKA JAVA programowanie obiektowe KRÓTKA HISTORIA JĘZYKA JAVA KRÓTKA HISTORIA JĘZYKA JAVA 1991 - narodziny języka java. Pierwsza nazwa Oak (dąb). KRÓTKA HISTORIA JĘZYKA JAVA 1991 - narodziny

Bardziej szczegółowo

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018 Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy

Bardziej szczegółowo

Czym są właściwości. Poprawne projektowanie klas

Czym są właściwości. Poprawne projektowanie klas Z akcesorów get i set korzysta każdy kto programuje w C#. Stanowią one duże udogodnienie w programowaniu obiektowym. Zapewniają wygodę, bezpieczeństwo i znacząco skracają kod. Akcesory są ściśle związane

Bardziej szczegółowo

Zasady programowania Dokumentacja

Zasady programowania Dokumentacja Marcin Kędzierski gr. 14 Zasady programowania Dokumentacja Wstęp 1) Temat: Przeszukiwanie pliku za pomocą drzewa. 2) Założenia projektu: a) Program ma pobierać dane z pliku wskazanego przez użytkownika

Bardziej szczegółowo

Być może jesteś doświadczonym programistą, biegle programujesz w Javie,

Być może jesteś doświadczonym programistą, biegle programujesz w Javie, Kompendium PHP 01 Być może jesteś doświadczonym programistą, biegle programujesz w Javie, C++, Pythonie lub jakimś innym języku programowania, których jak myślę, powstało już tyle, że chyba nie ma osoby,

Bardziej szczegółowo

Zaawansowane aplikacje WWW - laboratorium

Zaawansowane aplikacje WWW - laboratorium Zaawansowane aplikacje WWW - laboratorium Przetwarzanie XML (część 2) Celem ćwiczenia jest przygotowanie aplikacji, która umożliwi odczyt i przetwarzanie pliku z zawartością XML. Aplikacja, napisana w

Bardziej szczegółowo

Podręcznik użytkownika Obieg dokumentów

Podręcznik użytkownika Obieg dokumentów Podręcznik użytkownika Obieg dokumentów Opracowany na potrzeby wdrożenia dla Akademii Wychowania Fizycznego im. Eugeniusza Piaseckiego w Poznaniu W ramach realizacji projektu: Uczelnia jutra wdrożenie

Bardziej szczegółowo

JAVA W SUPER EXPRESOWEJ PIGUŁCE

JAVA W SUPER EXPRESOWEJ PIGUŁCE JAVA W SUPER EXPRESOWEJ PIGUŁCE Obiekt Obiekty programowe to zbiór własności i zachowań (zmiennych i metod). Podobnie jak w świecie rzeczywistym obiekty posiadają swój stan i zachowanie. Komunikat Wszystkie

Bardziej szczegółowo

Expo Composer. www.doittechnology.pl 1. Garncarska 5 70-377 Szczecin tel.: +48 91 404 09 24 e-mail: info@doittechnology.pl. Dokumentacja użytkownika

Expo Composer. www.doittechnology.pl 1. Garncarska 5 70-377 Szczecin tel.: +48 91 404 09 24 e-mail: info@doittechnology.pl. Dokumentacja użytkownika Expo Composer Dokumentacja użytkownika Wersja 1.0 www.doittechnology.pl 1 SPIS TREŚCI 1. O PROGRAMIE... 3 Wstęp... 3 Wymagania systemowe... 3 Licencjonowanie... 3 2. PIERWSZE KROKI Z Expo Composer... 4

Bardziej szczegółowo

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych Obiekty reprezentują pewne pojęcia, przedmioty, elementy rzeczywistości. Obiekty udostępniają swoje usługi: metody operacje,

Bardziej szczegółowo

Spis treści. 1 Java T M

Spis treści. 1 Java T M Spis treści 1 Java T M 1 2 Co to jest Platforma Java T M 1 3 Przygotowanie komputera 2 4 Pierwszy program 2 5 Dokumentacja 3 6 Budowa aplikacji. Klasy. 3 7 Pola i metody 4 8 Konstruktory 5 9 Inne proste

Bardziej szczegółowo

Rozdział 5. Administracja kontami użytkowników

Rozdział 5. Administracja kontami użytkowników Rozdział 5. Administracja kontami użytkowników Ćwiczenia zawarte w tym rozdziale pozwolą przygotować oddzielne środowisko pracy dla każdego użytkownika komputera. Windows XP, w porównaniu do systemów Windows

Bardziej szczegółowo

using System;... using System.Threading;

using System;... using System.Threading; Kontekst synchronizacji Wątek w platformie.net może posiadać kontekst synchronizacji reprezentowany przez instancję klasy SynchronizationContext lub jej klasy potomnej. Jeżeli wątek posiada taki kontekst

Bardziej szczegółowo

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Program, to lista poleceń zapisana w jednym języku programowania zgodnie z obowiązującymi w nim zasadami. Celem programu jest przetwarzanie

Bardziej szczegółowo

Programowanie współbieżne i rozproszone

Programowanie współbieżne i rozproszone Programowanie współbieżne i rozproszone WYKŁAD 1 dr inż. Literatura ogólna Ben-Ari, M.: Podstawy programowania współbieżnego i rozproszonego. Wydawnictwa Naukowo-Techniczne, Warszawa, 2009. Czech, Z.J:

Bardziej szczegółowo

Java EE produkcja oprogramowania

Java EE produkcja oprogramowania Java EE produkcja oprogramowania PPJ PODSTAWY PROGRAMOWANIA W JAVIE PODSTAWY JĘZYKA JAVA 1 Warszawa, 2016Z 2 Ogólna charakterystyka języka Java 3 Java 1/2 Język programowania Java został opracowany przez

Bardziej szczegółowo

REFERAT O PRACY DYPLOMOWEJ

REFERAT O PRACY DYPLOMOWEJ REFERAT O PRACY DYPLOMOWEJ Temat pracy: Projekt i realizacja elektronicznego dziennika ocen ucznia Autor: Grzegorz Dudek wykonanego w technologii ASP.NET We współczesnym modelu edukacji, coraz powszechniejsze

Bardziej szczegółowo

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static), Tworzenie obiektów Dostęp do obiektów jest realizowany przez referencje. Obiekty w języku Java są tworzone poprzez użycie słowa kluczowego new. String lan = new String( Lancuch ); Obszary pamięci w których

Bardziej szczegółowo

Podstawy programowania skrót z wykładów:

Podstawy programowania skrót z wykładów: Podstawy programowania skrót z wykładów: // komentarz jednowierszowy. /* */ komentarz wielowierszowy. # include dyrektywa preprocesora, załączająca biblioteki (pliki nagłówkowe). using namespace

Bardziej szczegółowo

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi EGZAMIN PIERWSZY (25 CZERWCA 2013) JĘZYK C++ poprawiam ocenę pozytywną z egzaminu 0 (zakreśl poniżej x) 1. Wśród poniższych wskaż poprawną formę definicji

Bardziej szczegółowo

Tworzenie prezentacji w MS PowerPoint

Tworzenie prezentacji w MS PowerPoint Tworzenie prezentacji w MS PowerPoint Program PowerPoint dostarczany jest w pakiecie Office i daje nam możliwość stworzenia prezentacji oraz uatrakcyjnienia materiału, który chcemy przedstawić. Prezentacje

Bardziej szczegółowo

5.2. Pierwsze kroki z bazami danych

5.2. Pierwsze kroki z bazami danych 5.2. Pierwsze kroki z bazami danych Uruchamianie programu Podobnie jak inne programy, OO Base uruchamiamy z Menu Start, poprzez zakładkę Wszystkie programy, gdzie znajduje się folder OpenOffice.org 2.2,

Bardziej szczegółowo

Tutorial prowadzi przez kolejne etapy tworzenia projektu począwszy od zdefiniowania przypadków użycia, a skończywszy na konfiguracji i uruchomieniu.

Tutorial prowadzi przez kolejne etapy tworzenia projektu począwszy od zdefiniowania przypadków użycia, a skończywszy na konfiguracji i uruchomieniu. AGH, EAIE, Informatyka Winda - tutorial Systemy czasu rzeczywistego Mirosław Jedynak, Adam Łączyński Spis treści 1 Wstęp... 2 2 Przypadki użycia (Use Case)... 2 3 Diagramy modelu (Object Model Diagram)...

Bardziej szczegółowo

Lab 9 Podstawy Programowania

Lab 9 Podstawy Programowania Lab 9 Podstawy Programowania (Kaja.Gutowska@cs.put.poznan.pl) Wszystkie kody/fragmenty kodów dostępne w osobnym pliku.txt. Materiały pomocnicze: Wskaźnik to specjalny rodzaj zmiennej, w której zapisany

Bardziej szczegółowo

Zakres tematyczny dotyczący podstaw programowania Microsoft Office Excel za pomocą VBA

Zakres tematyczny dotyczący podstaw programowania Microsoft Office Excel za pomocą VBA Zakres tematyczny dotyczący podstaw programowania Microsoft Office Excel za pomocą VBA 1 Rozdział 1 Praca z makropoleceniami Opis: W tym rozdziale kursanci przechodzą przez wprowadzenie do programowania

Bardziej szczegółowo

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

Języki i techniki programowania Ćwiczenia 2

Języki i techniki programowania Ćwiczenia 2 Języki i techniki programowania Ćwiczenia 2 Autor: Marcin Orchel Spis treści: Język C++... 5 Przekazywanie parametrów do funkcji... 5 Przekazywanie parametrów w Javie.... 5 Przekazywanie parametrów w c++...

Bardziej szczegółowo

Programowanie MorphX Ax

Programowanie MorphX Ax Administrowanie Czym jest system ERP? do systemu Dynamics Ax Obsługa systemu Dynamics Ax Wyszukiwanie informacji, filtrowanie, sortowanie rekordów IntelliMorph : ukrywanie i pokazywanie ukrytych kolumn

Bardziej szczegółowo

Ćwiczenie 1. Przygotowanie środowiska JAVA

Ćwiczenie 1. Przygotowanie środowiska JAVA Ćwiczenie 1 Przygotowanie środowiska JAVA 1. Wprowadzenie teoretyczne Instalacja JDK (Java Development Kit) NaleŜy pobrać z java.sun.com środowisko i zainstalować je. Następnie naleŝy skonfigurować środowisko.

Bardziej szczegółowo

Rys. 1. Główne okno programu QT Creator. Na rysunku 2 oznaczone zostały cztery przyciski, odpowiadają kolejno następującym funkcjom:

Rys. 1. Główne okno programu QT Creator. Na rysunku 2 oznaczone zostały cztery przyciski, odpowiadają kolejno następującym funkcjom: 1. QT creator, pierwsze kroki. Qt Creator wieloplatformowe środowisko programistyczne dla języków C++, JavaScript oraz QML, będące częścią SDK dla biblioteki Qt. Zawiera w sobie graficzny interfejs dla

Bardziej szczegółowo

Programowanie zaawansowane

Programowanie zaawansowane Programowanie zaawansowane Ćwiczenie 6 Komunikacja silnie typowana I. Utwórz aplikację okienkową realizującą proste obliczenia arytmetyczne. Obsługa zdarzeń w aplikacji typu Windows Form Application odbywa

Bardziej szczegółowo

Backend Administratora

Backend Administratora Backend Administratora mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 W tym celu korzystając z konsoli wydajemy polecenie: symfony generate:app backend Wówczas zostanie stworzona

Bardziej szczegółowo

Kurs programowania. Wykład 8. Wojciech Macyna

Kurs programowania. Wykład 8. Wojciech Macyna Wykład 8 Program bez watków, jeden procesor, trzy zadania Program z watkami, jeden procesor, trzy zadania Procesory wielordzeniowe, każde zadanie na osobnym procesorze Trzy zadania uruchomione w watkach

Bardziej szczegółowo

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017 Wykład 8 10 maj 2017 Współbieżność Watki w JAVA-ie Współbieżność może być realizowana na poziomie systemu operacyjnego (procesy) lub na poziomie aplikacji (watki). W JAVA-ie powszechnie stosuje się watki.

Bardziej szczegółowo

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C #import "Fraction.h" #import @implementation Fraction -(Fraction*) initwithnumerator: (int) n denominator: (int) d { self = [super init]; } if ( self ) { [self setnumerator: n anddenominator:

Bardziej szczegółowo