Gównoburza o cipy
Nawet na nasze forum wtargnęła sprawa mapki Śpiocha dotycząca czipów. Chodzi o limit eksportu bulk do 790M TPP do 2027 roku. Uprzejmie zawiadamiam, że jest to bezprzedmiotowa gównoburza. Wyjaśniam dlaczego.
To 790 milionów całkowitej zdolności obliczeniowej na jakiś ludzki język to limit 50 tysięcy urządzeń takich jak obecnie H100:
https://www.nvidia.com/en-us/data-center/h100/
Zanim przejdziemy do bardziej szczegółowych objaśnień, to najpierw takie dla ludu. Przyjmijmy, że lud poczciwy wie co to jest RTX4090. Taka karta graficzna za ca dwa tysie ojro do grania w wodotryski na ekranie. Ma naście tysięcy rdzeni do przetwarzania 32 bitowych danych, czyli na ludzki – kolorków. Na nasz techniczny w rozumieniu powszechnym pod CUDA i typy danych dla macierzy 4x32float (czyli takie obrazki z liczb).
Jeśli liczycie coś technicznego (obciążenia w cadzie) to potrzebujecie macierze macierzy (tensory i można wejść w kolejne rzędy) do czego tam jest coś z pińcet rdzeni. One operują na 32, 16 i 8 bitach, dlatego do obliczeń tego typu mogą wcisnąć więcej danych w “obrazek”.
Oczywiście potrafimy to też wymusić na tych 16384 wcześniej pakując ośmiobitówki w postaci n0 x256 x256 + N1 x256 + N2 i podobne sztuczki. Przy czym w większości używacie GPU do oglądania szybko zmieniających się obrazków w grach więc kolory są cztery (przezroczystość) i jeszcze dochodzi bufor głębokości (aby zrobić culling na przesłoniętych tekselach), stencil i podobne kwiatki techniczne, które użytkownika mało interesują, a w procesie rzemieślniczym (bo nie tfu-rczym) są początkowo nieintuicyjne. Powstrzymam się od rozpisywania, bo już ten akapit przyciąłem (zacząłem się rozpisywać co i w jakim formacie tam lata oraz dlaczego; a ma być, na razie, dla ludu).
Lud lubi odbicia w lusterkach, a tam się liczy składany wektor (jest wystarczający, bo polaryzacji się nie liczy, więc bez macierzy się wozi; one są tylko wrzucane na kalkulacje odbić i pozycji źródło – kamera) i do tego w karcie jest dwie kopy mikroklocków. Wystarcza do zadowalania.
Zaznaczyłem “inne zastosowania” niż migające obrazki, więc teraz je omówmy, po co, na co i czym się to w karcie liczy. Cały proces przebiega na skalarach z zakresu od 0 do 1. To są takie liczby jak 10not (jeszcze ludzkie licznie). Czyli dziesięć do ujemnej potęgi, jakiejś tam – do jakiej dojdziemy. Technicznie to się liczy przy podstawie 2, ale są bin10 (2) typy ludzi, i z tego dowcipu każdy wie jakie. Na potrzeby użytkownika ten wykładnik pow(x,n) oznacza z jaką precyzją są przechowywane dane. GPU nie certoli się z numerkami jak ALU w CPU, więc jak się coś w zakresie nie zmieściło to wypada i nigdy tego nie było. W bitach przechowywana jest cecha i mantysa (było w szkole) więc im dłuższe słowo (więcej bitów) tym większą precyzję tam można zachować. Skrajnym przypadkiem jeszcze dostępnym bez udziwnień jest FP64 gdzie słowo zawiera flagę znaku, 11 bitów cechy i 52 mantysy co pozwala na precyzję ca10not308. Oczywiście można urwać znak i pomajstrować, więc da się “nieco” więcej, ale bez kombinowania to na ludzki mierząc rozmiarem plancka wszechświat mamy 10not61. Więc na kiego ta precyzja?
Jeśli dokonujemy jakiejś operacji (najczęściej mul – mnożenie) to wymnożony wynik nie mieści się w rejestrze z prawej (bo chcemy z prawej, czyli utrata precyzji, a nie ważących). Czyli tracimy precyzję, w kontekście macierzy oznacza to, że jeśli ją “obracamy” (mnożymy po osi obrotu) o jakąś wartość nie będącą rozsądnym podzielnikiem pirad (pi radianów – pół kółka na ludzki) to geometria macierzy po mnożeniu będzie jakaś nie taka, czyli wektory, z których się składa przestaną być ortogonalne. Przy małej precyzji (powiedzmy gry – szybko ma działać) robimy wtedy ortonormalizację, czyli pitagorasem jak młotkiem doprowadzamy dane do porządku, znaczy przekątna po wektorach orientacji ma wynosić jeden i basta – wektory składowe mają prawo stracić precyzję.
//przestawiam młotek:
l = sqrt(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]);
if (l != 0)
{
l = 1 / l;
M[@ 8] *= l;
M[@ 9] *= l;
M[@ 10]*= l;
}
M[@ 4] = M[9] * M[2] – M[10]* M[1];
M[@ 5] = M[10]* M[0] – M[8] * M[2];
M[@ 6] = M[8] * M[1] – M[9] * M[0];
var l = sqrt(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]);
if (l != 0)
{
l = 1 / l;
M[@ 4] *= l;
M[@ 5] *= l;
M[@ 6] *= l;
}
M[@ 0] = M[10]* M[5] – M[9] * M[6];
M[@ 1] = M[8] * M[6] – M[10]* M[4];
M[@ 2] = M[9] * M[4] – M[8] * M[5];
return M;
//koniec młotka
//dlaczego małe L i jeden wygląda tak samo to już typografów męczcie; tu na szczęście jest sensowniejsza czcionka niż arial;
Gdybyśmy tego nie robili (przyjmijmy, że jakoś tam wyłączycie to w grze) i zestackowali serię operacji (czyli ruszacie kamerą po mapie i kręcicie na różne strony) to widok (świat), który jest odwrotnością macierzy projekcji kamery zacznie się rozjeżdżać, kąty przestaną być poprawne i podobne cyrki. Przyjmując wykonywanie takich operacji w sposób matematycznie złośliwy co klatkę przy 16 bitach pierwsze efekty, o które obserwator by się mógł czepić na dużych odległościach (z-far, odległy plane clipping macierzy projekcji) będą już po 30 sekundach.
Jeśli jednak liczycie coś technicznego czy naukowego to żadnej ortonormalizacji nie dopuszczamy, ponieważ byłyby to szukane z d – znaczy z tej funkcji ortonormalizującej, a nie z danych po operacjach. Dlatego aby uniknąć problemiku robi się na precyzji znacznie przekraczającej wymogi fizyczne i rezultat końcowy nawet przy utracie precyzji na 64 bitach dalej będzie obliczeniowo w porządku względem plancka. Co dla naprężeń czy wytrzymałości konstrukcji oznacza, że 16 bitów nas zadowala, a dla ganiania elektronów w polach magnetycznych 32, a jakby się komuś atomowe wybuchy zachciało liczyć to 64 wystarcza z naddatkiem. Oczywiście istnieją rozwiązania na większe zakresy, ale na piecyku są one softwarowe, więc wolne (kryptografia), a na sprzętowych nie mają innych zastosowań, więc nikt tego do domu nie wstawia.
W karcie do użytku domowego nie macie FP64, bo do niczego by nie służyło. To tylko do grubych obliczeń numerycznych, symulacji fiszyki, kalkulacji inżynierstwa czy innego MatLabowania. Grafiki się na tym nie robi.
To co tam macie to FP32 czyli ca 10not38 co i tak jest przerostem formy, ale ze względu na komunikację z CPU karmiącego kartę danymi już tak sobie jest. Zastosowanie gdzie aż taka precyzja jest potrzebna są delikatnie mówiąc naciągane, ale pozwalają na pewną dozę lenistwa w pakowaniu numerków paczkami. Na tym możecie pociągnąć więcej niż dość obliczeń CAD, CAM, MatLab i gierek. A nawet jakieś tam prostsze sieci neuronowe do obrazków. Karta graficzna tak naprawdę na tym nie chodzi domyślnie, ale można to włączyć poleceniami dla zmiennych (wyższej precyzji). Powiedzmy, że karta (konkretnie kompilator) trochę oszukuje jeśli nie dostaje informacji, że ma pilnować precyzji danych, przy czym większość kompilatorów dodaje takie polecenia jeśli wykryje na zmiennych operacje, które by precyzję psuły.
Wariantem jest TP32 czyli mniej precyzyjna mantysa do wożenia większej liczby liczb w paczce. Wozi się tym macierze w paczkach, dlatego nazywa się to tensor float. To tylko inna konfiguracja tej samej liczby bitów. Jednym rozsądnym zastosowaniem tego jest uczenie maszynowe systemów eksperckich (na tym wozi się e-jaj). Bo to tak technicznie jest po prostu bardzo duży wielomian odczapkowego rzędu gdzieś bardzo daleko na trójkącie paskala z wykładnikami.
Dalej mamy FP16, czyli mniejszą dokładność (10not5), w której wypluwa się do monitora sterowanie napięciem (kolorki), a do obliczeń niższej precyzji jest wystarczające – na tym robi się duże zbiory pod e-jaja czy interferencję modeli (mnożenie Waszego prompta przez bazę – tak w skrócie wynik jest odpowiedzią).
Większość operacji nie wymaga tej precyzji, za to przetwarzanie FP8 (czyli taki int udający float bo od 0 do 1) jest diablo szybkie, ale Wasza karta tej opcji nie ma. I w zasadzie o to kopie są kruszone. Awantura z Chińczykami o RTXy była właśnie o to, że poprzerabiali im kod klocków aby na samych FP8 jechały. Takim niby trochę oszukanym, ale skutecznym.
Przyjmijmy, że chodzi o tego e-jaja. Karta “domowa” za dwa tysie ojrów ma na te potrzeby jakieś >300 TF (niby 330, ale trzeba się ogarniać CUDA bez baboli). H100 kosztuje ca 30keur i ma jakieś cztery PF, czyli proporcjonalnie niby trochę mniej. W wersji serwerowej (wpinane jak płyta w rack) to trzykilowy klocek o wartości 1/10 wagi w złocie. Oczywiście można przeliczyć na mieszkania w Pcimiu Dolnym albo samochody premium.
Limit tych 50k pcs oznacza, że można do Polin sprowadzić w dużych partiach do pięciu ton tego złota. Czyli 150 ton kart (wersja serwerowa). Przy obecnych cenach prądu data center wymagający takiego sprzętu raczej się nie zapowiada nad Wartą. Nic nie słyszałem aby planowano wydatki na badania nad bronią jądrową Popiel 238 czy systemem eksperckim Radziwił Radzi. Zaś ilość specjalistów do zrobienia czegokolwiek użytecznego z taką ilością gratów przekracza nie tylko jakikolwiek budżet na badania, ale zahacza o ten na obsługę długu.
Można z góry założyć, że do końca 2027 jurysdykcja Niedorzecza nie zbliży się z importem nawet do 10% omawianego limitu. To jest zwyczajnie nie ta gospodarka, nie tego rozmiaru. A szum w propagandzie jest taki jakby Jankesi się nie wiadomo czego dopuścili.
Tymczasem Jankesi mogą opublikować mapkę z ograniczeniem eksportu hidżabów do Polski – mają większe wzięcie niż jednostki obliczeniowe. Zarówno hidżabów jak i usług obliczeniowych dokonuje się w miejscach odległych, bezpiecznych, stabilnych politycznie i podatkowo z tanim prądem. Jankesi dali limit zakupów na dwa lata o wartości… nowej rafinerii (bez wliczenia łapówek). Nikt nie stawia nowej rafinerii? Nie rozmyślił się z budowy data center z powodu tego limitu i stawia rafinerię zamiast aby jakoś upchnąć kapitał? Tak właśnie myślałem.
Cała gównoburza z mapką i limitem jest o nic. Nikt tu nawet ułamka tego sprzętu nie planował sprowadzać. Cala sprawa jest administracyjnym wypierdem, który dotyczy kwestii nieistniejącej (jak większość działań administracji).
Przyznaję, że wykasowałem pół tekstu bo bym zaspamował kwiatkami w rodzaju:
float nx =-vec0.x*in.x-vec1.x*in.y-vec2.x*in.z;
float ny =-vec0.y*in.x-vec1.y*in.y-vec2.y*in.z;
float nz =-vec0.z*in.x-vec1.z*in.y-vec2.z*in.z;
vec4 np = vec4(nx,ny,nz,1.);
objaśniając co się gdzie rozjeżdża i dlaczego robimy tak albo siak highhp.
