Symulatory systemów komputerowych: znany wszystkim pełnopłatny symulator oraz mniej znane symulatory taktyczne i tras

W drugiej części artykułu o symulatorach systemów komputerowych nadal będę w prosty sposób przedstawiać symulatory komputerowe, a mianowicie symulację w pełnej platformie, z którą najczęściej styka się zwykły użytkownik, a także model taktowany i trasy, które są bardziej rozpowszechnione w kręgach deweloperów.

Symulatory systemów komputerowych: znany wszystkim pełnopłatny symulator oraz mniej znane symulatory taktyczne i tras

W pierwszej części Opowiedziałem, czym są w ogóle symulatory, a także o poziomach modelowania. Teraz, opierając się na tej wiedzy, proponuję zanurkować nieco głębiej i porozmawiać o symulacji w pełnej platformie, o tym, jak zbierać trasy, co z nimi potem robić, a także o mikroarchitekturze opartej na modelu taktowanym.

Symulator w pełnej platformie (full platform simulator), czyli „Jeden w polu — nie wojownik”

Jeśli konieczne jest zbadanie pracy jednego konkretnego urządzenia, na przykład karty sieciowej, lub napisanie dla tego urządzenia oprogramowania układowego lub sterownika, to takie urządzenie można modelować oddzielnie. Jednak używanie go w oderwaniu od reszty infrastruktury nie jest zbyt wygodne. Aby uruchomić odpowiedni sterownik, potrzebny będzie procesor centralny, pamięć, dostęp do magistrali do przesyłania danych i inne. Ponadto, do działania sterownika potrzebny jest system operacyjny (OS) oraz stos sieciowy. Dodatkowo może być wymagany oddzielny generator pakietów i serwer do odbioru odpowiedzi.

Symulator w pełnej platformie tworzy środowisko do uruchamiania pełnego stosu oprogramowania, który obejmuje wszystko, od BIOS-u i bootloadera po sam system operacyjny i różne jego podsystemy, takie jak ten sam stos sieciowy, sterowniki, aplikacje na poziomie użytkownika. W tym celu zrealizowane są programowe modele większości urządzeń komputerowych: procesora i pamięci, dysku, urządzeń wejścia-wyjścia (klawiatura, mysz, wyświetlacz), a także wspomniana karta sieciowa.

Poniżej znajduje się schemat blokowy chipsetu x58 firmy Intel. W pełno-platformowym symulatorze komputera na tym chipsecie niezbędna jest implementacja większości wymienionych urządzeń, w tym tych, które znajdują się wewnątrz IOH (Input/Output Hub) i ICH (Input/Output Controller Hub), które nie zostały szczegółowo narysowane na schemacie blokowym. Jednak jak pokazuje praktyka, nie jest tak mało urządzeń, które nie są wykorzystywane przez oprogramowanie, które zamierzamy uruchomić. Modeli takich urządzeń nie trzeba tworzyć.

Symulatory systemów komputerowych: znany wszystkim pełnopłatny symulator oraz mniej znane symulatory taktyczne i tras

Najczęściej pełno-platformowe symulatory są realizowane na poziomie instrukcji procesora (ISA, zob. poprzedni artykuł). Pozwala to na stosunkowo szybkie i niedrogie stworzenie samego symulatora. Poziom ISA jest również dobry, ponieważ pozostaje bardziej lub mniej stały, w przeciwieństwie do na przykład poziomu API/ABI, który zmienia się częściej. Dodatkowo implementacja na poziomie instrukcji pozwala na uruchamianie tzw. niezmodyfikowanego binarnego oprogramowania, czyli uruchamianie już skompilowanego kodu bez jakichkolwiek zmian, dokładnie w takim kształcie, w jakim jest używane na rzeczywistym sprzęcie. Innymi słowy, można zrobić kopię („dump”) dysku twardego, wskazać go jako obraz dla modelu w pełno-platformowym symulatorze i – voila! – system operacyjny i inne programy ładują się w symulatorze bez żadnych dodatkowych działań.

Wydajność symulatorów

Symulatory systemów komputerowych: znany wszystkim pełnopłatny symulator oraz mniej znane symulatory taktyczne i tras

Jak wspomniano trochę wyżej, sam proces symulacji całego systemu, czyli wszystkich jego urządzeń, jest dość wolnym przedsięwzięciem. Jeśli jeszcze do tego zrealizować to na bardzo szczegółowym poziomie, na przykład mikroarchitektonicznym lub logicznym, to wykonanie stanie się ekstremalnie wolne. Natomiast poziom instrukcji jest odpowiednim wyborem i pozwala na działanie systemu operacyjnego i programów z prędkościami, które są wystarczające dla użytkownika do komfortowej interakcji z nimi.

Tutaj warto poruszyć temat wydajności symulatorów. Zwykle mierzy się ją w IPS (instrukcjach na sekundę), a dokładniej w MIPS (miliony IPS), czyli ilości instrukcji procesora wykonanych przez symulator w ciągu jednej sekundy. Jednocześnie prędkość symulacji zależy także od wydajności systemu, na którym sama symulacja działa. Dlatego, być może, właściwiej byłoby mówić o "spowolnieniu" (slowdown) symulatora w porównaniu z oryginalnym systemem.

Najczęściej spotykane na rynku pełnoplatformowe symulatory, takie jak QEMU, VirtualBox czy VmWare Workstation, oferują przyzwoitą wydajność. Użytkownik może nawet nie zauważyć, że praca odbywa się w symulatorze. Dzieje się tak dzięki specjalnej funkcji w procesorach, którą jest wirtualizacja, algorytmom translacji binarnej oraz innym interesującym rozwiązaniom. To wszystko jest temat na osobny artykuł, ale krótko mówiąc, wirtualizacja to sprzętowa zdolność współczesnych procesorów, która pozwala symulatorom nie symulować instrukcji, a bezpośrednio przekazywać je do wykonania do rzeczywistego procesora, o ile architektury symulatora i procesora są podobne. Translacja binarna jest to konwersja kodu maszynowego gościa na kod maszyny gospodarza i jego późniejsze wykonywanie na rzeczywistym procesorze. W rezultacie symulacja jest tylko nieznacznie wolniejsza, od 5 do 10 razy, a często działa z tą samą prędkością, co rzeczywisty system. Chociaż wpływa na to wiele czynników. Na przykład, jeśli chcemy symulować system z kilkudziesięcioma procesorami, prędkość natychmiast spadnie o te kilka dziesiątek razy. Z drugiej strony, symulatory takie jak Simics w najnowszych wersjach wspierają wieloprocesorowy sprzęt gospodarza i skutecznie równolegle rozdzielają symulowane rdzenie na rdzenie rzeczywistego procesora.

Jeśli chodzi o prędkość symulacji mikroarchitektur, to z reguły jest ona o kilka rzędów wielkości wolniejsza, około 1000-10000 razy, niż wykonanie na zwykłym komputerze, bez symulacji. A realizacje na poziomie elementów logicznych są jeszcze wolniejsze o kilka rzędów. Dlatego w roli emulatora na tym poziomie wykorzystuje się FPGA, co znacznie zwiększa wydajność.

Wykres poniżej pokazuje przybliżoną zależność prędkości symulacji od szczegółowości modelu.

Symulatory systemów komputerowych: znany wszystkim pełnopłatny symulator oraz mniej znane symulatory taktyczne i tras

Symulacja taktów

Mimo niewielkiej prędkości działania, symulatory mikroarchitektury są dość powszechne. Modelowanie wewnętrznych bloków procesora jest konieczne, aby dokładnie symulować czas wykonania każdej instrukcji. Może tu pojawić się nieporozumienie – ponieważ, wydawałoby się, dlaczego po prostu nie zaprogramować czasu wykonania dla każdej instrukcji. Ale taki symulator będzie działać bardzo niedokładnie, ponieważ czas wykonania tej samej instrukcji może różnić się z wywołania na wywołanie.

Najprostszy przykład – instrukcja dostępu do pamięci. Jeśli żądana komórka pamięci jest dostępna w cache, czas wykonania będzie minimalny. Jeśli w cache brak tej informacji ("cache miss"), znacznie zwiększy to czas wykonania instrukcji. W związku z tym do dokładnej symulacji konieczny jest model cache. Jednak na modelu cache sprawa się nie kończy. Procesor nie będzie po prostu czekał na uzyskanie danych z pamięci, gdy ich brakuje w cache. Zamiast tego zacznie wykonywać kolejne instrukcje, wybierając takie, które nie są zależne od wyniku odczytu z pamięci. To tzw. wykonanie „nie w porządku” (OOO, out of order execution), które jest konieczne, aby zminimalizować czas bezczynności procesora. Uwzględnienie tego wszystkiego podczas obliczania czasu wykonania instrukcji pomoże modelowanie odpowiednich bloków procesora. Wśród tych instrukcji, wykonywanych podczas oczekiwania na wynik odczytu z pamięci, może się pojawić operacja warunkowego przejścia. Jeśli wynik spełnienia warunku jest w tej chwili nieznany, procesor ponownie nie zatrzymuje wykonania, lecz dokonuje „założenia”, wykonuje odpowiednie przejście i kontynuuje proaktywne wykonywanie instrukcji z miejsca przejścia. Taki blok, nazywany predyktorem gałęzi, również musi być zaimplementowany w symulatorze mikroarchitektury.

Obrazek poniżej pokazuje główne bloki procesora, których znajomość nie jest konieczna, podano go tylko po to, aby pokazać złożoność realizacji mikroarchitektury.

Symulatory systemów komputerowych: znany wszystkim pełnopłatny symulator oraz mniej znane symulatory taktyczne i tras

Praca wszystkich tych bloków w rzeczywistym procesorze jest synchronizowana za pomocą specjalnych sygnałów zegarowych, podobnie jak w modelu. Taki symulator mikroarchitektury nazywa się symulatorem cykli (cycle accurate). Główne jego zadanie to dokładne prognozowanie wydajności rozwijanego procesora i/lub obliczanie czasu wykonania określonego programu, na przykład jakiegoś benchmarku. Jeśli wartości będą niższe od wymaganych, konieczne będzie dopracowanie algorytmów i bloków procesora lub optymalizacja programu.

Jak pokazano powyżej, symulacja cykli jest bardzo wolna, dlatego stosuje się ją tylko przy badaniu określonych aspektów działania programu, gdzie konieczne jest poznanie rzeczywistej prędkości wykonania programów i ocena przyszłej wydajności urządzenia, którego prototyp jest modelowany.

Na czas symulacji pozostałych działań programu wykorzystywany jest symulator funkcjonalny. Jak takie skojarzone wykorzystanie przebiega w rzeczywistości? Najpierw uruchamiany jest symulator funkcjonalny, na którym ładowany jest system operacyjny i wszystko, co potrzebne do uruchomienia badanej aplikacji. Nie interesuje nas ani sam system operacyjny, ani początkowe etapy uruchamiania programu, jego konfiguracja itp. Jednak nie możemy również pominąć tych części i od razu przejść do wykonania programu z połowy. Dlatego wszystkie te wstępne etapy są realizowane na symulatorze funkcjonalnym. Po tym, jak program wykona się do interesującego nas momentu, istnieją dwie możliwości. Można zamienić model na cykliczny i kontynuować wykonanie. Tryb symulacji, w którym wykorzystywany jest kod wykonywalny (tj. zwykłe skompilowane pliki programów), nazywa się symulacją opartą na wykonaniu (execution driven simulation). Jest to najpopularniejsza forma symulacji. Możliwe jest również inne podejście – symulacja oparta na trasach (trace driven simulation).

Symulacja oparta na trasach

Składa się z dwóch kroków. Za pomocą symulatora funkcjonalnego lub na rzeczywistej maszynie zbiera się i zapisuje do pliku dziennik działań programu. Taki dziennik nazywa się trasą (trace). W zależności od tego, co jest badane, trasa może zawierać wykonywalne instrukcje, adresy pamięci, numery portów, informacje o przerwaniach.

Kolejnym krokiem jest „odtwarzanie” trasy, kiedy symulator cykli odczytuje trasę i wykonuje wszystkie instrukcje w niej zapisane. Na końcu uzyskujemy czas wykonania tego fragmentu programu oraz różne charakterystyki tego procesu, na przykład procent trafień w pamięci podręcznej.

Ważną cechą pracy z trasami jest deterministyczność, to znaczy, uruchamiając symulację w opisany powyżej sposób, wielokrotnie reprodukujemy tę samą sekwencję działań. Umożliwia to, zmieniając parametry modelu (rozmiary pamięci podręcznej, buforów i kolejek) oraz wykorzystując różne algorytmy wewnętrzne lub je dostosowując, badać, jak dany parametr wpływa na wydajność systemu i która opcja daje najlepsze wyniki. Wszystko to można przeprowadzić z modelem prototypu urządzenia przed stworzeniem rzeczywistego prototypu sprzętowego.

Złożoność tego podejścia polega na konieczności wcześniejszego uruchomienia aplikacji i zebrania trasy, a także ogromnego rozmiaru pliku z trasą. Do zalet można zaliczyć to, że wystarczy zamodelować jedynie interesującą część urządzenia lub platformy, podczas gdy symulacja wykonania zazwyczaj wymaga pełnego modelu.

Zatem w tym artykule omówiliśmy cechy symulacji na pełnej platformie, porozmawialiśmy o szybkości realizacji na różnych poziomach, symulacji cykli oraz tras. W następnym artykule opiszę główne scenariusze wykorzystania symulatorów, zarówno w celach osobistych, jak i z punktu widzenia rozwoju w dużych firmach.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster