Tytuł oryginalny: „Architektura kleju i koprocesora”
Autor: Vitalik Buterin, założyciel Ethereum
Opracował: Deng Tong, Golden Finance
Specjalne podziękowania dla Justina Drake’a, Georgiosa Konstantopoulosa, Andreja Karpathy’ego, Michaela Gao, Tarun Chitra i różnych współpracowników Flashbota za ich opinie i komentarze.
Jeśli przeanalizujesz z umiarkowaną szczegółowością wszelkie obliczenia wymagające dużych zasobów we współczesnym świecie, jedną z cech, którą raz po raz odkryjesz, jest to, że obliczenia można podzielić na dwie części:
Stosunkowo niewielka ilość „logiki biznesowej”, która jest złożona, ale nie wymaga intensywnych obliczeń;
Dużo intensywnej, ale wysoce zorganizowanej „kosztownej pracy”.
Te dwie formy przetwarzania danych najlepiej obsługiwać na różne sposoby: pierwszą, której architektura może być mniej wydajna, ale musi być bardzo ogólna; drugą, której architektura może być mniej ogólna, ale musi być bardzo wydajna.
Jakie są przykłady tego odmiennego podejścia w praktyce?
Najpierw przyjrzyjmy się środowisku, które znam najlepiej: maszynie wirtualnej Ethereum (EVM). Oto ślad debugowania gethów ostatniej transakcji Ethereum, którą przeprowadziłem: Aktualizacja skrótu IPFS mojego bloga na ENS. W ramach tej transakcji zużyto łącznie 46924 gazu i można go sklasyfikować w następujący sposób:
Koszt podstawowy: 21 000
Dane połączeń: 1556
Wykonanie EVM: 24 368
Kod operacji SLOAD: 6400
Kod operacji SSTORE: 10,100
Kod operacji LOG: 2149
Inne: 6719
Ślad EVM aktualizacji skrótu ENS. Przedostatnia kolumna to zużycie gazu.
Morał z tej historii jest następujący: większość wykonania (około 73%, jeśli spojrzysz tylko na EVM, około 85%, jeśli uwzględnisz podstawową część kosztów obejmującą obliczenia) koncentruje się na bardzo małej liczbie ustrukturyzowanych, kosztownych operacji: odczyty pamięci i zapisuje, rejestruje i szyfruje (koszt podstawowy obejmuje 3000 za weryfikację podpisu płatności, EVM obejmuje również 272 za hashowanie płatności). Pozostała część wykonania to „logika biznesowa”: zamiana bitów danych wywołania w celu wyodrębnienia identyfikatora rekordu, który próbuję ustawić, i skrótu, dla którego go ustawiam itp. W przypadku transferu tokenów będzie to obejmować dodawanie i odejmowanie sald, w bardziej zaawansowanych aplikacjach może to obejmować rotacje itp.
W EVM te dwie formy wykonania są obsługiwane inaczej. Logika biznesowa wysokiego poziomu jest napisana w języku wyższego poziomu, zwykle Solidity, który kompiluje się do EVM. Kosztowna praca jest nadal wykonywana przez kody operacji EVM (SLOAD itp.), ale ponad 99% rzeczywistych obliczeń odbywa się w dedykowanych modułach napisanych bezpośrednio w kodzie klienta (lub nawet bibliotekach).
Aby lepiej zrozumieć ten wzorzec, przyjrzyjmy się mu w innym kontekście: kod AI napisany w Pythonie przy użyciu latarki.
Przejście do przodu bloku modelu transformatora
Co tu widzimy? Widzieliśmy stosunkowo niewielką ilość „logiki biznesowej” napisanej w Pythonie, która opisuje strukturę wykonywanych operacji. W prawdziwej aplikacji będzie istniał inny rodzaj logiki biznesowej, która określa szczegóły, takie jak sposób uzyskania danych wejściowych i co zrobić z wynikami. Jeśli jednak zagłębimy się w każdą indywidualną operację (poszczególne kroki w self.norm, torch.cat, +, *, self.attn...), zobaczymy obliczenia wektorowe: te same operacje są obliczane masowo w wartościach równoległych . Podobnie jak w pierwszym przykładzie, niewielka część obliczeń jest wykorzystywana do logiki biznesowej, a większość obliczeń służy do wykonywania dużych strukturalnych operacji macierzowych i wektorowych - w rzeczywistości większość z nich to po prostu mnożenia macierzy.
Podobnie jak w przykładzie EVM, te dwa rodzaje pracy są obsługiwane na dwa różne sposoby. Kod logiki biznesowej wysokiego poziomu jest napisany w Pythonie, języku bardzo wszechstronnym i elastycznym, ale także bardzo powolnym, a my po prostu akceptujemy tę nieefektywność, ponieważ stanowi ona tylko niewielką część całkowitych kosztów obliczeniowych. Tymczasem intensywne operacje są pisane w wysoce zoptymalizowanym kodzie, często kodzie CUDA, który działa na GPU. Coraz częściej zaczynamy nawet widzieć wnioskowanie LLM przeprowadzane na układach ASIC.
Współczesna kryptografia programowalna, taka jak SNARK, również działa według podobnego wzorca na dwóch poziomach. Po pierwsze, dowód można napisać w języku wysokiego poziomu, w którym ciężkie podnoszenie odbywa się za pomocą operacji wektorowych, jak w powyższym przykładzie AI. Pokazuje to okrągły kod STARK, który tutaj mam. Po drugie, same programy wykonywane w kryptografii można napisać w sposób oddzielający ogólną logikę biznesową od wysoce ustrukturyzowanej, kosztownej pracy.
Aby zrozumieć, jak to działa, możemy przyjrzeć się jednemu z najnowszych trendów zaprezentowanych przez STARK. Aby zapewnić wszechstronność i łatwość obsługi, zespoły coraz częściej budują programy testujące STARK dla powszechnie przyjętych minimalnych maszyn wirtualnych, takich jak RISC-V. Każdy program, którego wykonanie wymaga udowodnienia, można skompilować do RISC-V, a program sprawdzający może następnie udowodnić wykonanie tego kodu w standardzie RISC-V.
Schemat z dokumentacji RiscZero
Jest to bardzo wygodne: oznacza to, że wystarczy, że raz napiszemy logikę dowodu i od tego momentu każdy program wymagający dowodu będzie mógł zostać napisany w dowolnym „tradycyjnym” języku programowania (np. RiskZero obsługuje Rust). Istnieje jednak problem: takie podejście wiąże się ze znacznymi kosztami ogólnymi. Programowalne szyfrowanie jest już zbyt drogie; dodanie narzutu na uruchamianie kodu w interpreterze RISC-V jest zbyt duże. Dlatego programiści wymyślili sztuczkę: zidentyfikowali konkretne, kosztowne operacje, które stanowią większość obliczeń (zwykle skróty i podpisy), a następnie utworzyli wyspecjalizowane moduły, aby bardzo skutecznie udowodnić te operacje. Następnie wystarczy połączyć nieefektywny, ale ogólny system sprawdzający RISC-V z wydajnym, ale wyspecjalizowanym systemem sprawdzającym i uzyskać to, co najlepsze z obu światów.
Programowalne szyfrowanie inne niż ZK-SNARK, takie jak obliczenia wielostronne (MPC) i szyfrowanie w pełni homomorficzne (FHE), można optymalizować przy użyciu podobnych metod.
Ogólnie rzecz biorąc, na czym polega to zjawisko?
Współczesne komputery w coraz większym stopniu opierają się na tym, co nazywam architekturą klejową i koprocesorową: masz jakiś centralny komponent „klejowy”, który jest bardzo wszechstronny, ale nieefektywny, odpowiedzialny za wykonywanie zadań między jednym lub większą liczbą komponentów koprocesora. Te komponenty koprocesora mają niską ogólność, ale wysoką wydajność przesyłania danych pomiędzy nimi.
To uproszczenie: w praktyce krzywa kompromisu między wydajnością a wszechstronnością prawie zawsze ma więcej niż dwa poziomy. Procesory graficzne i inne chipy, często określane w branży jako „koprocesory”, są mniej wszechstronne niż procesory, ale bardziej wszechstronne niż układy ASIC. Kompromis w zakresie specjalizacji jest złożony i zależy od przewidywań i intuicji co do tego, które części algorytmu pozostaną takie same za pięć lat, a które zmienią się za sześć miesięcy. W architekturze dowódczej ZK często widzimy podobne wiele warstw specjalizacji. Jednak w przypadku szerokich modeli mentalnych wystarczy rozważyć dwa poziomy. Podobne sytuacje mają miejsce w wielu obszarach informatyki:
Z powyższych przykładów z pewnością wynika, że jest to prawo naturalne, że obliczenia można dzielić w ten sposób. W rzeczywistości można znaleźć przykłady specjalizacji informatycznej obejmującej dziesięciolecia. Myślę jednak, że ta separacja pogłębia się. Myślę, że jest ku temu powód:
Dopiero niedawno osiągnęliśmy granice poprawy szybkości zegara procesora, więc dalsze zyski można osiągnąć jedynie poprzez równoległość. Jednakże równoległość jest trudna do uzasadnienia, dlatego często bardziej praktyczne dla programistów jest kontynuowanie rozumowania sekwencyjnego i umożliwienie równoległości przeprowadzanej na zapleczu, opakowanej w wyspecjalizowane moduły zbudowane do określonych operacji.
Prędkości obliczeniowe dopiero niedawno stały się tak duże, że koszt obliczeniowy logiki biznesowej stał się naprawdę znikomy. W tym świecie sensowna jest również optymalizacja maszyn wirtualnych, na których działa logika biznesowa, aby osiągnąć cele inne niż wydajność obliczeniowa: przyjazność dla programistów, znajomość, bezpieczeństwo i inne podobne cele. Tymczasem dedykowane moduły „koprocesorowe” można w dalszym ciągu projektować pod kątem wydajności, a ich bezpieczeństwo i łatwość obsługi programistów wynikają ze stosunkowo prostego „interfejsu” z klejem.
Coraz wyraźniej widać, jakie są najważniejsze i kosztowne operacje. Jest to najbardziej widoczne w kryptografii, gdzie najprawdopodobniej stosowane są pewne rodzaje kosztownych operacji: operacje modułowe, liniowe kombinacje krzywych eliptycznych (czyli mnożenie wieloskalarne), szybkie transformaty Fouriera i tak dalej. Staje się to coraz bardziej widoczne w przypadku sztucznej inteligencji, gdzie od ponad dwudziestu lat większość obliczeń to „głównie mnożenia macierzy” (aczkolwiek z różnym poziomem precyzji). Podobne tendencje pojawiają się w innych obszarach. W obliczeniach (wymagających dużej mocy obliczeniowej) jest znacznie mniej nieznanych niewiadomych niż 20 lat temu.
co to znaczy?
Kluczową kwestią jest to, że klej powinien być zoptymalizowany, aby był dobrym klejem, a koprocesor powinien być zoptymalizowany, aby był dobrym koprocesorem. Konsekwencje tego możemy zbadać w kilku kluczowych obszarach.
EVM
Wirtualna maszyna blockchain (np. EVM) nie musi być wydajna, wystarczy znajoma. Po prostu dodając odpowiednie koprocesory (tzw. „prekompilację”), obliczenia na niewydajnej maszynie wirtualnej mogą w rzeczywistości być tak samo wydajne, jak obliczenia na natywnej, wydajnej maszynie wirtualnej. Na przykład obciążenie związane z 256-bitowymi rejestrami EVM jest stosunkowo niewielkie, podczas gdy korzyści wynikające ze znajomości EVM i istniejącego ekosystemu programistów są znaczne i długotrwałe. Zespoły programistyczne optymalizujące EVM odkryły nawet, że brak równoległości często nie stanowi głównej bariery w skalowalności.
Najlepszym sposobem na ulepszenie EVM może być po prostu (i) dodanie lepszych, prekompilowanych lub wyspecjalizowanych kodów operacji, na przykład rozsądna może być kombinacja EVM-MAX i SIMD, oraz (ii) ulepszenie układu pamięci, na przykład drzew Verkle. jako efekt uboczny znacznie zmniejsza koszt dostępu do sąsiadujących ze sobą gniazd pamięci.
Optymalizacja przechowywania w propozycji drzewa Ethereum Verkle, umieszczanie razem sąsiadujących kluczy do przechowywania i dostosowywanie kosztu gazu, aby to odzwierciedlić. Tego typu optymalizacje w połączeniu z lepszą prekompilacją mogą być ważniejsze niż dostrajanie samego EVM.
Bezpieczne przetwarzanie danych i otwarty sprzęt
Jednym z wyzwań związanych z poprawą bezpieczeństwa współczesnego przetwarzania na poziomie sprzętowym jest jego zbyt złożona i zastrzeżona natura: chipy są projektowane tak, aby były wydajne, co wymaga autorskiej optymalizacji. Backdoory można łatwo ukryć, a luki boczne są stale odkrywane.
W dalszym ciągu podejmowane są wysiłki na rzecz opracowania bardziej otwartych i bezpiecznych alternatyw pod wieloma względami. Część obliczeń coraz częściej odbywa się w zaufanych środowiskach wykonawczych, w tym na telefonach użytkowników, co poprawia bezpieczeństwo użytkowników. Kontynuowany jest nacisk na sprzęt konsumencki typu open source, a niektóre z ostatnich zwycięstw, takie jak laptopy RISC-V z systemem Ubuntu.
Laptop RISC-V z systemem Debian
Problemem pozostaje jednak wydajność. Autor linkowanego artykułu pisze:
Jest mało prawdopodobne, aby nowsze konstrukcje chipów typu open source, takie jak RISC-V, konkurowały z technologią procesorową, która już istnieje i była udoskonalana przez dziesięciolecia. Postęp zawsze ma swój początek.
Bardziej paranoiczne pomysły, takie jak ten projekt budowy komputera RISC-V na FPGA, wiążą się z większymi kosztami. Ale co, jeśli klejenie i architektura koprocesora oznaczają, że ten narzut w rzeczywistości nie ma znaczenia? Jeśli zaakceptujemy, że otwarte i bezpieczne chipy będą wolniejsze niż zastrzeżone, nawet porzucimy w razie potrzeby typowe optymalizacje, takie jak wykonanie spekulacyjne i przewidywanie rozgałęzień, ale spróbujemy to zrekompensować, dodając (jeśli to konieczne, zastrzeżone) moduły ASIC, które są używane w większości intensywnych określone rodzaje obliczeń, co z tym? Wrażliwe obliczenia można wykonać w „głównym chipie”, który zostanie zoptymalizowany pod kątem bezpieczeństwa, projektu open source i odporności na kanał boczny. Bardziej intensywne obliczenia (np. dowody ZK, AI) będą wykonywane w modułach ASIC, które będą wiedzieć mniej informacji o przeprowadzanych obliczeniach (być może, poprzez zaślepienie kryptograficzne, w niektórych przypadkach nawet informacje zerowe).
kryptografia
Inną kluczową kwestią jest to, że wszystko to napawa optymizmem, jeśli chodzi o kryptografię, zwłaszcza kryptografię programowalną, która staje się głównym nurtem. Widzieliśmy kilka hiperoptymalizowanych implementacji niektórych wysoce ustrukturyzowanych obliczeń w SNARK, MPC i innych ustawieniach: niektóre funkcje mieszające są tylko kilkaset razy droższe niż bezpośrednie wykonywanie obliczeń, a sztuczna inteligencja (głównie mnożenie macierzy). jest również bardzo niski. Dalsze ulepszenia, takie jak GKR, mogą jeszcze bardziej obniżyć ten poziom. Wykonanie w pełni ogólnej maszyny wirtualnej, zwłaszcza w interpreterze RISC-V, może w dalszym ciągu wiązać się z około 10 tysiącami razy większym obciążeniem, ale z powodów opisanych w tym artykule nie ma to znaczenia: o ile stosowane są odpowiednio wydajne i wyspecjalizowane techniki Dzięki obsłudze najbardziej wymagających obliczeniowo części można kontrolować całkowity koszt.
Uproszczony diagram MPC poświęcony mnożeniu macierzy, największemu elementowi wnioskowania modelu AI. Zobacz ten artykuł, aby uzyskać więcej informacji, w tym o tym, jak zachować prywatność modelu i danych wejściowych.
Wyjątkiem od poglądu, że „warstwy kleju muszą być tylko znajome, a nie wydajne” jest opóźnienie i, w mniejszym stopniu, przepustowość danych. Jeśli obliczenia obejmują dziesiątki razy ciężkich operacji na tych samych danych (jak w kryptografii i sztucznej inteligencji), wówczas wszelkie opóźnienia spowodowane nieefektywnymi warstwami kleju mogą stać się głównym wąskim gardłem w czasie wykonywania. Dlatego też warstwy kleju mają również wymagania dotyczące wydajności, chociaż wymagania te są bardziej szczegółowe.
podsumowując
Ogólnie rzecz biorąc, uważam, że powyższe tendencje są bardzo pozytywne z wielu perspektyw. Po pierwsze, jest to logiczny sposób na maksymalizację wydajności obliczeniowej przy jednoczesnym zachowaniu przyjazności dla programistów, a możliwość uzyskania większej liczby obu korzyści jest dobra dla wszystkich. W szczególności poprawia naszą zdolność do wykonywania wrażliwych i wymagających wydajności obliczeń (np. dowodów ZK, wnioskowania LLM) lokalnie na sprzęcie użytkownika, umożliwiając specjalizację po stronie klienta w celu uzyskania większej wydajności. Po drugie, stwarza ogromne możliwości zapewnienia, że dążenie do wydajności nie naruszy innych wartości, w szczególności bezpieczeństwa, otwartości i prostoty: bezpieczeństwa kanału bocznego i otwartości sprzętu komputerowego, zmniejszonej złożoności obwodów w ZK-SNARK i ograniczenia złożoność maszyn wirtualnych. Historycznie rzecz biorąc, pogoń za wydajnością powodowała, że inne czynniki schodziły na dalszy plan. Dzięki architekturze opartej na kleju i koprocesorze nie jest to już potrzebne. Jedna część maszyny optymalizuje wydajność, inna część optymalizuje wszechstronność i inne wartości, a obie współpracują ze sobą.
Tendencja ta jest również bardzo dobra dla kryptografii, która sama w sobie jest doskonałym przykładem „drogiego przetwarzania strukturalnego” i trend ten przyspiesza ten trend. Daje to kolejną szansę na poprawę bezpieczeństwa. Większe bezpieczeństwo jest możliwe również w świecie blockchain: możemy mniej martwić się optymalizacją maszyny wirtualnej, a bardziej skupić się na optymalizacji prekompilacji i innych funkcji współistniejących z maszyną wirtualną.
Po trzecie, tendencja ta zapewnia możliwości udziału mniejszym, nowym graczom. Jeśli informatyka stanie się mniej monolityczna i bardziej modułowa, znacznie obniży to barierę wejścia. Nawet użycie układu ASIC do jednego rodzaju obliczeń może potencjalnie mieć znaczenie. Dotyczy to również obszaru proofów ZK i optymalizacji EVM. Pisanie kodu z niemal najnowocześniejszą wydajnością staje się łatwiejsze i bardziej dostępne. Audyt i formalna weryfikacja takiego kodu staje się łatwiejsza i bardziej dostępna. Wreszcie, ponieważ te bardzo różne obszary informatyki zbiegają się według pewnych wspólnych wzorców, istnieje między nimi więcej miejsca na współpracę i uczenie się.