Închide anunțul

Mike Ash dedicat pe blogul lui implicațiile practice ale trecerii la arhitectura pe 64 de biți în iPhone 5S. Acest articol se bazează pe descoperirile sale.

Motivul acestui text se datorează în principal cantității mari de dezinformare răspândită despre ceea ce înseamnă de fapt noul iPhone 5s cu procesor ARM pe 64 de biți pentru utilizatori și piață. Aici vom încerca să aducem informații obiective despre performanța, capacitățile și implicațiile acestei tranziții pentru dezvoltatori.

„64 de biți”

Există două părți ale unui procesor la care se poate referi eticheta „X-bit” - lățimea registrelor întregi și lățimea pointerilor. Din fericire, la majoritatea procesoarelor moderne aceste lățimi sunt aceleași, așa că în cazul A7 asta înseamnă registre întregi de 64 de biți și pointeri de 64 de biți.

Cu toate acestea, este la fel de important să subliniem ce NU înseamnă „64 de biți”: Dimensiunea adresei fizice RAM. Numărul de biți pentru a comunica cu RAM (deci cantitatea de RAM pe care o poate suporta un dispozitiv) nu este legat de numărul de biți CPU. Procesoarele ARM au adrese între 26 și 40 de biți și pot fi modificate independent de restul sistemului.

  • Dimensiunea magistralei de date. Cantitatea de date primite din RAM sau din memoria tampon este în mod similar independentă de acest factor. Instrucțiunile individuale ale procesorului pot solicita cantități diferite de date, dar sunt fie trimise în bucăți, fie primite mai mult decât este necesar din memorie. Depinde de mărimea cuantumului de date. iPhone 5 primește deja date din memorie în quanta de 64 de biți (și are un procesor de 32 de biți), și putem întâlni dimensiuni de până la 192 de biți.
  • Orice este legat de virgulă mobilă. Mărimea unor astfel de registre (FPU) sunt din nou independente de funcționarea internă a procesorului. ARM a folosit FPU pe 64 de biți încă de înainte de ARM64 (procesor ARM pe 64 de biți).

Avantaje și dezavantaje generale

Dacă comparăm arhitecturi identice pe 32 de biți și 64 de biți, în general, acestea nu sunt atât de diferite. Acesta este unul dintre motivele confuziei generale a publicului care caută un motiv pentru care Apple trece la 64 de biți și în dispozitivele mobile. Totuși, totul vine din parametrii specifici ai procesorului A7 (ARM64) și din modul în care Apple îl folosește, nu doar din faptul că procesorul are o arhitectură pe 64 de biți.

Totuși, dacă ne uităm în continuare la diferențele dintre aceste două arhitecturi, vom găsi câteva diferențe. Cel mai evident este că registrele întregi pe 64 de biți pot gestiona mai eficient numerele întregi pe 64 de biți. Chiar și înainte, era posibil să se lucreze cu ele pe procesoare pe 32 de biți, dar acest lucru însemna de obicei împărțirea lor în bucăți lungi de 32 de biți, ceea ce a cauzat calcule mai lente. Deci, un procesor pe 64 de biți poate calcula în general cu tipuri de 64 de biți la fel de rapid ca și cu cele pe 32 de biți. Aceasta înseamnă că aplicațiile care folosesc în general tipuri pe 64 de biți pot rula mult mai rapid pe un procesor pe 64 de biți.

Deși 64 de biți nu afectează cantitatea totală de RAM pe care o poate folosi procesorul, poate facilita lucrul cu cantități mari de RAM într-un singur program. Orice program care rulează pe un procesor pe 32 de biți are doar aproximativ 4 GB spațiu de adrese. Ținând cont de faptul că sistemul de operare și bibliotecile standard ocupă ceva, acest lucru lasă programul cu undeva între 1-3 GB pentru utilizarea aplicației. Cu toate acestea, dacă un sistem pe 32 de biți are mai mult de 4 GB de RAM, utilizarea acelei memorie este puțin mai complicată. Trebuie să recurgem la forțarea sistemului de operare să mapeze aceste bucăți mai mari de memorie pentru programul nostru (virtualizarea memoriei), sau putem împărți programul în mai multe procese (unde fiecare proces are din nou teoretic 4 GB de memorie disponibilă pentru adresare directă).

Cu toate acestea, aceste „hack-uri” sunt atât de dificile și lente încât un minim de aplicații le folosesc. În practică, pe un procesor pe 32 de biți, fiecare program își va folosi doar 1-3 GB de memorie, iar mai multă RAM disponibilă poate fi folosită pentru a rula mai multe programe în același timp sau pentru a folosi această memorie ca buffer (caching). Aceste utilizări sunt practice, dar am dori ca orice program să poată utiliza cu ușurință bucăți de memorie mai mari de 4 GB.

Acum ajungem la afirmația frecventă (de fapt incorectă) că fără mai mult de 4 GB de memorie, o arhitectură pe 64 de biți este inutilă. Un spațiu de adrese mai mare este util chiar și pe un sistem cu memorie mai mică. Fișierele mapate în memorie sunt un instrument util în care o parte din conținutul fișierului este legată logic de memoria procesului, fără ca întregul fișier să fie încărcat în memorie. Astfel, sistemul poate, de exemplu, să proceseze treptat fișiere mari de multe ori mai mari decât capacitatea RAM. Pe un sistem pe 32 de biți, fișierele atât de mari nu pot fi mapate în mod fiabil în memorie, în timp ce pe un sistem pe 64 de biți, este o simplă simplitate, datorită spațiului de adrese mult mai mare.

Cu toate acestea, dimensiunea mai mare a pointerilor aduce și un mare dezavantaj: altfel, programele identice au nevoie de mai multă memorie pe un procesor pe 64 de biți (acești pointeri mai mari trebuie să fie stocați undeva). Deoarece pointerii sunt o parte frecventă a programelor, această diferență poate îngreuna memoria cache, ceea ce, la rândul său, face ca întregul sistem să funcționeze mai lent. Deci, în perspectivă, putem vedea că dacă am schimba doar arhitectura procesorului la 64 de biți, ar încetini de fapt întregul sistem. Deci, acest factor trebuie echilibrat prin mai multe optimizări în alte locuri.

ARM64

A7, procesorul pe 64 de biți care alimentează noul iPhone 5s, nu este doar un procesor ARM obișnuit cu registre mai largi. ARM64 conține îmbunătățiri majore față de versiunea mai veche, pe 32 de biți.

procesor Apple A7.

Registru

ARM64 deține de două ori mai multe registre întregi decât ARM pe 32 de biți (ai grijă să nu confundi numărul și lățimea registrelor - am vorbit despre lățime în secțiunea „64 de biți”. Deci ARM64 are ambele registre de două ori mai largi și de două ori mai multe registre). ARM-ul pe 32 de biți are 16 registre întregi: un numărător de program (PC - conține numărul instrucțiunii curente), un pointer de stivă (un pointer către o funcție în curs), un registru de legătură (un pointer către revenirea după sfârșit). al funcției), iar restul de 13 sunt pentru utilizarea aplicației. Cu toate acestea, ARM64 are 32 de registre întregi, inclusiv un registru zero, un registru de legătură, un indicator de cadru (similar cu un pointer de stivă) și unul rezervat pentru viitor. Acest lucru ne lasă cu 28 de registre pentru utilizarea aplicației, mai mult decât dublu față de ARM pe 32 de biți. În același timp, ARM64 a dublat numărul de registre cu numere în virgulă mobilă (FPU) de la 16 la 32 de registre pe 128 de biți.

Dar de ce este atât de important numărul de registre? Memoria este în general mai lentă decât calculele CPU, iar citirea/scrierea poate dura foarte mult timp. Acest lucru ar face ca procesorul rapid să fie nevoit să aștepte în continuare memorie și am atinge limita naturală de viteză a sistemului. Procesoarele încearcă să ascundă acest handicap cu straturi de buffere, dar chiar și cel mai rapid (L1) este tot mai lent decât calculul procesorului. Cu toate acestea, registrele sunt celule de memorie direct în procesor și citirea/scrierea lor este suficient de rapidă pentru a nu încetini procesorul. Numărul de registre înseamnă practic cantitatea de memorie cea mai rapidă pentru calculele procesorului, ceea ce afectează foarte mult viteza întregului sistem.

În același timp, această viteză are nevoie de un suport bun de optimizare din partea compilatorului, astfel încât limbajul să poată folosi acești registre și să nu fie nevoit să stocheze totul în memoria generală a aplicației (înceata).

Set de instructiuni

ARM64 aduce, de asemenea, modificări majore setului de instrucțiuni. Un set de instrucțiuni este un set de operații atomice pe care le poate efectua un procesor (de exemplu, „ADD register1 register2” adaugă numerele în două registre). Funcțiile disponibile pentru fiecare limbă sunt compuse din aceste instrucțiuni. Funcțiile mai complexe trebuie să execute mai multe instrucțiuni, astfel încât să poată fi mai lente.

Nou în ARM64 sunt instrucțiunile pentru criptarea AES, funcțiile hash SHA-1 și SHA-256. Deci, în loc de o implementare complexă, doar limbajul va numi această instrucțiune - ceea ce va aduce o accelerare uriașă la calculul unor astfel de funcții și, sperăm, va adăuga securitate în aplicații. De exemplu. noul Touch ID folosește, de asemenea, aceste instrucțiuni în criptare, permițând viteză și securitate reală (teoretic, un atacator ar trebui să modifice însuși procesorul pentru a accesa datele - ceea ce este cel puțin nepractic având în vedere dimensiunea sa în miniatură).

Compatibilitate cu 32 de biți

Este important de menționat că A7 poate rula complet în modul pe 32 de biți fără a fi nevoie de emulare. Înseamnă că noul iPhone 5s poate rula aplicații compilate pe 32 de biți ARM fără nicio încetinire. Cu toate acestea, atunci nu poate folosi noile funcții ARM64, așa că merită întotdeauna să faci o construcție specială doar pentru A7, care ar trebui să ruleze mult mai repede.

Modificări ale timpului de rulare

Runtime este codul care adaugă funcții limbajului de programare, pe care le poate folosi în timp ce aplicația rulează, până după traducere. Deoarece Apple nu trebuie să mențină compatibilitatea aplicațiilor (că un binar pe 64 de biți rulează pe 32 de biți), și-ar putea permite să mai facă câteva îmbunătățiri în limbajul Objective-C.

Unul dintre ele este așa-numitul indicator etichetat (indicator marcat). În mod normal, obiectele și pointerii către acele obiecte sunt stocate în părți separate ale memoriei. Cu toate acestea, noile tipuri de pointer permit claselor cu puține date să stocheze obiecte direct în pointer. Acest pas elimină necesitatea de a aloca memorie direct pentru obiect, doar creați un pointer și obiectul din interiorul acestuia. Pointerii etichetate sunt acceptate doar în arhitectura pe 64 de biți și datorită faptului că nu mai există suficient spațiu într-un pointer pe 32 de biți pentru a stoca suficiente date utile. Prin urmare, iOS, spre deosebire de OS X, nu a acceptat încă această caracteristică. Cu toate acestea, odată cu sosirea lui ARM64, acest lucru se schimbă, iar iOS a ajuns din urmă cu OS X și în acest sens.

Deși pointerii au o lungime de 64 de biți, pe ARM64 sunt utilizați doar 33 de biți pentru adresa proprie a pointerului. Și dacă suntem capabili să demascăm în mod fiabil restul biților pointerului, putem folosi acest spațiu pentru a stoca date suplimentare - ca în cazul pointerelor etichetate menționate. Din punct de vedere conceptual, aceasta este una dintre cele mai mari schimbări din istoria Objective-C, deși nu este o caracteristică comercializabilă - așa că majoritatea utilizatorilor nu vor ști cum Apple avansează Objective-C.

În ceea ce privește datele utile care pot fi stocate în spațiul rămas al unui astfel de pointer etichetat, Objective-C, de exemplu, le folosește acum pentru a stoca așa-numitul număr de referințe (număr de referințe). Anterior, numărul de referințe era stocat într-un loc diferit în memorie, într-un tabel hash pregătit pentru acesta, dar acest lucru ar putea încetini întregul sistem în cazul unui număr mare de apeluri alloc/dealloc/retain/release. Tabelul a trebuit să fie blocat din cauza siguranței firului, astfel încât numărul de referință a două obiecte din două fire nu a putut fi schimbat în același timp. Cu toate acestea, această valoare este nou introdusă în restul așa-numitelor isa indicatori. Acesta este un alt avantaj discret, dar uriaș și o accelerare în viitor. Cu toate acestea, acest lucru nu ar putea fi niciodată realizat într-o arhitectură pe 32 de biți.

Informațiile despre obiectele asociate, dacă obiectul este slab referit, dacă este necesar să se genereze un destructor pentru obiect etc., sunt de asemenea nou introduse în locul rămas al pointerilor către obiecte. Mulțumită acestor informații, Objective-C runtime este capabil să accelereze în mod fundamental timpul de rulare, ceea ce se reflectă în viteza fiecărei aplicații. Din testare, aceasta înseamnă aproximativ 40-50% accelerare a tuturor apelurilor de gestionare a memoriei. Doar trecând la pointerii pe 64 de biți și folosind acest spațiu nou.

Concluzie

Deși concurenții vor încerca să răspândească ideea că trecerea la o arhitectură pe 64 de biți este inutilă, veți ști deja că aceasta este doar o părere foarte neinformată. Este adevărat că trecerea la 64 de biți fără a vă adapta limba sau aplicațiile nu înseamnă nimic - chiar încetinește întregul sistem. Dar noul A7 folosește un ARM64 modern cu un nou set de instrucțiuni, iar Apple și-a dat osteneala să modernizeze întreg limbajul Objective-C și să profite de noile capabilități - de aici și accelerarea promisă.

Aici am menționat un număr mare de motive pentru care o arhitectură pe 64 de biți este pasul corect înainte. Este o altă revoluție „sub capotă”, datorită căreia Apple va încerca să rămână în frunte nu doar prin design, interfață cu utilizatorul și ecosistem bogat, ci mai ales cu cele mai moderne tehnologii de pe piață.

sursa: mikeash.com
.