Zamknij reklame

Mike'a Asha poświęcony na swoim blogu praktyczne implikacje przejścia na architekturę 64-bitową w iPhonie 5S. Artykuł ten opiera się na jego ustaleniach.

Powodem napisania tego tekstu jest przede wszystkim rozpowszechniana duża ilość dezinformacji na temat tego, co tak naprawdę nowy iPhone 5s z 64-bitowym procesorem ARM oznacza dla użytkowników i rynku. W tym miejscu postaramy się przedstawić obiektywne informacje na temat wydajności, możliwości i konsekwencji tego przejścia dla programistów.

„64-bitowy”

Istnieją dwie części procesora, do których może odnosić się etykieta „X-bit” – szerokość rejestrów całkowitych i szerokość wskaźników. Na szczęście w większości nowoczesnych procesorów szerokości te są takie same, więc w przypadku A7 oznacza to 64-bitowe rejestry całkowite i 64-bitowe wskaźniki.

Jednakże równie ważne jest podkreślenie, co NIE oznacza „64-bitowy”: Rozmiar adresu fizycznego RAM. Liczba bitów potrzebnych do komunikacji z pamięcią RAM (a zatem ilość pamięci RAM, którą może obsłużyć urządzenie) nie jest powiązana z liczbą bitów procesora. Procesory ARM mają adresy od 26 do 40 bitów i można je zmieniać niezależnie od reszty systemu.

  • Rozmiar magistrali danych. Podobnie niezależna od tego czynnika jest ilość danych odbieranych z pamięci RAM lub bufora. Poszczególne instrukcje procesora mogą żądać różnych ilości danych, ale są albo wysyłane w porcjach, albo odbierane z pamięci w większej ilości, niż jest to potrzebne. Zależy to od wielkości kwantu danych. iPhone 5 odbiera już dane z pamięci w kwantach 64-bitowych (i ma 32-bitowy procesor), a możemy spotkać się z rozmiarami do 192 bitów.
  • Wszystko, co dotyczy zmiennoprzecinkowego. Rozmiar takich rejestrów (FPU) jest ponownie niezależny od wewnętrznego działania procesora. ARM używa 64-bitowego FPU jeszcze przed ARM64 (64-bitowy procesor ARM).

Ogólne zalety i wady

Jeśli porównamy skądinąd identyczne architektury 32-bitowe i 64-bitowe, generalnie nie różnią się one zbytnio. Jest to jeden z powodów ogólnego zamieszania wśród opinii publicznej szukającej powodu, dla którego Apple przechodzi na wersję 64-bitową również w urządzeniach mobilnych. Wszystko jednak wynika ze specyficznych parametrów procesora A7 (ARM64) i sposobu, w jaki Apple go wykorzystuje, a nie tylko z faktu, że procesor ma architekturę 64-bitową.

Jeśli jednak nadal przyjrzymy się różnicom między tymi dwiema architekturami, znajdziemy kilka różnic. Oczywistym jest, że 64-bitowe rejestry całkowite mogą wydajniej obsługiwać 64-bitowe liczby całkowite. Już wcześniej można było z nimi pracować na procesorach 32-bitowych, jednak zazwyczaj wiązało się to z podzieleniem ich na kawałki o długości 32-bitowej, co powodowało wolniejsze obliczenia. Zatem procesor 64-bitowy może generalnie wykonywać obliczenia na typach 64-bitowych tak samo szybko, jak na procesorach 32-bitowych. Oznacza to, że aplikacje, które zazwyczaj korzystają z typów 64-bitowych, mogą działać znacznie szybciej na 64-bitowym procesorze.

Chociaż wersja 64-bitowa nie wpływa na całkowitą ilość pamięci RAM wykorzystywanej przez procesor, może ułatwić pracę z dużymi porcjami pamięci RAM w jednym programie. Każdy pojedynczy program działający na 32-bitowym procesorze ma tylko około 4 GB przestrzeni adresowej. Biorąc pod uwagę, że system operacyjny i standardowe biblioteki coś zajmują, programowi pozostaje od 1 do 3 GB na wykorzystanie aplikacji. Jeśli jednak system 32-bitowy ma więcej niż 4 GB pamięci RAM, wykorzystanie tej pamięci jest nieco bardziej skomplikowane. Musimy uciekać się do zmuszania systemu operacyjnego do mapowania większych fragmentów pamięci dla naszego programu (wirtualizacja pamięci) lub możemy podzielić program na wiele procesów (gdzie każdy proces ponownie teoretycznie ma 4 GB pamięci dostępnej do bezpośredniego adresowania).

Jednak te „hacki” są tak trudne i powolne, że korzysta z nich minimalna liczba aplikacji. W praktyce na 32-bitowym procesorze każdy program będzie wykorzystywał tylko swoje 1-3 GB pamięci, a więcej dostępnej pamięci RAM można wykorzystać do uruchamiania wielu programów jednocześnie lub wykorzystać tę pamięć jako bufor (caching). Te zastosowania są praktyczne, ale chcielibyśmy, aby każdy program mógł z łatwością korzystać z fragmentów pamięci większych niż 4 GB.

Teraz dochodzimy do częstego (właściwie błędnego) twierdzenia, że ​​bez więcej niż 4 GB pamięci architektura 64-bitowa jest bezużyteczna. Większa przestrzeń adresowa jest przydatna nawet w systemie z mniejszą ilością pamięci. Pliki mapowane w pamięci to przydatne narzędzie, w którym część zawartości pliku jest logicznie połączona z pamięcią procesu, bez konieczności ładowania całego pliku do pamięci. Dzięki temu system może np. stopniowo przetwarzać duże pliki wielokrotnie większe niż pojemność pamięci RAM. W systemie 32-bitowym tak dużych plików nie można wiarygodnie mapować w pamięci, podczas gdy w systemie 64-bitowym jest to bułka z masłem ze względu na znacznie większą przestrzeń adresową.

Jednak większy rozmiar wskaźników ma również jedną dużą wadę: w przeciwnym razie identyczne programy wymagają więcej pamięci na 64-bitowym procesorze (te większe wskaźniki muszą być gdzieś przechowywane). Ponieważ wskaźniki są częstą częścią programów, różnica ta może obciążyć pamięć podręczną, co z kolei powoduje wolniejsze działanie całego systemu. Z perspektywy czasu widzimy, że gdybyśmy po prostu zmienili architekturę procesora na 64-bitową, faktycznie spowolniłoby to cały system. Zatem czynnik ten należy zrównoważyć większą liczbą optymalizacji w innych miejscach.

ARM64

A7, 64-bitowy procesor napędzający nowy iPhone 5s, to nie tylko zwykły procesor ARM z szerszymi rejestrami. ARM64 zawiera znaczne ulepszenia w stosunku do starszej, 32-bitowej wersji.

Procesor Apple A7.

rejestr

ARM64 mieści dwa razy więcej rejestrów całkowitych niż 32-bitowy ARM (uważaj, aby nie pomylić liczby i szerokości rejestrów - mówiliśmy o szerokości w sekcji „64-bitowe”. Zatem ARM64 ma zarówno dwa razy szersze rejestry, jak i dwa razy więcej rejestry). 32-bitowy ARM posiada 16 rejestrów całkowitych: jeden licznik programu (PC - zawiera numer bieżącej instrukcji), wskaźnik stosu (wskaźnik do wykonywanej funkcji), rejestr łącza (wskaźnik do powrotu po zakończeniu funkcji), a pozostałych 13 służy do użytku aplikacji. Jednakże ARM64 ma 32 rejestry całkowite, w tym jeden rejestr zerowy, rejestr łącza, wskaźnik ramki (podobny do wskaźnika stosu) i jeden zarezerwowany na przyszłość. To pozostawia nam 28 rejestrów do użytku aplikacji, czyli ponad dwukrotnie więcej niż w 32-bitowym ARM. Jednocześnie ARM64 podwoił liczbę rejestrów liczb zmiennoprzecinkowych (FPU) z 16 do 32 rejestrów 128-bitowych.

Ale dlaczego liczba rejestrów jest tak ważna? Pamięć jest generalnie wolniejsza niż obliczenia procesora, a odczyt/zapis może zająć bardzo dużo czasu. Spowodowałoby to, że szybki procesor musiałby czekać na pamięć, a my osiągnęlibyśmy naturalny limit prędkości systemu. Procesory próbują ukryć tę wadę za pomocą warstw buforów, ale nawet najszybszy (L1) jest nadal wolniejszy niż obliczenia procesora. Rejestry są jednak komórkami pamięci znajdującymi się bezpośrednio w procesorze i ich odczyt/zapis jest na tyle szybki, aby nie spowalniać procesora. Liczba rejestrów oznacza w praktyce ilość najszybszej pamięci do obliczeń procesora, co w ogromnym stopniu wpływa na szybkość całego systemu.

Jednocześnie prędkość ta wymaga dobrego wsparcia optymalizacyjnego ze strony kompilatora, aby język mógł korzystać z tych rejestrów i nie musiał przechowywać wszystkiego w ogólnej (wolnej) pamięci aplikacji.

Zestaw instrukcji

ARM64 wprowadza również poważne zmiany w zestawie instrukcji. Zestaw instrukcji to zestaw niepodzielnych operacji, które może wykonać procesor (np. „ADD rejestr1 rejestr2” dodaje liczby z dwóch rejestrów). Z tych instrukcji składają się funkcje dostępne dla poszczególnych języków. Bardziej złożone funkcje muszą wykonywać więcej instrukcji, więc mogą działać wolniej.

Nowością w ARM64 są instrukcje dotyczące szyfrowania AES, funkcji skrótu SHA-1 i SHA-256. Zatem zamiast skomplikowanej implementacji, tylko język wywoła tę instrukcję - co znacznie przyspieszy obliczanie takich funkcji i, miejmy nadzieję, zwiększy bezpieczeństwo aplikacji. Np. nowy Touch ID również wykorzystuje te instrukcje do szyfrowania, zapewniając rzeczywistą szybkość i bezpieczeństwo (teoretycznie atakujący musiałby zmodyfikować sam procesor, aby uzyskać dostęp do danych – co najmniej niepraktyczne, biorąc pod uwagę jego miniaturowy rozmiar).

Kompatybilność z systemem 32-bitowym

Warto wspomnieć, że A7 może w pełni działać w trybie 32-bitowym, bez konieczności emulacji. Oznacza to, że nowy iPhone 5s może bez żadnego spowolnienia uruchamiać aplikacje skompilowane na 32-bitowym ARM. Jednak wtedy nie będzie mógł korzystać z nowych funkcji ARM64, dlatego zawsze warto zrobić specjalny build specjalnie dla A7, który powinien działać znacznie szybciej.

Zmiany w czasie wykonywania

Runtime to kod dodający funkcje do języka programowania, z których może korzystać podczas działania aplikacji, aż do momentu jej przetłumaczenia. Ponieważ Apple nie musi utrzymywać kompatybilności aplikacji (że 64-bitowy plik binarny działa na 32-bitowym), może sobie pozwolić na wprowadzenie kilku dodatkowych ulepszeń w języku Objective-C.

Jednym z nich jest tzw oznakowany wskaźnik (wskaźnik zaznaczony). Zwykle obiekty i wskaźniki do tych obiektów są przechowywane w oddzielnych częściach pamięci. Jednak nowe typy wskaźników umożliwiają klasom z małą ilością danych przechowywanie obiektów bezpośrednio we wskaźniku. Ten krok eliminuje potrzebę alokowania pamięci bezpośrednio dla obiektu, wystarczy utworzyć wskaźnik i znajdujący się w nim obiekt. Oznaczone wskaźniki są obsługiwane tylko w architekturze 64-bitowej, również ze względu na fakt, że we wskaźniku 32-bitowym nie ma już wystarczającej ilości miejsca do przechowywania wystarczającej ilości przydatnych danych. Dlatego iOS, w przeciwieństwie do OS X, nie obsługiwał jeszcze tej funkcji. Jednak wraz z pojawieniem się ARM64 to się zmienia i iOS również pod tym względem dogonił OS X.

Chociaż wskaźniki mają długość 64 bitów, w ARM64 tylko 33 bity są używane na własny adres wskaźnika. A jeśli uda nam się wiarygodnie zdemaskować resztę bitów wskaźnika, to możemy wykorzystać tę przestrzeń do przechowywania dodatkowych danych – tak jak w przypadku wspomnianych wskaźników tagged. Koncepcyjnie jest to jedna z największych zmian w historii Objective-C, chociaż nie jest to funkcja rynkowa – więc większość użytkowników nie będzie wiedziała, w jaki sposób Apple posuwa do przodu Objective-C.

Jeśli chodzi o przydatne dane, które można przechowywać w pozostałej przestrzeni takiego otagowanego wskaźnika, na przykład Objective-C używa go teraz do przechowywania tzw. liczba referencji (liczba referencji). Wcześniej liczba referencji była przechowywana w innym miejscu pamięci, w przygotowanej dla niej tablicy skrótów, jednak w przypadku dużej liczby wywołań alloc/dealloc/retain/release mogło to spowolnić cały system. Tabela musiała być zamknięta ze względu na bezpieczeństwo wątków, więc nie można było jednocześnie zmienić liczby referencji dwóch obiektów w dwóch wątkach. Jednakże wartość ta jest nowo wstawiana do reszty tzw isa wskaźniki. To kolejna niepozorna, ale ogromna zaleta i przyspieszenie w przyszłości. Jednak w architekturze 32-bitowej nie można było tego nigdy osiągnąć.

Informacje o skojarzonych obiektach, czy obiekt ma słabe referencje, czy konieczne jest wygenerowanie destruktora dla obiektu itp., są również na nowo wstawiane w pozostałe miejsce wskaźników do obiektów.Dzięki tej informacji Objective-C runtime jest w stanie zasadniczo przyspieszyć czas działania, co znajduje odzwierciedlenie w szybkości każdej aplikacji. Z testów wynika, że ​​oznacza to około 40-50% przyspieszenia wszystkich wywołań zarządzania pamięcią. Wystarczy przejść na wskaźniki 64-bitowe i wykorzystać tę nową przestrzeń.

záver

Chociaż konkurenci będą starali się szerzyć pogląd, że przejście na architekturę 64-bitową nie jest konieczne, Ty już wiesz, że jest to po prostu bardzo niedoinformowana opinia. Prawdą jest, że przejście na wersję 64-bitową bez dostosowania języka lub aplikacji tak naprawdę nic nie znaczy - a nawet spowalnia cały system. Ale nowy A7 wykorzystuje nowoczesny ARM64 z nowym zestawem instrukcji, a Apple zadał sobie trud modernizacji całego języka Objective-C i wykorzystania nowych możliwości - stąd obiecane przyspieszenie.

Wspomnieliśmy tutaj wiele powodów, dla których architektura 64-bitowa jest właściwym krokiem naprzód. To kolejna rewolucja „pod maską”, dzięki której Apple będzie starał się utrzymać w czołówce nie tylko designem, interfejsem użytkownika i bogatym ekosystemem, ale przede wszystkim najnowocześniejszymi technologiami na rynku.

Źródło: mikeash.com
.