Wniosek uint16
Rozbudzono rozum, a gdzie schował się demon z zeszytem?
Ten od zeszytu:
http://en.wikipedia.org/wiki/Maxwell%27s_demon
Znowu jest czas pografomanić na robocie. Oczywiście nie tylko tym się zajmuję. Dopiero co drażniłem się z przedemerytalnym Dżołke (gdyby z odpowiednią fonetyką odczytać lokalnie używane zdrobnienie Jego imienia, to tak by brzmiało), który pieniacko rezonował na temat stosunku do pracy kontrowanego “za tyle to jest tak”. Czyli standardowe bai lang, tang ping. Ale on jest z tej jeszcze boomerskiej epoki, gdzie istniały pojęcia wysługa lat, urlop, a nawet inne błędy i wypaczenia.
Wypadałoby zahaczyć o jakiś temat, a dwa rozgrzebane zostawiłem na piecyku w jaskini, więc pociągnę nowy. @Koncereyra podrzucił na forum filmy o historii “jak doszło do oops”. Gdzieś tu wrzucą link, o jest:
jeśli na forum się nie zakopał zbyt mocno. Film ten składa się z błędnej opowieści historycznej (narrator nie zna i nie rozumie punktu wyjścia, opowiada z perspektywy człowieka cywilizowanego o życiu pionierów), ale na końcu w dialogu się rozkręca i kto rozumie jak do tego doszło to znajdzie tam smaczki. Ponieważ opowiada o lokalnych dla mnie tubylcach i w pewnych niszach ten model kształcenia oraz rozumowania przetrwał (zdążyłem jeszcze zahaczyć ze dwie dekady temu w tubylczej szkole robiąc tubylcze papiery “umi”), wskazując że wypadałoby się tego sposobu rozumowania nauczyć, a @Koncereyra był łaskaw odnieść się, że to istotne to wyjaśnię dlaczego się nie zgadzam. Czyli takie commentary tylko bez YT.
Zacznijmy od kartki w kratkę. I zeszytu w ogóle. Ten odpowiednik zeszytu macie w każdym IDE, ma ponumerowane linie. I macie kartki zwykle jako funkcje. Z takiego zeszytu w kratkę pozostały chyba wyłącznie obszary pamięci gpu na przechowywanie zbiorów wektorów (i skalowanych zbiorów) najczęściej kojarzone z teksturami i ich wersjami mipmap, dzięki czemu przy perspektywie powtarzalnych obrazów oczy nie głupieją. Ale to tylko przybliżenie. Historia z filmiku zaczyna się w głębokich latach sześćdziesiątych, czyli gdzieś tak zaraz po śmierci Stalina. “Komputery” na jakich ci ludzie zaczynali swoją edukację logicznie były tym czego używamy obecnie (nihil novi), ale technologicznie były instalacjami elektrycznymi. Nie elektronicznymi. Działały na zestawach przełączników, jakich dziś używamy do sterowania dużym prądem przy użyciu małego (switch). Dopiero układy zintegrowane (scalaki) rozwiązały problem kaskady rezystor->tranzystor->rezystor->tranzystor-> loop. Ponieważ udało się zrobić takie sterowanie parametrami prądu i cyklem zegarowym, że rezystor “zniknął” stając się własnością samego “kabla” (ścieżki), a warstwy diod i szyn zasilania kolejnej warstwy są obecnie sprytnie ukryte jako kolejne warstwy M bardzo zintegrowanych “scalaków” gdzie im głębiej zejdziemy na kierunku M– tym dla gasnącego zasilania można użyć coraz węższych ścieżek. Mam o tym rozgrzebany tekst od strony metalurgicznej, gdzie wskazuję ile elektronów “rusza na wycieczkę” dla każdego tranzystora w cyklu zegarowym.
“Programowanie” przy tej zmianie technologicznej było “pisaniem instrukcji”. I film zaczyna się właśnie bez tego kontekstu, kiedy to programowanie pojawia się już bliżej tego co dziś rozumiemy pod tą nazwą. Więc ten kontekst przytoczę, bo został on w filmie zgubiony. Większości narzędzi, które dziś używamy jako oczywiste nie istniały ówcześnie, istniało tylko to co działa na samym spodzie klocka, kiedy go uruchamiamy, gdzie odwołania są stałe i pozostałe funkcje logiczne dopiero podpinane.
Instrukcja ówcześnie była zapisem ustawienia przełączników, takich odpowiedników automatycznych zworek (dziś tranzystorów). Jedna odpowiadała za instrukcję procesora (czyli jak ustawić labirynt), a dwie pozostałe to były liczby opisujące dalszą ścieżkę, najczęściej dość prostą, bo magazynową i dlatego kartka w kratkę. Do dziś rozpisanie tych liczb daje binary tree gdzie z labiryntu wyjdziemy, a liczba wyjść jest skończona i z góry znana. Najbardziej typowym punktem startowym było wprowadzenie liczby (instrukcji) pobrania z pamięci (adres zerowy, żeby nic nie ustawiać) i załadowania jako kolejnego polecenie procka, oraz adresu pierwszego jako odwołania do komórki pamięci gdzie było co czynić dalej. Tej pamięci za dużo nie było, “komputery” były dość ślamazarne (w kilkuset cyklach na minutę bo chodziły na dużym prądzie i wygaszanie dość mechanicznego układu przełączników chwilę zajmowało), a do tego nie było ich zbyt wiele. Wymagały też ciągłej obsługi technicznej – miało się tam co popsuć. Dlatego program pisano na kartce, i dopiero kiedy było pewne, że to pójdzie dobrze wrzucano na maszynę. Czyli w procesie było absolutnie koniecznym przyswojenie w głowie symulacji działania maszyny, aby te ciągi liczb (instrukcji) rozpisać prawidłowo. Ponieważ było to dość upierdliwe, a scalaki rozwiązywały hopsztylion problemów technicznych nowa technologia wzięła branżę szturmem i pozwoliła stworzyć narzędzia quality of life. Na przykład takie, które pozwalały zapisywać mniejszą liczbą znaków (hex) te instrukcje i adresy (zamiast ciągów 0/1 ustawienia przełączników) co scalak przekładał na cią włączeń (0/1). To są korzenie asemblera, który nie jest pierwotnym sposobem wprowadzania instrukcji, tylko ułatwieniem dla homo sapcia. Oczywiście ktoś uczący się kodoklepstwa dzisiaj patrząc na asemblera puka się w czoło pytając co tu jest urwał dla homo sapacza, no ale z punktu widzenia ustawiania zworek to jednak był język najwyższego poziomu.
Moc obliczeniowa i pamięć przyrastały dzięki rozwojowi scalaków błyskawicznie. Z jednej kartki w kratkę zrobił się szybko cały zeszyt, a dziś to cache procesora. Kolejnym quality of life było zrobienie programu tłumaczącego syntax zbliżony do homosapaczowego na asm, a dalej z górki. Co jeszcze bardziej ułatwiło klepanie koda, choć ówczesne języki bardzo odnosiły się do żargonu asemblerowego (te wszystkie move, jump etc – pozostało to do dziś na klawiaturze w psotaci del, end, ins, num, scr, alt, esc itp). Ale nie poszło to wcale z instrukcji na asembler wcale taką prostą drogą – istniały inne rozwiązania, które wyginęły. Na przykład translator liczb dec (powiedzmy, bo mówimy o rozwiązaniach 4 i 5 bitowych ówcześnie) na instrukcje, oraz inne koncepcje ograniczone (gdzie numpad do wprowadzania instrukcji miał tylko 4 cyfry, kasownik wprowadzenia, enter i przerywacz operacji, coś jak reset). Te uboczne rozwiązania jakiś czas utrzymały się w przemyśle (skoro maszyna działa i ktoś w to umie to nie ma co psuć). Akurat takiego komputera pokładowego używano w misjach Apollo, ten na Ziemi który wykonywał robotę obliczeniową i wysyłał odpowiedzi działał już inaczej. Ostatnie takie rozwiązania wyginęły wraz z przejściem sieci telefonicznej na sygnał cyfrowy (w funkcji sygnału łatwiej zapisywać cztery wartości niż dwie, graficznie przedstawiano to wektorami).
Warto mieć na uwadze, że omawiane w filmie osoby miały cały ten bagaż rozwiązań w głowach. A rezultatem ich pracy było przejście ze statycznego do dynamicznego przydziału pamięci. I to jest kwestia kluczowa, której w filmie w ogóle nie poruszono. Rozpisując program na kartce trzeba było z góry założyć co będzie w której komórce pamięci przechowywane (oraz czy warto). Kilka komórek przydzielano na pamięć roboczą obliczeń (gdy były za długie na jeden cykl) i trzeba było od razu wiedzieć ile wyniesie najdłuższe możliwe, a na rozrzutność nie było miejsca. Część pamięci na stałe była przydzielana na output (taki sektor pamięci odpowiadający aplication surface, choć to wtedy po prostu była pamięć “ekranu” i układ transformujący sygnałna wyświetlacz go sobie w swoich cyklach pobierał innym wyjściem, cpu nie wydawał polecenia zrzucenia na monitor, bo całe “gpu” to był tylko region pamięci podręcznej do składowania stanu wyświetlacza na output). Z tego że pamięć była przydzielona na stałe (wirtualnie, w zamyśle programisty) to procesu ochrony pamięci nie było. Można było instrukcją poke zrobić cokolwiek, gdziekolwiek, z czymkolwiek i wywalić cały pociąg. Co prowadzi nas do debugera. Takiego zwierzęcia nie było w zoo. A było potrzebne. Jego konsturkcja zaczęła się od dodania na samym cpu wyjścia pomiarowego bezpośrednio na rejestrze instrukcji proca oraz dwóch segmentów liczb w tych instrukcjach. Czyli instrukcja, mem0, mem1. I wywalenie tego na drukarkę. Co wypluwało przez cały czas działania proca linijki sygnału. Żeby było szybko szło to igłą na taśmę – weź sobie później odczytaj. Później dodano moduł tłumaczący na hex i instrukcję na asm (bo liczb dalej tłumaczyć nie trzeba). Skutkiem tego trzeba było na wydruku poszukać gdzie zaczyna się bełkot. Oczywiście rosnąca prędkość scalaków nie pozwalała żadnej drukarce za tym nadążyć, a rosnąca długość programów zarżnęłaby dowolną papiernię wydrukami. Dodano więc obsługę – numer cyklu od startu i drukowanie tylko w przypadku instrukcji nierozpoznanej, oraz w przypadku instrukcji uruchamiającej druk (taki przerywnik programu odpowiadający mniej więcej obecnemu show debug wrzucany do logiki jako prt – print, a to co znamy dzisiaj jako “by kontynuować naciśnij spację” było przerywnikiem sys rqi – system request response from Input). Można było wtedy przeczytać co się stanęło, że stanęło i pomyśleć. Tak wtedy jak i dziś były dwa rodzaje błędów, przy czym nieobsługiwane. Pierwszy dziś obsługiwany to taki, że nam wywala error – instrukcja nie istnieje, odwołuje się do czegoś czego nie ma, albo jest nie takie jak powinno. Ówcześnie to narzędzie nie istniało (o tym jest dużo w filmie, strong data type, ochrona pamięci dla funkcji). Więc jak coś było zjebane na instrukcji (nieistniejącej), albo odwołaniu do nieistniejącej pamięci to komputer działał zgodnie z tą pętlą, czyli robił nic czekając na zwrotkę z nieistniejącego wyjścia z labiryntu. Wtedy błąd na debugu z drukajki łatwo wykryć, bo po prostu nie schodzą kolejne instrukcje i czytamy te kilka ostatnich głupich, a szczególnie ostatnią, i poprawiamy. Gorszy jest drugi rodzaj błędu, który w zasadzie błędem nie jest, za to częstym powodem do darcia łacha na forum – wszystko działa zgodnie z instrukcją, co nie znaczy, że zgodnie z oczekiwaniami – takie były rozkazy. Czyli program działa, tylko mieli jakieś farmazony, zamiast tego czego oczekiwaliśmy i szukamy gdzie się nam argumenty posypały. Właśnie stąd jest to przerwanie “wrzuć na druk” obecnie “wrzuć na output” czyli show debug message i tam dowiadujemy się czegoś o ile dobrze pytamy. I jeśli rozumiemy co popełniliśmy.
Bazą tego co omawiane jest w filmie (czyli po co oops) była ochrona pamięci, która zaczęła się od sektora przydzielonego na wyświetlanie.To taki na nasze odpowiednik tekstury, przechowywano w każdej z komórek zapis “jak ustawić prąd na wyświetlaczu”, czyli na przykład 4bit jasności, a później 2+3+3 (lub 3+2+3 czy inna kombinacja) koloru. Żeby nie było bajzlu komu wolno tam pisać to kompilator nie dopuszczał tam dowolnych poleceń memory poke, tylko takie gdzie było draw. Trzeba było intencjonalnie zadać rozkaz, że to idzie do pamięci wyświetlacza i wiemy co robimy. Skończyło się przypadkowe przechowywanie wyników obliczeń w pamięci ekranu. Ponieważ jednak koncepcja dynamicznej ochrony pamięci dla poszczególnych funkcji nie mogła nagannie wpychać interpretera (nazywajmy go kompilatorem, ale to bliżej tego co mamy jako virtual machine, tak wtedy cały cpu chodził, kod był interpretowany bezpośrednio, tylko tłumaczony na asm i na instrukcje) w asembler to trzeba było to rozwiązać przez porównanie dynamicznie przydzielonych liczb. Czyli zadeklarować adres i indeks, coś jak na array od którego peek do którego danej funkcji wolno grasować. Jeśli odwoła się do czegoś innego to będzie to bezskuteczne. Później zrobiono tak, żeby kompilator wychwytywał takie bezczelności, a w językach wyższych poziomów, gdzie pamięć przydzielana jest w locie (o tym właśnie w filmie) cofał kompilację jeśli jest nielegał. Obecnie takiego nielegała możecie zrobić chyba wyłącznie na data type, ponieważ numer z wpisywaniem twardego odwołania do indeksu przez asm w językach wysokiego poziomu nie przeleci przez warstwy kompilacji. Chyba że robicie coś złośliwego, ale taki numer zostanie wychwycony przez obecne urządzenia przed wrzuceniem na stack, bo od przydzielania adresów jest tam układ, a nie widzimisie kodoklepcy. Z wielu powodów (na przykład omijanie niesprawnej instrukcji, jeśli klocek się sypie, albo omijanie zwalonego sektora pamięci dowolnego poziomu). Oczywiście na upartego i ten nadzór można zmienić, ale dłubanie w tych instrukcjach to dość specjalistyczna dziedzina (złożone się zrobiło) i zmienicie najwyżej w swoim klocku. Oczywiście M$ potrafi wrzucić na produkcję takie coś bez testów i wtedy lotniska wykrzaczają się jedno po drugim, a w szpitalach gaśnie światło.
Cięgle jednak jesteśmy na jednej maszynie, z jednym wątkiem, na jednym core, gdzie wszystko chodzi w syncu, instrukcja za instrukcją, linie po linii. Jeśli się odwołujemy do czego co jest wcześniej w logicie to to tam już jest ile by akurat nie wynosiło i ma właściwy data type, bo istniej po lewej stronie wykresu. A oops wykminiono właśnie z tego powodu, że jeśli odpalimy więcej core (ówcześnie więcej kompów), i one będą miały różne instrukcje to już pal diabli ping, ale z samego tego faktu wyniknie różnica w numerze linijki, numerze cyklu, i mamy async wykonawczy. Trzeba więc wprowadzić więcej testów i zabezpieczeń. A to że z punktu widzenia maszyny instrukcje są od zera do, adresy pamięci od zera do, linijki od zera do, cykle tak samo, funkcje tak samo, podłączone maszyny tak samo to dla kogoś kto w tym siedzi od prehistorii jest to może do ogarnięcia, ale quality of life aby tego używać wymaga kolejnego poziomu abstrakcji ułatwiającego odczytanie tego co się dzieje i napisania się co niby dziać się ma przez większą liczbę homosapaczy, niekoniecznie tak ogarniętych w tej dziedzinie. Ponieważ oni mają rozwiązać tym narzędziem jakieś swoje rachunki, a nie budować koło od nowa.
Czyli wchodzi nam async, liczba maszyn, liczba wątków. Async jest kluczem do rozwiązania problemu jaki przed sobą postawili pomysłodawcy oops. A ponieważ na ludzki rozum ciężko jest posługiwać się logiką, w której dynamicznie zmieniają się odniesienia wewnętrzne obsługiwanych odbiorców i źródeł danych w postaci:
t73 policza a12+b3 i zwróć falgując jako 57; t13 zwrócił 35, czyli może liczyć o15 dla argumentów, a7, b3, c48 i zwrócić wynik flagowany 58; brak odpowiedzi od t7 w czasie [ramka], przypisujemy najbliższy równorzędny jako t7 i wyrzucamy z listy, dopóki nie oflaguje gotowości;
I tak wkoło Macieju. Kto obecnie jest pod t3, co robi i skąd się tam wziął, co miał zlecone można dojść wstecznie po logu, o ile jest prowadzony i komuś się chce dłubać. Więc aby tego loga mieć do przeczytania trzeba nad tą całą numerologią prowadzoną przez cpu przy każdej zmianie, każdej fladze i każdej zwrotce dodać coś czytelnego dla homosapcia. Każdy sposóbjest dobry, ale siedli do tego ludzie od systematyki, a nie księgowi (i całe urwał szczęście, bo excella każdy widział – takie by były skutki). Tego akurat w filmie nie ujęto dlaczego tak się stało, co w zasadzie ktoś kto studiował “biologię” (scjentologii komputerowej wtedy nie było, ale tylko z braku komputerów jako obiektu studiów). Tak w przybliżeniu biologię. Więc może wyjaśnię dlaczego tak, bo to specyfika lokalna. Na Północy po podstawówce idzie się do szkoły. Nie ma czegoś takiego jak kształcenie ogólne, czy liceum ogólnokształcące w naszym rozumieniu. Są szkoły zawodowe, technika i przygotowujące do studiów z jakiegoś obszaru (taki odpowiednik mocno profilowanego liceum). To że się to nazywa gimnazjum nie ma znaczenia, nazwa jest tak samo z d jak każda inna. Można pójść torem niemieckim – technikum plus zajęcia przygotowujące na studia inżynierskie. Ale dwie standardowe trasy to profilówka techniczna (przygotowująca od razu na studia inżynierskie, a odpad zrzucająca do technikum) i przyrodnicza (przygotowująca na studia jak byśmy to nazwali “naukowe/badawcze” i zrzucająca odpad do fastfoodów). Czyli jeśli ktoś ówcześnie od razu był taki bystry, aby ustawić sobie cel “pójdę na studia” to przyjmując iż nie chciał zajmować się budową huty, stalowni, okrętu, samolotu i obwodnicy trafiał na nauki przyrodnicze. Tak na wszelki słuczaj szkoły zazwyczaj prowadzą kierunek techniczny i przyrodniczy razem, bo gównażeria niekoniecznie musi być zorientowana do czego się nadaje i łatwiej zrobić swapa na tym etapie. Dodajmy, że nauka na Północy obowiązkowa jest tylko do końca podstawówki (do dzisiaj^^), a ówcześnie od szóstej klasy szło się do pracy i na tym najczęściej kształcenie się kończyło (tak, znam starych Północników, którzy w wieku 15 lat poszli do roboty, na tym ich edukacja się kończy i po 50 latach zasuwania po 45h tygodniowo [dzień pracy 9h, a to że niby tam jest przerwa nie zmienia foktu] dostają taką emeryturę, że grzebią w śmietnikach – gdyby komuś się zdawało państwo dobrobytu i socjalu). Czyli ci co szli na gimbazę przydoniczą raczej wiedzieli co robią. No i z tej gimbazy wychodzi się z fizą, matmią, chemią i biologią zależnie od szkoły na nawet wyśrubowanym poziomie z dużą ilością praktyki w labach. Ówcześnie akurat laby o kompiutrach były w kierunku przyrodniczym, bo technika się żelastwem zajmowała i bardziej inżynierskimi zabawami, ale elektroniki jeszcze w szkołach nie było. Przyjmując kierunek “kariera naukowa” wspominany w filmie Północnik musiał pójść dalej na coś, co pozwoli robić z kompiutrami. Co tam oznacza fizę lub bio. Co ciekawe chemia jest tylko do zastosowań (kształcenie prosto do przemysłu), a Matematyki w naszym rozumieniu jako osobnego, ezoterycznego kierunku przed doktoranckimi nie ma (a pedagogiczny to poziom motorniczego). Dlatego obrany kierunek studiów w filmie jest wyjaśniony jako “biolog”. Ale to ma równy sens jak bias iż jakiś grecki filozof nie był matematykiem.
Ten bias, wskazany w filmie jest fałszywy i przedstawiany z perspektywy człowieka współczesnego opowiadającego o świecie, który przeminął. Nie jest to świat zrozumiały w kategoriach pojęciowych jakimi dysponuje opowiadający (na moje oko jest po prostu młody i niszowy), a jeśli nawet to byłoby nieprzyswajalne przed tablicą więc nawet jeśli rozumie to tego nie ujawnia.
Wracając do naszych numerków z literkami – trzeba było przypisać jakąś czytelną dla homosapacza systematykę, a taką dysponują jedynie nauki biologiczne (pamiętajmy, że mówimy o czasach dynamicznego rozwoju, pierwszym stosunku z DNA, które nie bez powodu odniesiono od razu do kodu i instrukcji – biasy aparatu pojęciowego działały w obie strony). Co łatwo odkryć próbując rozczytać funkcje i operatory w naukach przyrodniczych. W fizyce definicje są restrykcyjne wzorem albo z czasów zamierzchłych (pole… tylko nie dwuwymiarowe, topologia – tyle że nie opisująca terenu, albo operatory wprost z Matematyki), w chemii mają ezoteryczne pochodzenie z języków starożytnych, w farmacji też czary mary w użyciu, za to w biologii, jako że dziedzina jest całkiem młoda bo większość roboty pochodzi z ostatnich 70 lat to nazewnictwo jest z nowoczesnego aparatu pojęciowego i na zrozumiałej systematyce funkcyjnej (bez abstrakcji). Czyli do zastosowania wprost. Łatwo wyrwać kilka terminów i stwierdzić, że są opisane w taki sposób, na przykład transkryptaza to coś, co robi funkcję przepisującą z czegoś na coś. To że to jest enzym, że podłączając do swojego mechanizmu cząstki luzem, w wyniku mechanicznego nacisku cząstek przepuszczanych przez układ enzymu dokleja ich dopełnienie jest bez znaczenia, ważne jaką pełni funkcję, a nie czym i jak to robi. W fiszyce pewnie by to nazwali enzymem tego co to wymyślił, a nie “co ten wihajster robi”. Dlatego semantykę wzięto z biologii. Bo polecenie było jasne – mamy to opisać, i to tak żeby dało się przeczytać i zrozumieć, bo tak inaczej to już mamy z mikroklocka.
Ludzki syntax wymaga aby czynność (funkcję) wykonywał ktoś (obiekt) korzystając z informacji (argumentów) przekazanych do obróbki w łańcuchu dowodzenia (master-slave) i zwracanych temu kto kazał (master). Dlatego na początku użyto pojęcia obiektu. I to nie znaczyło tego co obecnie w w języakch wysokiego poziomu tylko dotyczyło abstraktu dziś zwanego maszyną. Konkretnie wirtualną. I to od razu miało w pseudokodzie symulacji opis wirtualnych maszyn (nie urządzeń – ta nazwa już była dla podzespołów zarządzanych samodzielnie z danych w cyklach przez maszynę). Kolejną sprawą było sprawdzenie poprawności danych (argumentów) w obie strony (slave-master). Tak za dużo to się ówcześnie zrobić nie dało – maszyny operowały wprost na bitach, można im było majstrować przy długości, ale opylanie bitu na flagę było na tyle problematyczne, że nie fatygowano się z wprowadzaniem liczb ujemnych tylko przesuwano zakres (po całkowitych) i skalowano epsilonem (przesunięcie przecinka). Liczby zmiennoprzecinkowo początkowo istniały jako koncepcja wyłącznie do zapisu wyniku dla dużych liczb bo przepchnięcie przez proca dwóch 8 bitowych liczb aby zająć 4×8 bitów i chyba siedem albo osiem operacji do uzyskania 2×8 cecha plus mantysa było rozrzutnością ponad miarę. Problem rozwiązano spadkiem cen scalaków, gwałtownym wzrostem ich wydajności etc. Ale od lat sześćdziesiątych do osiemdziesiątych jest kawałek, a powszechnie w domach liczby zmiennoprzecinkowe jako standard wchodzą dopiero w latach dziewięćdziesiątych. Wcześniej to była opcja kosztująca cykle. Dopiero układ zmieniający bardzo długi sygnał na składowe cechy i mantysy (czyli klocek wykonujący tylko tę operację sprzętowo) oraz flagowanie wprowadził to pod strzechy. Ale tylko pods strzechy – duże kompy od liczenia poważnych rzeczy dalej jadą na kalkulacjach integer i dopiero gpu stosowane do obliczeń wprowadza wektor jako standard (czyli ostatnie 15 lat, czasy nam jak najbardziej współczesne). No więc w tamtych czasach trzeba było na pałę dodać flagowanie, a dalej standard zapisu. Źródłem tego był skrót chr – że teraz opisujemy numer symbolu na potrzeby wyświetlania, wydruku czy cokolwiek. Tyle, że to nie było polecenie wykonywane wewnątrz, a obsługa urządzenia zewnętrznego. Pakując w rejestr instrukcji polecenie chr pierwszy rejestr cache proca był zrzucany labiryntem tranzystorów ustawionych numerycznym odpowiednikiem chr na urządzenie wyjścia, którym był lookup table dostający zawartość rejestru (to wartość zawsze leci labiryntem, odpowiednik funkcja(arg) chyba, że polecenie jest bezargumentowe jak pwr()), i tam zgodnie z numerem znaku był zestaw przełączeń macierzy igieł (lub diod, lub whatever) aby ten obraz zrzucić na nośnik (na przykład ekran lub kartkę).
Tak po prawdzie to cokolwiek byłoby w rejestrze i znajdzie się w lookuptable zejdzie. Chyba że nie ma w lookupie urządzenia, wtedy będzie pusty znak, albo zależnie od coraz to nowszych sterowników jakiś numeryczny odpowiednik ustawienia. Tym tropem poszli twórcy aby flagować typ danych i sprawdzać przed stosunkiem. Było to o tyle istotne, że wpadli na pomysł aby nie przekazywać samej danej tylko jej adres/indeks. Na ludzkie jest to przekazanie dwóch limesów odkąd dokąd czytać. I kto dopuszczał się rzeczy niegodziwych wie, że można wbić odczyt z adresu indeksem wstecz co kiedyś pozwalało na dostęp do zastrzeżonego obszaru pamięci, aż do klocków dodano moduł, który mimo to je chroni w limesach na loopie; Zamiast wartości bezwzględen adres minus jeden albo dostaje się kopa errorem, albo zwraca z końca legalnego zakresu minus indeks. To o tyle istotne, że w gpu taka organizacja pamięci pozostała (dużo rzeczy w gpu zostało po staremu bo jest szybciej bez całego oops szpeja; a gpu szybkie ma być). O ile nie ustawicie inaczej to z zakresu 0-1 wartość UV tekstury 1.2,.2.5 zwróci .2,.5. A jak ustawicie inaczej to spoza 0-1 zwróci roun 0-1 nearest bo niezwrócenie czegokolwiek w cyklu gpu wywróciłoby rowerek (pusty return oczekiwanego rozmiaru jest przygotowany w rejestrze zanim funkcja zacznie się rozglądać po szufladach). Flagować musieli, ponieważ bajt był wtedy krótki (4,6,8bitów zależnie na jakim klocku) i przekazanie czegoś składającego się z innej liczby bitów wynikało ze sposobu zarządzania pamięcią (przygotowany zakres bitowy był ciachany od adresu po bicie przez sprzętowy odpowiednik peek). Kołderka była krótka, więc pewne rzeczy ustawiało się na 1 (flagi) inne na 3, a jeszcze inne na 11 kolejnych bitów co przy dynamicznym zarządzaniu zasobami generowałoby niezły burdel. Zwracam uwagę, że w pionierskich czasach pamięć była tak skromna, że zarządzano każdym bitem. Porządek wymagał aby to jakoś poklastrować co od strony sprzętowej pozwoliło od strzała zwiększyć ilość dostępnej pamięci mul długość bajtu w bitach (zwracając nie jeden input sygnału, tylko cały pociąg). To wymusiło flagowanie (później 4bit) co tam dalej jedzie w wagonach (chr, int, float) oraz długość wagonu (później 4bit). W gpu takich rzeczy nie ma, sama kompilacja funkcji dyktuje jak będzie czesana pamięć (przyjmijmy od int8 do float32) i można tam sobie posadzić dowolne fikołki, które zostaną wykoane dowolnie głupio, ale zgodnie z instrukcją.
Strong data type miał o tyle sens, że patrz drukajka – lookup table chr (dziś znany jako ascii). A pewne moduły w klocku wymagają pewnej długości bitów dzięki czemu nie trzeba im wbudowywać pętli uzupełnienia końca wagonu do pełnej długości, a to upraszcza budowę klocka, jego produkcję i można więcej tranzystorów wyzyskać na użyteczności. Inaczej pół klocka zajmowałoby się tylko dopychaniem sygnału kolanem. Co prowadzi nas do ówczesnego sensu terminu bufor danych – to było to co dziś nazywamy typem danych. Taki bufor fixed był przygotowany jako zakres adres/indeks na dany rodzaj przechowywanego sygnału. Ponieważ typ danych się przyjął od strzała termin bufor przeniesiono piętro wyżej na zbiory takich danych wyznaczające gdzie znajdują się paczki. Było to o tyle wygodne, że indeksowanie bufora do komórek pamięci adres/indeks pozwalało go wozić po całej pamięci. Nie żeby ktoś zaraz chciał przenosić dane, bo to strasznie cykle wsuwa, ale pozwoliło na pewną elastyczność (jak buffer grow) i opisanie obszaru. A to właśnie było celem – takie wyznaczenie obszaru, który jest zastrzeżony w funkcji wykonania projektu na maszynie, a nie na etapie projektu, że w zeszycie zarysowano kratki pamięci “i tutaj będzie zestaw liczb tylko do tej funkcji, miejmy nadzieję, że w żadnej innej nie chlapniemy poke z tymi adresami”. Ponieważ można było nawet nadać nazwę takiemu buforowi (co prawda krótką, limit znaków w nazwach funkcji i zmiennych jeszcze pamiętam) i akurat wchodziły powszechnie dostępne, choć urywające kieszeń nośniki pamięci nieulotnej to pozostałością tej nazwy buforów i buforów w buforach w zapisie na dyskach są… foldery. Coś czego tak naprawdę na dysku nie ma, to tylko tagi dla użyszkodnika, na dysku jest zapis ciągły.
Tę samą logikę zastosowano (mając już praktykę nad pamięcią) do funkcji i tak powstały nam pewne rodzaje funkcji udające maszynę. Te paczki nazwano obiektami, żeby łatwiej było się homosapaczowi połapać jak do tego doszło, że uruchomiono jakąś funkcję. Bo w procku takiego podziału nie ma, wszystko na stacku jest obsługiwane jedno po drugim. Jest zupełnie bez różnicy czy odpaliłeś winampa czy edytor tekstu, a nawet oba na raz. Procek dostaje instrukcję i liczby w rejestr, a następnie przełącza szlaczki i zadaje sygnał (tę liczbę) przez otwartą właśnie ścieżkę (przez każdą, ale inne są zamknięte więc tylko ta działa). Czy to prowadzi akurat na dysk, do ramu czy do układu generującego sygnał audio prockowi za jedno. Ale użytkownik miałby kłopot próbując dozorować która funkcja na stacku do czego w tym tempie, mimo że to dalej linijka po linijce wali na stacka tak jakby 70 lat temu ktoś nabazgrał kod dźwięk do karty, literka na wyświetlacz, sprawdź input klawiatury, sprawdź stan kolejnego dźwięku na audio. Po prostu ten stack jest składany w locie i tylko na warstwach wysokiej abstrakcji użyszkodnik ma to polabelkowane co z jakiego procesu idzie i dokąd. Bo przyjmijmy, że użyszkodnik klika edytor tekstu, ten zaczyna zrzucać na stack jakie pliki pootwierać, co zassać, co mu przydzielić, gdzie się rysować i to będzie chwilę mieliło bo os ma priorytety, żeby wszystko ładnie wyglądało, żeby w tym czasie pokazywać dzień, godzinę, co na insta, obsłużyć przeglądarkę, myszę, sprawdzić co na USB słychać, a w tym czasie ten sam użyszkodnik stwierdza, że cicho tu, to zapuści jeszcze winapma. I na stack lecą polecenia co wczytać, skąd, jakie pliki, jakie ustawienia etc. Z punktu widzenia stacku proca to jeden wuj – to i tak jest tylko instrukcja, rejestr, rejestr, następny. Z punktu widzenia abstrakcji wyżej – jeden wuj, tylko dzisiaj to jeszcze pokolejkować priorytetem, poprzydzielać pamięć, podzielić między rdzenie, a później na taśmę i co proc zrzuci to już urządzenia będą się martwić czy to zeszło na audio czy na videło. Co na output to z kloca. Jednakże dla użyszkodnika różnica w pojmowaniu jest, bo gdyby przejrzał co się wyczynia pod spodem, to będzie miał tylko instrukcję, rejestr, rejestr. Fajnie jeśli do tego jest mapka “ta instrukcja to pobranie z klawiatury”, kontekst (300 lini stacku niżej) – focus jest na edytorze tekstu, keyboard string sanitizing – jeden znak na d(t) cykli w milisekundach, następnie buffer grow o chr, zrzucić z rejestru na bufor, odczytać z bufora, zrzucić do aplication surface na gpu, i niech się tam w gpu archeo martwi co z tym zrobić, dostali “tydzień temu” (20k milisekund), że na hdmi z vsync, co 7ms grabić z zakresu dla aplication surface to se ogarną, a dalej to sobie ogarnie monitor, który zczytano “pół roku” temu i miejmy nadzieję, że przez 6m milisekund nikt kabla nie przegryzł. Bo następna linijka jest już hopsztyliona innych, działających w tle dobroczyńców ludzkości. Czytać by się tego nie dało. Więc pierwsze co macie w każdym filtrze asm to wątek ograniczony do wybranego programu na klocku. I tylko ten wątek i jego przydziały są macane, a i tak zazwyczaj jest tam ciężko strawna kasza z gruzem.
W filmie jest to wyjaśniane, że chodziło o symulację urządzeń, ale to było w czasach, kiedy trzeba je było symulować bo ich nie było, co pozwalało symulować ich ping, brak odpowiedzi, synchronizację, resynchronizację, zrzuty danych. Dziś niczego symulować nie trzeba, dla dobra użyszkodnika (i zdolności czytania bo liczba cykli na sekundę “odrobinę wzrosła”) jest to wedle tej logiki podzielone. Dla porządku programy mają przydzielane wątki, ponieważ da się ich odpalić dużo “na raz”, to że są kolejkowane i wykonywane po kolei to inna sprawa. Ale rdzenie będące w zsadzie oddzielnymi urządzeniami muszą się jakoś podzielić ramem, dostępem do gpu, nad tą ośmiornicą w tej logice jest łeb, ale w sieci takiego łba nie ma i każdy musi sobie sam ogarniać, więc tu implementacja jest taka sama (gdyby któryś rdzeń dostał coś głupiego do roboty i nie mógł wyjść z delirki). Programy mają swoje wątki nazwane obiektami, nad nimi czuwa overlord, który je niby synchronizuje. Programy wykonywane linia po linii na jednym obiekcie są oczywiście szybkie (zaraz do tego przejdziemy) szczególnie jeśli jadą na fixed buffer. Wtedy ten obiekt jest tylko po to, żeby się bezpieka na os nie czepiała, że się tu jakieś podejrzane herezje uprawia.
To wszystko jest tylko dla porządku zrozumiałego przez homo sapcia, dzięki temu więcej homo sapciów może klepać koda nie bardzo orientując się co się dzieje pod spodem (samo się dzieje, krasnoludki). A pod spodem jak widzicie w tekście odbywa się głownie buchalteria. Adresy, liczba komnat, prawo do zasiedlenia, prawo wyjścia na plac zabaw i załatwienia potrzeby (dukarka, gpu, audio, klucz szyfrujący, hdd), albo prawo do popatrzenia tylko (na przykład hdd, ram). Ta buchalteria jest skomplikowana, bo jest dynamiczna, to taki urząd, gdzie mimo ciągłej przebudowy, zmiany numeracji pokojów i numerków w kolejce jest wysoce nieprawdopodobne aby ktoś z formularzem nie trafił do okienka. Czuwa nad tym kolektor garbatych. Którego to @gruby sklął bo ten kolektor zajmuje się raportowaniem do gminy, które lokale są do zasiedlenia. Odbywa się to tak, że usługa (odpalony program) wchodzi do wątku, i przydziela zmienną, w której przechowuje sygnał. To może być pojedyncza flaga, może być kilometr arraya, stringa czy inny mat1920x1080x4xf8. Przy włączeniu garbage collectora każda taka zmienna melduje się z jakiego programu (normalnie to jej wisi na drzwiach, ale tu musi się zameldować), jaki ma tam wewnętrzny numer (asset index) i ile zajmuje. Kolektor garbatych dzwoni do programu, pyta jaki typ danych jest pod asset index i ile komnat zajmuje. Jeśli się zgadza to zapisuje w kajecie, że okupant legalny i wpuszcza na ram. Co jakiś czas (wedle ustawień programu) łazi po ramie i jak jest labelka, że to początek data type to sprawdza czy z programu, który go wywołał, jeśli tak to czyta indeks, i w programie sprawdza czy adres assetu się zgadza, czy liczba zajmowanych komnat się zgadza, jeśli nie to oznacza, że miejsce jest do kolonizacji. I tak wkółko. Kolektor garbatych nie może jednak macać buforów. Jak coś skrewicie w programie z buchalterią buforów to dopiero wyjście z programu i kolektor garbatych os wywali co znajdzie jako przydzielone dla programu, który zabito i oznaczy do kolonizacji. Dlatego większość sposobów jak coś sknocić opiera się na majstrowaniu przy buforach, które typem danych nie są. Po staremu są przydziałem (nadzorowanym przez os) od kratki – do kratki. Oczywiście fragmentacja pamięci też podlega buchalterii, więc jeśli stworzy się dwa, nieregularnie przeplatane co f8 bufory po połowie ramu, to sama księgowość zajmie drugie pół. Zazwyczaj to większe^^
I to w zasadzie jest wszystko o czym ten filmik był, a czego nie wyłuskano na wierzch. Że cała ta zabawa w oops to buchalteria. Owszem potrzebna, tylko że na uniwersalne urządzenie liczące potrzebne są uniwersalne rozwiązania obsługujące ile się da. Czyli prowadzące zawsze więcej niż potrzebujemy do projektu. Co w wielu przypadkach oznacz, że prowadzenie buchalterii jest wielokrotnie cięższe niż same funkcje. W takim wypadku pozostaje albo robić duże, złożone programy, które tę infrastrukturę wykorzystują, albo wyłączyć ile się da tak żeby os nie jęczał i zrobić po staremu. Czyli na buforze z własnymi przydziałami po zeszycie. No i tutaj pojawia się pewien drobny zgrzyt. Bo to, że potrafimy to oczywiste, że z przyczyn historycznych potrafimy tym zarządzać bo nie było kiedyś wyboru – kolejna sprawa, ale przy obecnych potrzebach dawno przekroczony jest limit, w jakim da się to zrobić efektywniej niż robią to automaty. Co więcej… moc obliczeniowa pozwala włączać coraz większą liczbę homosapaczy do tej roboty kolejnymi uproszczeniami. Takim epickim osiągnięciem jest każdy visual. W zasadzie niepotrzebne, ale jeśli bez tego ktoś nie umie zarządzać liczbami, a z tym umie to jest to proteza dedykowana właśnie dla niego. Ilość zabezpieczającej buchalterii wkoło i na poziomie os co prawda uniemożliwia takiej osobie robienie rozwiązań niestandardowych, ale zupełnie wystarczających do większości zastosowań. I to jest clue filmu – może poszło w dziwną stronę, ale działa. Natomiast wniosek jaki tam wyciągnięto – czy warto umieć po staremu, bo może gdzieś ten labirynt nawarstwionych rozwiązań źle skręcił jest jak najbardziej poprawna. Może istnieją inne, efektywniejsze drogi. Tylko że po wciągnięciu stack overflow jako danych treningowych dla copiolta i innych ejaj wsparcia komu będzie chciało się rozgrzebywać to wszystko od poziomu asm od nowa? To są kwestie dotyczące kształcenia związane z Dukajową koncepcją postpiśmienną. W przemyśle symulujemy to grupą zadań, które trzeba wykonać przy użyciu prymitywnych narzędzi. Nie po to żeby to robić, ale żeby wiedzieć że się da i rozwiązanie istnieje. To zabawy z gatunku użycie pilnika obok obrabiarki, która może zrobić to samo szybciej, lepiej, dokładniej. Czy cięcie blachy wiertarką i przecinakiem. W tej samej szkole uczone są podstawy działania najmniejszych klocków (żebyśmy mieli wyobrażenie co się dzieje w sterowniku, bo tam klocki ciągle są duże, a kodu mało i wszystko asm). Podejrzewam, że ma to tyle samo sensu co nauka czytania i pisania. Skoro wystarczy kliknąć ikonkę aby urządzenie na głos odczytało, a zostawianie śladu na papierze odbywa się najwyżej w toalecie to spędzanie czasu nad zagadnieniami “czytanie i pisanie” jest atawistycznym ekscentryzmem. Ale brak tych kwalifikacji widać w działaniu programów, w kodzie, na forach – rozwiązywanie nieistniejących problemów, i tworzenie kolejnych warstw abstrakcji do rozwiązania problemów, które już zostały rozwiązane dawniej, prościej, efektywniej tylko wyginęli ludzie, którzy rozumieli jakie własności danych wykorzystano aby tak to zrobić.
Ma to pewne, dość istotne konsekwencje. Maszyny uczą się na najpowszechniejszych danych. Miliony much nie mogą się mylić. Ponieważ kwestia tworzenia instrukcji bezpośrednio sygnałem i na najniższych poziomach abstrakcji nie jest powszechna to i maszyny nie będą ogarniać zagadnień, które w danych treningowych wystąpią co najwyżej historycznie. Problemy przestaną być rozwiązywane ponieważ nie będą występować. I wtedy coraz trudniej będzie ochronić układy elektroniczne przed ingerencją wykorzystującą nieoczywiste własności złożenia układu i sygnału. Istnieją oczywiście “niszowe” dziedziny, gdzie omawiane kwestie są progiem wejścia. Wcześniej to były superkomputery, a obecnie zastępujące je klastry gpu. Chodzi głownie o operacje na tensorach binarnych, czyli takich, gdzie na przykład mat4x4 zawiera wyłącznie włączenia (zera lub jedynki, a nie zakresy 0-1) wykorzystywane do hurtowych obliczeń na bardzo okrojonym zakresie instrukcji (chyba 4bit). Te urządzenia, ze względu na oczekiwaną wydajność kalkulacji nie mają nic zbędnego (czołg jest piękny, ponieważ nie posiada niczego co nie jest potrzebne do spełniania jego jedynej funkcji; coś jak młoda blondynka), nie sprawdzają danych (data type, byte length), nie wykonują żadnej operacji kontrolnej. Dane wchodzą w potok i opuszczają przetworzone zgodnie z sygnałem instrukcji. Jeśli coś się po drodze zgubiło lub pomyliło – problem siedzi na krześle przed monitorem. Jest to tak zorganizowane dlatego, że każda funkcja sprawdzająca, każde rozdzielenie skopiowanego sygnału, każdy sync podwaja zasoby niezużyte na wynik i to zużycie rośnie wykładniczo. To jak postawienie kontrolera jakości przy każdym pracowniku, następnie kontrolera do kontrolerów i kogoś kto upilnuje strażników. Już w pierwszej iteracji mamy więcej zasobów na kontroli niż przy robocie. I tak działają urządzenia do kodoklepstwa, jakie homosapacze mają w domach, dlatego kod wygląda jak makaron i ludzie drą japy, że na nowoczesnym sprzęcie aplikacje im lagują. To właśnie ta biurokracja pilnowania danych “dla bezpieczeństwa użyszkodnika” w funkcji “myślących jest mało więc kosztują, dobierzmy programistów z pozostałych” pożera gigantyczne zasoby ukryte w domowych piecykach.
Oczywiście pojawiły się koncepcje by zakazać nauki i użycia niskich poziomów abstrakcji bez kapitańskiego pozwolenia (z rok temu latały takie memy). Ale tego się nie da odzobaczyć i narosły wraz z oops bagaż biurokracji w danych (czyli ciągłych check and recheck) prędzej czy później skończy jak Kartagina. Przy czym niekoniecznie dlatego, że nagle znajdziemy złoże myślących homosapaczy, tylko ejaje ogarną sensowną kompilację oczekiwań takich homosapaczy jakie są wprost na instrukcje (z pominięciem asm) co krok po kroku zmieni sposób projektowania układów na takie, które mają mniejszą liczbę instrukcji (tak jak ten 4bit) za to więcej różnych klocków z różnymi zestawami instrukcji. Co akurat ma miejsce jeśli rozłożycie logikę klocka na części – choćby otwarcie ścieżki labiryntu do addera zawiera 1bit instrukcję. Pierwsza to proste wrzucenie w rejestr addera dwóch sygnałów i przepuszczenie w kolejności bitów przez układ bramek będący tablicą prawdy z wpuszczaniem 1bit carry w pętli. Banalna kaskada. Druga to kierująca do układu, który odejmuje. Sygnałem sterującym jest przepuszczona przez bramki będące tablicą prawdy flag sygnału – jeśli są różne to odejmować, inaczej dodawać. Są do tego dwa, oddzielne układy o powierzchni maksymalnej (obecnie najnowsze dla 64bit) w okolicach 950x500nm. W przypadku gpu powszechniejszym układem jest multipler (rozmiaru 1.5kx1.5knm) nadziobany po całym układzie kaskadowo w macierzach 4×4 z adderami. Tylko w gpu jest prostszy rejestr i oddzielnie są układy do i8,i16,f8,f16 (dominujący w powszechnie dostępnych),f32 i f64 (jeśli akurat na karcie f64 było do czegoś potrzebne). Rozmiar tych układów zależy wprost od rozmiaru rejestru w funkcji akurat stosowanej szerokości ścieżki (i ich gęstości w warstwach). Czyli układy robiące za superkomputery (i1 czyli tylko zero lub jeden) na tym samym rozmiarze płytki mogą tak teoretycznie ca 16^2 razy więcej, ale robią tylko operacje na mat4x4(i1 – boolean semiring, kto dłubie w transmicjach, a mamy takich czytelników skojarzy Hamminga:
https://en.wikipedia.org/wiki/Hamming_code
), które ze względu na swój własny dział wydziału dla czubków, ze względu na pewne własności takich macierzy mają bardzo dużo wzorów skróconego (wręcz tablicowego, czyli można tworzyć układy, które zamiast liczyć ze wsadu od razu wypluwają wynik bez liczenia, tylko rozpoznając sygnał 16bit) i są dla nich takie układy robione – do niczego w komputerach ogólnego zastosowania to się na razie nie przydaje. Oczywiście dział z czubkami używa normalnych kompów do symulowania (piękne zatoczyliśmy koło odnośnie topicu w filmie) tych układów, przygotowania danych wsadowych i interpretacji danych na wyjściu. Gdyby graficznie przedstawić taki wsad to jest on obrazkiem wysokości 4px i długości stąd do tej palmy i w pi… jeśli komuś kojarzy się z taśmą perforowaną – tak, technologia zatoczyła koło. Tylko ten wsad nie jest czytany po długości, a po szerokości. Dlatego jest fast fast. To są równoległe, połączone dalej w kaskadzie układy będące tymi właśnie komputerami o jakich w filmie omawiane jest symulowanie sieci urządzeń. I działa to bez żadnych obiektów, bez żadnych check data type, żadnych obszarów zastrzeżonych (cały zeszyt wchodzi na raz) bez żadnej buchalterii obniżającej wydajność. Nie ma debugowania w locie, nie ma niczego zbędnego. Logika przygotowania wsadu i interpretacji danych jest poza układem. To właśnie dlatego istnieje oops – aby więcej homosapaczy mogło dane interpretować. A to że wróciliśmy do tego rozwiązania po takiej pętli rozrastających się instrukcji x86, arm i innych manowców wskazuje, że problem jest po stronie homospacza, a wróciliśmy bo tak zorganizowane układy wyodrębniliśmy właśnie do podawania nam raw data – wszak gpu zajmuje się wyrzuceniem na ekran właśnie macierzy, takiej taśmy perforowanej rozmiaru ekranu, gdzie wybija dziurki, żeby widać było czerwone, zielone i niebieskie.
Kolejne poziomy abstrakcji są potrzebne homosapaczom, nie rachunkom. Uorganizowanie i porządek jakiego potrzebujemy w systematyce aby wyobrazić (ci którzy muszą) co jest czym i ponazywać świat przywołując bóstwa i demony to jest problem w głowie, nie w kalkulatorze. Obciążyliśmy tą robotą kalkulatory i przepaliliśmy kupę zasobów by rozwinąć branżę. Nie jest to jednak potrzebne do realizacji samej funkcji urządzenia. Pozostaje kwestia jak szybko ejajami ogarniemy kompilatory z naszego sposobu myślenia na te mat(4×4)i1 (chyba że homosapki na wydziałach odkryją dość wzorów dla innych tensorów; jest tu problem z rozmiarem, co działa na 4×4 niekoniecznie działa na 3×3, a co innego działa na 5x5x5x5); większość badań dotyczy 4×4. Bo takie układy są i nie ma co zmieniać, ale konsekwencją takiego porządku jest absolutny determinizm (ta karta w kratkę) całego programu:
https://en.algorithmica.org/hpc/pipelining/branchless/
którego każdy krok ze względu na uint16 jest wykonywany w jednym cyklu zegarowym, a wątków równoległych po gpu jest… i jeszcze trochę.
Przy takim rozwoju wypadków historia znowu zatoczy koło – tak jak z cachu wyodrębniono ram, i na tej bazie wyodrębniono zewnętrzne nośniki stałe, i z regionu cache pobieranego przez przetwornik telezorki wyodrębniono gpu, które nie jest uniwersalnym, programowalnym urządzeniem jak cpu, tylko kaskadowym uproszczeniem, ale cholernie szybkim na mniejszej liczbie instrukcji tak… prawdopodobnie wyrośnie nam w kompach kolejny układ oparty o f1, dla którego cpu będzie tylko interfejsem z homosapkowego na ejajowy. Bo tak to obecnie działa, że wsad przygotowywany jest na normalnym kompie dla zjadacza chleba i wrzucany w te superkalkulatory, przy których rezultaty hajpowanych komputerów kwantowych to nieporadne robienie pod siebie. Bo działa. Zwracam jednak uwagę, że zaczęliśmy tę opowieść o organizowaniu pamięci z poklastrowania 1bitowych komórek pamięci w bajty ładowane pociągiem. I wracamy do układów operujących mat4x4f1 czyli 16bitową paczką danych oraz 4bitową instrukcją co z tym zrobić. Gdybyśmy mieli nad tym móżdżyć to dla ludzkich potrzeb byłby to 20bitowy odpowiednik bajtu. Tak działa. Ale nie trzeba nad tym móżdżyć, bo z punktu widzenia maszyny te wirtualne podziały potrzebne nam nic nie znaczą gdyż na wejściu każdy z tych 4+16 trafia oddzielnie do swojego wejścia z kaskady. Najwyżej ma pustą instrukcje (użyszkodnik nie dał danych). Cała ta robota z podziałem pamięci, przydziałami, typami danych (jak ktoś ma buty na rzepy to nawet obiektami) jest potrzebna homosapaczowi przy interpretacji na wyjściu i ewentualnie przy poprawianiu procesu (debug) jeśli coś sknocił i nie wie co. Maszynie nie jest to potrzebne i jest to zbędny bagaż.
Dlatego lektor w filmie ma rację – ten sposób myślenia i te sztuczki będą potrzebne. Ale nie będą potrzebne wszystkim tylko dokładnie tym, o których opowiadał – tych co to robią. Dla pozostałych pozostanie interfejs o takim czy innym poziomie abstrakcji. Interfejs z maszyną, która sobie na bazie kulawego, ludzkiego kodu skompiluje przeskakując poziomy abstrakcji w taki sposób, o jakim tu i ówdzie wspomniał @Koncereyra. Na razie jest to jeszcze w powijakach, ale ejaj z kodu potrafi wywnioskować co jest return (Out) i co jest argumentem (In). Później prześledzić co się z tym robi i uprościć obsługę (bo tego nie trzeba tu mnożyć, a tam sprawdzać bo to wynika z tego, a to jest oczywiste i inne być nie może). Na razie z jedną funkcją ejaj sobie jakoś tam kulawo radzi (@Koncereyra twierdzi, że te testowane na dużej liczbie tokenów radzą sobie z dłuższym kodem całkiem poprawnie, i uważam to za wiarygodne, bo o tokeny głównie się potykam musząc rozkładać równania na kawałki) i od biedy potrafi ją uprościć. Jeśli uprości tak szereg funkcji nie będzie musiał sprawdzać data type, bo ten będzie znany. A upraszczając dalej będzie mógł powywalać labelki zmiennych, obiektów i procesów z góry wiedząc co zejdzie w którą komórkę pamięci. Dokładnie tak jak robiliśmy to w zeszycie i robimy na pojedynczych klockach, które są na tyle małe, że jeszcze ogarniamy kuwetę na kartce w kratkę o ile jest ona z zeszytu, a nie ma rozmiaru kontynentu. Po wywaleniu tych wszystkich biurokratycznych upierdliwości uzyskany program będzie co prawda blackboxem do odczytania dla człowieka (przetworzenie logiki na układ bramek w kaskadzie gpu pod 4x4f1) i pozostanie kwestia, czy proces jaki doprowadził do jego powstania (razem ze wszystkimi przetworzeniami tej logiki przez ejaj) gdzieś składować. Tak żeby można było odczytać i zrozumieć. Zapewne będzie on potrzebny wyłącznie w sieci internet of ai (ioai) jako badane po skutkach i opinii użyszkodnika (działa/nie działa) dane treningowe. Zwracam uwagę, że to będą głownie dane jak rozumieć homo sapka i jego kulawy kod wysokiego poziomu czyli bryki dla ejaj “co autor ma na bezmyśli”. To problem który często mamy w robocie – przychodzi art director i pierdoli jak potłuczony, że z shadera na wyjściu jest “za bardzo zielone”, co to urwał znaczy “za bardzo” w odniesieniu do koloru ciężko pojąć, coś zielone albo jest albo nie jest, ale jak pan każe tak ja łażę, zadajemy mul <1. na zielone i pytamy czy to chciał, a ten “nein, nein!” no i weź się z typem dogadaj. Małpa z drzewa spadła i na rzeczywistość skrzeczy. Ma wyjaśnić jak ma być, a nie jak ma nie być. Ejaje mają dokładnie taki sam problem z interpretacją promptu od homosapa jeśli chodzi o przekład na liczby. Bo takiego poprawnego kodu z objaśnieniem i specyfikacją to zachowało się może trochę z wczesnego programu kosmicznego i wczesnej komputeryzacji awiacji. Cała reszta to radosna twórczaść komercyjna, gdzie cięto koszt na wszystkich, w szczególności na specyfikacji i zgodności. Stąd mamy przypadki francuskich rakiet kiedy układ nawigacyjny pierwszego członu na 8bit (wiekowy) przekazuje dane do drugiego, który ma wynieść (64bit) i kilometr nad ziemią okazuje się, że testy tego transferu odbyły się jedynie kanapowo w ramach rozważań teoretyczny “beeeedzie dobrze” po czym cała rokita zmienia kurs i widowiskowo rozpada się nad Gujaną. Raczej nie najlepsze dane treningowe dla ejaja, chyba że jako przykład “jak nie robić”, ale to jak z dyrektorem artystycznym “za bardzo zielone”.
Czy w populacji będziemy mieli dość ogarniętych ludzi kształconych w tej konwencji “pisma” idąc Dukajem? Przy tej liczności populacji, jeśli nie wprowadzimy zamordyzmu edukacyjnego być może się gdzieś to zachowa bo ludzie mają czas na hobby z dziećmi. A później jeszcze jacyś ciekawscy z puli się dokleją po drodze. Kiedy omawiani twórcy oopsa rozpoczynali edukację Stalin miał się dobrze, a komputery na planecie można było policzyć na palcach pracownika tartaku. Żadnej kierunkowej edukacji pod rozwiązywanie tych problemów nie było. Problem nie istniał. Zapewne ten problem wcale nie istnieje poza wąskim gronem nerdów w tym dłubiących. Kilka miliardów homosapków żyje w środowisku technologicznym, którego nie tylko nie potrafi odtworzyć, ale nawet nie ma aparatu pojęciowego aby sobie wyobrazić jak i dlaczego działa – w niczym to nie przeszkadza. Tak samo jak ejaj nie umie myśleć, ale posługuje się słowem tak, że da się nabrać tak homo sapki posługują się technologią wystarczająco skutecznie bez konieczności zrozumienia. Nie trzeba znać chemii i fizyki by rozpalić ognisko, można nauczyć posługiwania się ogniem bez tego bagażu. No ale wypada mieć kartkę w kratkę:
https://en.wikipedia.org/wiki/Logical_matrix
Stoimy przed zagadnieniem społecznym, które w historii gatunku nigdy nie wystąpiło. Przyjmując, że wykonywanie użytecznej pracy jest odpowiednikiem zdobywania zasobów/pożywienia to obecna złożoność tego procesu wyklucza ponad połowę populacji z uczestnictwa w produktywnej aktywności i ten limes szybko przesuwany jest w prawo. Ze względu na sprawność procesów nie przeszkadza to w wykarmieniu (również innymi zasobami pierwszej jak odzienie czy smartfon z dostępem do pornoli) populacji, która się w procesach nie przydaje – nadwyżki są tak ogromne. W tej nie jest wcale takim głupim pomysłem, aby tych co się dadzą złapać w siatkę wywieźć do okupu na okoliczność fikcyjnego konfliktu o nic, który bardzo przydaje się w rozwiązywaniu problemu społecznego.
