9:42
4/5/2015

W ostatnich dniach głośno było o katastroficznym problemie wykrytym w oprogramowaniu Boeinga 787 (tzw. Dreamlinera) — błąd programistyczny pozbawiał samolot samolot zasilania, jeśli jego generatory nie były wyłączane przez 248 dni. Ale mało kto wie, że niemalże taki sam błąd 24 lata temu został odkryty w baterii przeciwrakietowej Patriot. Przyjrzyjmy się tym dwóm incydentom bliżej.

Jak błąd Patriota zabił 28 żołnierzy?

Jest 25 lutego 1991 roku. Trwa wojna w zatoce perskiej. Koszary amerykańskich żołnierzy w Dahahran przed irackimi rakietami Scud ochrania mobilny, bo montowany na ciężarówce, rakietowy system ziemia-powietrze Patriot (na marginesie, jego kolejną wersję właśnie zakupiło Wojsko Polskie). System, pomimo wysokiej skuteczności szacowanej na 90%, nie zauważa jednej z irackich rakiet Scud, która trafia w koszary i zabija 28 amerykańskich żołnierzy.

Kiedy wojna się kończy, amerykańscy naukowcy analizują incydenty, w których Patrioty nie zadziałały poprawnie. W lutowym wydaniu New Scientist w 1992 pojawia się obszerny artykuł na ten temat. Profesor Ted Postol stawia tezę, że jedną z przyczyn zawodności systemu jest nowa wersja rakiety Scud, Al-Husayn, która jest tak niestabilna, że “kruszy się” podczas wejścia w atmosferę. Jej odpadające fragmenty mają ogłupiać Patrioty.

W marcu 1992 pojawia się jednak raport rządowej jednostki (General Accounting Office) który odnajduje dokładną przyczynę problemów Patriota — błąd programistyczny. Oto kluczowy fragment raportu:

Zadaniem systemu Patriot jest przewidzenie gdzie rakieta Scud pojawi się za chwilę. Pozycja jest wyliczana w oparciu o znaną prędkość i czas ostatniej lokalizacji rakiety na radarze. Prędkość jest liczbą rzeczywistą, np. 3759.2563 mil na godzinę, a czas pobierany z zewnętrznego zegara urządzenia z dokładnością co do dziesiątych sekundy i zapisywany jako liczba całkowita (32, 33, 34). Im dłużej system działa, tym większe są wartości idetyfikujące czas (2035, 2036, …). Aby ocenić przewidywane położenie rakiety Scud, zarówno prędkość jak i czas muszą być wyrażone jako liczby rzeczywiste. Niestety konwersja liczb jest ograniczona przez 24 bitowe rejestry systemu Patriot i tylko z taką precyzją jest w stanie zapisać liczbę. Brak precyzji w obliczeniach jest więc wprost proporcjonalny do czasu działania systemu i prędkości rakiety.

Systemy Patriot, które działały dłużej bez restartu, nieprecyzyjnie konwertowały czas. Patrioty w Dhahran działały bez przerwy dłużej niż 100 godzin. Po takim czasie pracy, błąd w konwertowaniu czasu wynosił 1/3 sekundy, co przy prędkości rakiety Scud sprawiało, że system spodziewał się jej w miejscu oddalonym o 600 metrów od poprawnego. Rakieta była więc wykrywana, ale kiedy Patriot zaczynał jej namierzanie, nie widział jej w kolejnych obliczanych przez siebie obszarach na niebie. System stwierdzał więc brak rakiety i nie podejmował reakcji.

To nie koniec pouczającej historii dla programistów. Analiza incydentu wykazała bowiem, że dokładnie 2 tygodnie przed tragicznym wydarzeniem w Dhahran, 11 lutego 1991, izraelscy inżynierowie odkryli błąd w precyzji obliczeń systemu Patriot, który stosowany jest przez okres dłuższy niż zalecany (ok. 8 godzin), o czym poinformowali armię USA a jako doraźne obejście błędu doradzali regularne restartowanie baterii Patriot. Tuż po otrzymaniu informacji o błędzie, producent Patriotów rozpoczął prace nad patchem i 26 lutego 1991 wypuścił łatkę do oprogramowania Patriota.

Teraz spójrzcie na datę na początku rozdziału… Wykorzystywanie produktu niezgodnie z instrukcją, brak skutecznej dystrybucji informacji o “obejściu” i spóźniona o jeden dzień łatka kosztowała życie 28 żołnierzy.

Dziura w Boeingu 787 Dreamliner

Przenieśmy się o 24 lata do przodu. Kilka dni temu amerykańska agencja nadzorująca lotnictwo FAA, wydaje raport, w którym informuje o błędzie w oprogramowaniu Dreamlinera (Boeinga 787), który powoduje wyłączanie generatorów prądu. Przyczyną jest tzw. integer overflow na wewnętrznym liczniku w oprogramowaniu generatorów. Przepełnienie zmiennej licznika powoduje przejście generatorów w tryb failsafe, podczas którego moc nie jest dostarczana do urządzeń samolotu. Dreszczyk pojawia się wtedy, kiedy wszystkie 4 generatory jakimi dysponuje Dreamliner włączono w tym samym momencie — ponieważ wtedy każdy z nich przestanie działać w tej samej chwili.

Richard_Soderberg_on_Twitter____SamuelGibbs_2^31_centiseconds___248_55_days__So__the_787_is_likely_shutting_down_because_of_a_signed_32-bit_integer_overflow_____

Dziennikarze relacjonujący raport sugerowali, że przy braku energii elektrycznej Boeing 787 stanie się “latającą cegłą“; bez działającej klimatyzacji, oświetlenia i bez wszystkich elektronicznych systemów sterowania, czyli tzw. fly-by-wire, który stopniowo wypiera rozwiązania hydrauliczno-mechaniczne. Guardian informował, że jeśli awaria generatorów nastąpi podczas startu lub lądowania, jej skutki mogą być katastrofalne. Żartowano też, że przed rozpoczęciem podróży Dreamlinerem, dla bezpieczeństwa i wyzerowania zmiennej w generatorze prądu, pasażerowie powinni poprosić pilota o zrestartowanie samolotu.

Wśród komentujących ten incydent miłośników lotnictwa problem bagatelizowano, twierdząc, że podczas utraty generatorów załączą się akumulatory, dające wystarczająco dużo czasu, aby “zrestartować” generatory, a dodatkowo samoloty wyposażone są także w tzw. RAT (Ram Air Turbine) generujący prąd na podstawie ruchu powietrza pod samolotem.

Jakie jest oficjalne stanowisko Boeinga? Producent uspokaja, że nigdy nie zdarzyło się, aby jakikolwiek z samolotów nie był wyłączany przez okres ponad 8 miesięcy. Poprawkę jednak oczywiście wypuści.

Pani doktor nie wejdzie do szatni, bo system nie pozwala

Na koniec, aby trochę zdystansować się od rakiet, wybuchów i spadających samolotów, chciałem pokazać, że nas — przeciętnych zjadaczy chleba — błędy programistyczne częściej będą dotykać w innych sytuacjach.

Przykładem jest pewna pani z tytułem naukowym doktora, która udała się na siłownię, ale nie była w stanie wejść do damskiej szatni. Przydzielony jej kod wejścia nie był przyjmowany przez zamek. Po zgłoszeniu problemu obsłudze zauważono, że system przypisał kobiecie kod do szatni męskiej. Dlaczego? Bo programista uznał, że jeśli ktoś ma tytuł naukowy “Dr”, to musi być mężczyzną. Pani doktor nie była zadowolona sugestią personelu, że do szatni wejdzie, jeśli zrezygnuje ze swojego tytułu naukowego na swojej karcie członkostwa…

CAdrt-QWgAE0SRG

PS. Wszystkie prowadzone przeze mnie szkolenia dla programistów otwieram zestawieniem kilku błędów programistycznych, które zakończyły się albo śmiercią albo wielomilionową stratą, aby pokazać jaka “moc” i “odpowiedzialność” drzemie pod palcami programistów. Poza powyższymi, warte uwagi są także problemy urządzenia Therac-25 i problemy rakiety Ariane 5 a także Mars Climate Orbiter i pewien ciekawy przetarg dla lotniska w Los Angeles. Jeśli chcecie dowiedzieć się jak bezpiecznie programować, aby ustrzec się nie tylko takich jak te opisane powyżej błędów, to zapraszam do udziału w szkoleniu z Atakowania i Ochrony Webaplikacji — najbliższy termin to 15-16 czerwca w Krakowie.

Przeczytaj także:

96 komentarzy

Dodaj komentarz
  1. no i az strach usiasc do roboty po takim artykule na poczatku tygodnia…

  2. Ludzi dzielimy na dwie grupy:
    1. Tych co czytają instrukcję przed włączeniem urządzenia
    2. Tych co czytają po pierwszej awarii

    Oba błędy ten z 787 jak i ten z Patriot-ów były opisane w instrukcjach. Jak widać nikomu nie chciało się czytać “tych głupot”.

    • A ty czytałeś jakąś instrukcję ? Instrukcje są jak przepisy prawa.Rozwlekłe (uwzględniają w cholerę przypadków które się prawie nie zdarzają),często źle napisane i często nie wiadomo co dokładnie znaczą. Ujmijmy to tak: nie każdy jest Rain-Manem czy kimś tego rodzaju by delektować się czytaniem encyklopedii czy książki telefonicznej. Większość ma to serdecznie “gdzieś”. Można ludziom napisać po kilku miesiącach czy latach wytężonej pracy (choć teraz można to zrobić po części programowo) wyśmienity tekst na 50 albo 100 stron który przedstawia wszystko co użyteczne z tekstu będącego odpowiednikiem encyklopedii Britannica z tysiącami stron.I co ? Większość ma to gdzieś ! Doświadczenie uczy,że nawet przeczytanie 4 stron to często dla nazbyt leniwych osobników zbyt wielki wysiłek.I to niezależnie od wykształcenia i pozycji społecznej.
      Co należy robić w takich sytuacjach ? W przypadku samolotów reset powinien być standardem (sprzętowym lub zawartym w oprogramowaniu) po lądowaniu,w przypadku zaś baterii Patriot – wymuszony reset po góra 16 godzinach pracy (24 to już błąd rzędu 0,07 s). Programista piszący coś zaawansowanego,który zakłada,że użytkownik zrobi coś za niego i nic nie spieprzy niechcący (bądź umyślnie) jest po prostu bawiącym się w pisanie kodu pętakiem. Zwłaszcza, jeśli to jest kod systemu od którego zależy bezpieczeństwo – w tym systemu typowo wojskowego jak Patriot.

    • @kez87, w taki sposób powinniśmy zwolnić wszystkich żołnierzy, bo jeżeli mamy na nich polegać, to wg Twojego zdania lepiej tego nie robić… Programista, który napisał program w konkretny sposób i dał do niego instrukcję jest zwolniony z odpowiedzialności. To Twój obowiązek przestrzegania instrukcji i używania urządzenia i oprogramowania ZGODNIE Z CELEM I WYMAGANIAMI. Nikt nie będzie odpowiadał za Twoje “widzi mi się np. nie czytać i nie słuchać”. Chciałem podać przykłady błędnych “programowych restartów”, usterek czy innych sytuacji, ale nie ma sensu ani powodu. To co napisałem wcześniej broni się w 100%. Kupując suszarkę masz jej nie wrzucać do wody, nikt za to nie będzie odpowiadał.

    • @kez87, dodając do poprzedniego komentarza – znam forum i ludzi, którzy zjedliby Cię, gdybyś zaczął używać wiertarki/wiertła/wkrętarki/piły/etc. w sposób niezgodny z instrukcją i przeznaczeniem, a to dlatego, że są to profesjonaliści i ludzie, którzy wiedzą, że jeżeli coś jest używane zgodnie z instrukcją, to nie ma prawa się popsuć i będzie działało tyle ile zakłada producent, a nie kilka dni… Więc są ludzie, którzy czytają instrukcje/zalecenia i wykorzystują sprzęt zgodnie z przeznaczeniem. Reszta to debile, które później płaczą, że coś im się zepsuło, a nowe, albo że to nie ich wina tylko kosiarki, że im obcięła paluchy, bo grzebali przy włączonej… Taka kosiarka z pewnością powinna mieć system wykrywania żywego ciała i powinna się automatycznie blokować… Tiaa…. Znam osobiście typa, który stracił czubek palca (dokładnie to pozbył się paliczka dalszego) przez kosiarkę, ale nie przeszkadza mu to w kontynuowaniu tej praktyki dalej… Głupi niczego się nie nauczy…

    • @Przemysław. Mój znajomy twierdził, że przy izolowaniu wolno pasących się kabli zasilających, nie musi wyłączać bezpieczników, bo prąd jest ZAWSZE na czarnej żyle. Jakież było jego zdziwienie, gdy prąd znalazłem u niego w domu na metalowej obudowie gniazda zasilającego.

    • Szanowny kolego,

      to nie jest toster, albo kości ram, że instrukcje przeczytasz w 1-2min.

      Dokumentacja samolotów składa się z wielu tomów po kilkaset stron, z czego po kilka dotyczy określonego JEDNEGO zakresu.

      Przeczytaj byle jaką książkę, nawet taką która posiada 50 stron i zapamiętaj z niej każdą wypowiedź.

      Pozdro.

    • “Programista, który napisał program w konkretny sposób i dał do niego instrukcję jest zwolniony z odpowiedzialności. To Twój obowiązek przestrzegania instrukcji i używania urządzenia i oprogramowania ZGODNIE Z CELEM I WYMAGANIAMI”

      Taki programista umie kodzić,umie coś zaprogramować,może nawet ma wykształcenie informatyczne i zarabia może kopę kasy ale jest totalnym,nieodpowiedzialnym patałachem. Prawa Murphy’ego są diabelnie ważne zwłaszcza w bezpieczeństwie i wojskowości.Mówią one bardzo streszczając,że jak można coś spieprzyć,to zawsze znajdzie się taki co spieprzy.

      Co do zwolnienia z odpowiedzialności.Równie dobrze możesz stosować w kodzie funkcje takie jak gets() i napisać w instrukcji,że nie wolno tu i tu wpisywać więcej niż n znaków.Ale takie programowanie jest gów… warte, wie to nawet taki newbie (albo i lamer – nie wiem jak mam oceniać swoją wiedzę) jak ja i jeśli ktoś tak pisze programy,to niech pomyśli nad zmianą zawodu – np. na jakiegoś fotografa. Przy okazji, tak patrząc poniżej liczby zmiennoprzecinkowe, to też niezły syf – choćby dlatego bardziej mi się podobają liczby stałoprzecinkowe nawet jeśli są “droższe”.

      Po prostu dobry inżynier (nie tylko oprogramowania) stara się,by produkty masowe które trafiają do różnych ludzi były CHOĆ TROCHĘ IDIOTOODPORNE. A mówić,że “jest w instrukcji i to zwalnia od odpowiedzialności” to może marketingowiec czy ktoś kto wciska innym zwyczajną niedoróbkę i tyle. Wszyscy popełniamy błędy,ale wiadomo jak ocenić kogoś kto upiera się,by w nich tkwić.

      “znam forum i ludzi, którzy zjedliby Cię, gdybyś zaczął używać wiertarki/wiertła/wkrętarki/piły/etc. w sposób niezgodny z instrukcją i przeznaczeniem, a to dlatego, że są to profesjonaliści i ludzie, którzy wiedzą, że jeżeli coś jest używane zgodnie z instrukcją, to nie ma prawa się popsuć i będzie działało tyle ile zakłada producent, a nie kilka dni…”

      Co nie zmienia faktu,że zakładanie,że sprzęt obsługuje przeszkolony specjalista który stosuje się do każdego słowa instrukcji jest zwyczajnie nierozsądne. Pewnie,że ze sprzętu powinno się korzystać zgodnie z instrukcją.Ja to wiem,ty to wiesz – ale są tacy którzy tego nie wiedzą.I niestety nawet “ludziom specjalnej troski” tak do końca nie zabronisz.

      Taka kosiarka z pewnością powinna mieć system wykrywania żywego ciała i powinna się automatycznie blokować…
      Instrukcja obsługi kosiarki dla idiotów mogła by zostać zapisana czcionką 12 na kartce a5 albo a6. Wlać paliwo i olej,Nie pchać palców do włączonej,pociągnąć silnie i szybko za sznurek żeby włączyć i dopompować jak po kilku pociągnięciach sznurka się nie włączy.
      Aha – można jeszcze dodać żeby nie przegrzać silnika,nie pchać jak silnik gaśnie i jak jest koszyk z tyłu to go regularnie opróżniać,nie kosić na kamienistym lub pełnym gałęzi terenie,ewentualnie może coś z pochylaniem. Coś jeszcze ? A tu masz dla porównania:
      http://books.googleusercontent.com/books/content?req=AKW5Qac5FP1BtI0cXRkRpu1kvHZ53AHaidUBc53FE066yrCjB8CNajd46qIZNCDYuLu3fLqzVlgfpGtqtOk3bxCvflsBveXKKmLpbHVOZ18s12Qe7m885rI_Iu9i0OIqqsZR8imML2-bzLC74-7Q33tlcBqBAMLtnBknHqAi19NWN2CUMjfyXzys-hHGFbo7KUTu24jr-JIDNrF0dTsQNki0NRaFcxMCTiOSIfFyJoY02vdFnbZjahadgP2kRvcV-QoU2M4VmvJ3
      ponad 550 stron. @Przemysław: Porównuj to z kosiarką. Wzorowe opanowanie tego rodzaju instrukcji jest oczywiście możliwe ale wiara w to,że człowiek nic nie spieprzy przez lata pracując przy takich systemach jest tak głupia,że to szkoda komentować.

    • Piszę i mam – sknociłem sam :P

      tekst “Taka kosiarka z pewnością powinna mieć system wykrywania żywego ciała i powinna się automatycznie blokować…” – powinien być oczywiście w cudzysłowiu,żeby było jasne,że to poniżej to odpowiedź.

    • @kez87, ale nie to nie była odpowiedź, bo i na co? Nie napisałem wcześniej żadnej wypowiedzi teoretycznego debila. Wyraziłem myśl jaką i wyrażaliby tacy debile… Nvm, wiadomo o co chodzi…

    • @kez87 @Przemysław
      Wg. mnie po prostu część instrukcji jest źle zapisana. Nie wiem jak to jest w samolotach itp., ale dosyć łatwo da się natrafić na instrukcje (jak to niedawno ktoś ładnie ujął) “pisane przez humanistów w taki sposób, że nie wiesz, czy czytasz instrukcję, czy rozprawke z j. polskiego z egzamiu gimnazjalisty” :/ Nie wszystkie są złe, ale często brakuje konkretów…

    • @Lubieerror, możliwe, że niektóre są źle opisane, ale mogę się założyć, że więcej wypadków, uszkodzeń, błędów, itp. jest spowodowanych nie źle napisaną instrukcją, a tym, że ktoś w ogóle jej nie przeczytał.

    • @Lubieerror: Nie,nie i jeszcze raz nie. Przypadki krytyczne które można i trzeba ograniczyć odrobiną kodu to nie jest materiał na żadną instrukcję.System chodzi dobę albo dłużej – co najmniej ostrzeżenie powinno wyskoczyć i tyle. Twierdzenie “a nie przeczytali instrukcji” czy coś w tym stylu jest żałosne.Warning to absolutne minimum,w skrajnych wypadkach wręcz przymusowe wyłączenie systemu celem resetu przez system powinno zostać przewidziane,tak samo jak skutki krytyczne używania niezgodnie z instrukcją powinny być chociaż przemyślane i jeśli koszt nie jest jakiś dramatyczny to można go ponieść. A ile kosztuje nawet taki wymuszony reset ? Ile to linii kodu trzeba by dodać ?

    • Wyobraźnia i przede wszystkim myślenie.
      To, że ktoś wymyślił światła drogowe aby POMAGAŁY w komunikacji to nie znaczy, że jeśli światło będzie czerwone (o 2 am), to będziesz sterczał na przejściu dla pieszych wyglądając jakieś autko którego nie ma!
      Przepraszam za temat, skojarzył mi się.
      W moim mieście światła drogowe te niby ‘inteligentne’ strasznie kuleją, śmiem twierdzić, że nie działają w ogóle inteligentnie (mechanizm przełącznika czasowego), a zamiast poprawy działania w pierwszej kolejności chcą uruchomić ‘karanie kierowców którzy przejadą na czerwonym świetle’ za pomocą istniejących tam kamer.

      Jak coś tworzyć to od początku do końca Z GŁOWĄ.

    • @Jaroski, no tak, bo instrukcję do samolotów czyta tylko i wyłącznie pilot samolotu. I to jeden tylko, bo po co dwóch ma czytać… Nie pogrążaj się takimi durnymi tekstami…

      @kez87 2015.05.04 18:39: Teraz (po akceptacji Twojego komentarza przez modów) rozumiem o co chodziło z tekstem w cudzysłowie :D Nie czytałem całego komentarza, tylko wyrywkowo, bo jest strasznie długi, a ja nie mam zbytnio ani czasu, ani chęci czytać opowiadania. Problem polega na tym, że odpowiedzialność programisty za użycie błędnych i niebezpiecznych funkcji spoczywa nadal na programiście, ale użytkowanie i stosowanie się do instrukcji jest wymogiem od użytkownika. Przykładem niech będą wybuchające telefony – producent odpowiada za to, że telefon wybuchł, a użytkownik za to, że pomimo ostrzeżenia o nie wodoodporności telefonu, pływał z nim w basenie. Są instrukcje i zalecenia i jeżeli było w niej, że ma być restart ręczny w ciągu np. 24h, to tak ma być. To nie jest widzi mi się.

    • Ja czytam każdą instrukcję. Ostatnio w kyszrach obsługiwaliśmy drony, wpierw po co sięgnąłem, to nie pilot, oj nie drodzy koledzy, lecz instrukcja! Śmiali się ze mnie. Do dyspozycji były 2 drony, z czego jednego byłem pilotem. Druga grupa już wystartowała, leciała 15 minut, ja jeszcze nawet nie odpaliłem silników ale wciąż czytałem instrukcję, tylko że fragment o lądowaniu… No i się stało. Po 30 minutach szykuję się do startu, załączam GPS, włączam zasilanie, a koledzy z przeciwnej drużyny już się szykują do lądowania i piszą sprawozdanie. Okazuje się, że dron na wysokości kilkuset metrów zaczał spadać, gwałtownie przyśpieszył, ale nie chciał ustabilizować lotu. Od razu usłyszałem krzyki, podbiegłem i się pytaje o co chodzi. Oni mówią: “On spada, spada , kur*a!”, a ja mówię: “kto spada, jakiś ptak? znów strzelaliście w niebo z taca40??”, co z kolei usłyszałem “Nie to nasz orzeł, dron noś ku**wa mać!”. Szybko sięgnałem po pilot i włączyłem funkcję powrotu do domu , i wylądował..

  3. ” błąd programistyczny pozbawiał samolot samolot zasilania” do poprawy.

  4. Jesteście bardzo nie precyzyjni w podaniu sprawy dla 787. Podstawowa kwestia to w samolotach są różne rodzaje zasilania: stałe i zmienne. Problem dotyczy zmiennego (AC) a nie stałego. To są różne i niezależne obwody.
    Kolejna sprawa to cytowanie bezmyślnych wypowiedzi dziennikarzy. Każdy kto zna się chociaż trochę na technice lotniczej i konstrukcji samolotów wie doskonale iż wypisują bzdury odnośnie “latającej cegły” – systemy sterowania będą miały ciągłość zasilania niezależnie od działania generatorów prądu. Nie należy zapominać iż jeszcze istnieje awaryjny system zasilania – turbina która w razie potrzeby jest wypuszczana na zewnątrz samolotu.

    Tak więc uprasza się niebezpiecznik o precyzję i dokładność dziennikarską a nie powielanie “bzdur”

    • PM: Artykuł w części dotyczącej 787 przedstawia 2 punkty widzenia — zarówno prasy — celowo z podaniem źródła, abyś mógł sobie sprawdzić który z zagranicznych tytułów mówił o katastrofie, a który o “cegle”, jak i punkt widzenia miłośników lotnictwa, który odejmuje dramatyzm z tej sytuacji, wspominając o akumulatorach i tzw. “szczurze” a dodatkowo stanowisko Boeinga. Gdzie widzisz tutaj nieprecyzyjność? Na lotnictwie się nie znamy — relacjonujemy więc materiały z jednej i drugiej strony opinii. Mam wrażenie, że nie doczytałeś do końca (piszesz bowiem o turbinie, która jest opisana w tekście) i od razu po zwrocie latająca cegła przeszedłeś do komentowania ;-)

    • Jak już mamy być tacy precyzyjni to AC to prąd PRZEMIENNY (który jest rodzajem prądu ZMIENNEGO), Panie Dokładny

    • @Greg, śmieszny jesteś. Jeżeli chodzi o DC, a AC, to jest bardzo duża różnica, którą należy w tekście zaznaczyć. Jeżeli natomiast mówimy o prądzie zmiennym i przemiennym, to tego pierwszego na co dzień nie używamy, więc nie wiem o co się czepiasz. Dodatkowo na prąd przemienny mówimy po prostu prąd zmienny, bo jest on prądem zmiennym okresowym. Reszta to prądy nieokresowe, tętniące lub stałe… Nie widzę tutaj żadnego błędu.

      @PK, brak zaznaczenia o jaki typ prądu chodzi jest bardzo dużym niedopowiedzeniem, bo oznacza, że w samolocie nie będzie w ogóle prądu, a to nie prawda. I nie “moc nie jest dostarczana”, bo moc pojawia się dopiero przy podłączeniu jakiegokolwiek odbiornika, generatory dostarczają prąd.

    • PM – Moje pytanie – jak wysunięcie i uruchomienie owej turbiny wpłynie na parametry lotu podczas startu bądź lądowania? Co jeśli awaria wystąpi w krytycznym dla lotu momencie wymagającej skupienia obydwu pilotów? Na przykład czy będą oni w stanie momentalnie odejść na drugi krąg gdy awaria wystąpi tuż przed przyziemieniem?

    • @s, zapominasz o akumulatorach. To nie są zabawki, w takich urządzeniach zawsze jest co najmniej kilka awaryjnych systemów…

    • Ja pierdziu…. po co ja studia kończyłem skoro tu tylu znawców, wystarczy posty czytać a człowiek na ich podstawie jest w stanie zbudować samolot …. jednak to prawda gdzie dwóch polaków tam trzy opinie

  5. Primo ultimo: testy jednostkowe na granicach przedziałów.

    • Ok. Zrobię i wyniki wpiszę w instrukcję. Nikt nie zakłada, że mobilny zestaw plot. będzie stacjonował w jednym miejscu przez 100 dni, albo że samolot będzie w ruchu przez ponad 250 dni.

    • Koziołek – nie 100 dni, a 100 godzin. A to już jest jak najbardziej realne.

    • @s, tak czy siak nie zmienia to faktu, że instrukcja jest po to, by ją przeczytać, zrozumieć i się do niej stosować. Pomijam fakt tego, że nawet ta pierwsza czynność z tych trzech nie jest robiona…

    • @Koziołek – takie zakładanie jest trudne,ale właśnie zakładanie “niemożliwego” różni dobrego testera (nie mylić z prostymi testerami od przeklikania test-caseów co nie programują) i bug-huntera od przeciętnego programisty.

    • @kez87, co innego testować niemożliwe przypadki ataków i/lub działania aplikacji, która dostępna jest dla milionów (webaplikacja), a co innego tworzenie konkretnej rzeczy dla konkretnych osób od których wymaga się konkretnej wiedzy i zachowania. Nikt nie daje żołnierzom broni i mówi “aaa, w instrukcji jest, że ten karabin zacina się w wodzie, ale my przetestowaliśmy i zacina się tylko raz na sto razy”, bo jeżeli w instrukcji jest, że w wodzie nie używać, to nie używać. To nie przeciętny człowiek, żeby zakładać, że będzie robił wszystko to czego nie przewiduje instrukcja…

    • @kez87, tylko że tester (QA) wykryje takie coś. Później trafi to do instrukcji użytkowania i nikt, ani programista, ani ten tester nie mają wpływu na to co zrobi użytkownik. Możesz być najlepszym testerem na świecie. Twój wpływ na działania użytkownika jest ujmójąc rzecz w okrągłe słowa ZEROWY.

  6. No i co teraz? Zawsze przed rozpoczeciem pracy wylaczaj urzadzenia elektryczne (wszystko) na 1-2 minuty. Inaczej moga Cie zabic bez restartu.

  7. Po co ktoś podaje tytuł naukowy rejestrując się na siłowni?

    • W tym samym celu jak podpisanie się na poczcie mgr Imię Nazwisko. Samodowartościowanie.

    • Może formularz wymagał? Często jest dropdown list, Pan/Pani/Dr/etc. na “zachodnich” serwisach.

    • Jak to po co? Żeby mieć bazę vipów :)

    • I dlatego, że ma do tego prawo, jak i dlatego, że formularz na to pozwalał :P

    • Dla przykładu w Niemczech nawet na kacie bankomatowej napiszą Ci Dr mgr inż. Tytuł naukowy staje się tam integralną i wymaganą częścią Twojego imienia i nazwiska.

  8. Bardzo ciekawym przypadkiem była awaria akceleratora do radioterapii który w wyniku “race condition” powodował przepełnienie 1-bajtowej zmiennej, a ta z kolei dopuszczała wielokrotny wzrost mocy dawki promieniowania.

    http://en.wikipedia.org/wiki/Therac-25

  9. Programista musi dawać sobie pozwolenie na popełnianie błędów, inaczej wykończy się psychicznie. Nikt nie przewidzi wszystkiego, inaczej nie byłoby bugfixów.

    Tam, gdzie błąd może kosztować ludzkie życie, powinny być (i są) stosowane metody minimalizowania skutków błędów. Trzeba wychodzić z założenia, że w sofcie będą błędy. Bo zawsze jakieś będą. I trzeba uczyć się na błędach innych, czytać, co zawiodło, gdzie były błędy, zastanawiać się, czy w naszym kodzie nie ma takich samych błędów. Potem oczywiście code review i solidne testy.

    Poza tym idea KISS sprawdza się tutaj lepiej niż gdziekolwiek indziej. Im coś prostsze, tym mniej zawodne. Tak to po prostu działa.

    Osobna sprawa to poleganie na jednej osobie. Sytuacja, w której błąd jednego konkretnego programisty skutkuje czyjąś śmiercią, jest zła. Sytuacja, w której życie ludzkie zależy od jednego centralnego komputera, też jest zła. Failsafe musi być ideą przyświecającą projektowaniu całego systemu od samego początku.

    • Dokladnie o to poszlo w wypadku z maszyną do radioterapii – w sofcie były błędy ale starsza generacja miała mechaniczne zabezpieczenia przed niepoprawna konfiguracja. W nowszej uznano ze software interlock to wystarczajace zabezpieczenie i…skonczylo sie jak sie skonczylo

  10. Dla ciekawych:

    i=0
    while (i!=1){
    i+=0.1;
    }

    Ile razy wykona sie petla? :)

    • Amator powie, że 10, specjalista, że nieskończoną, bo floaty nigdy nie są równe, praktyk – że nieskończonej nie da rady WYKONAĆ (bo to czas dokonany), po prostu nigdy się nie skończy, cwaniak też powie, że się nie zakończy, bo i to zwykle int i będzie ciągle równe zero, a profesjonalista zapyta, w jakim języku – jeżeli w nakładce na asemblera (typu C czy PHP), to pętla się prawdopodobnie nie zakończy przed bardzo dużą liczbą przebiegów (bo kiedyś to i te floaty mają szanse być równe), ale jeżeli w jakimś języku wyższego poziomu, niepodatnym na tego typu zaokrąglenia floatów (na przykład przy zadeklarowaniu i jako zmiennej stałoprzecinkowej z jednym miejscem dziesiętnym), to równie dobrze i 10 razy wystarczy. A jaką odpowiedź znałeś sam?

    • Ani razu.

    • Jeżeli to float to jest ciekawie.
      :) jeżeli już raz było + 1/2 to potem do jedynki następnej połówki zabraknie

    • Po prostu, kiedy pierwszy bit n/2 został już wykorzystany, to właściwie od tej pory praktycznie nie ma następnego aby trafić w jedynkę samą reprezentacją binarną bitów dzielących wartość n/(b^n].
      Właściwie to W OGÓLE nie da się zrobić jedynki wyłącznie z “półbitów” – no bo nie da się nawet dodać do siebie po przecinku dwóch połówek (jest tylko jedna).

      Jedyna możliwość trafienia w jedynkę to zaoperowanie na pierwszej połowie reprezentacji binarnej tego typu w której są te liczby całkowite i wygaszenie wszystkich bitów dzielących jedynkę.

      Cholera, właściwie to nawet kompilator nie ma szans się nie tyle domyślić, że chcemy przechodzić przez niektóre liczby całkowite (wymagające dodawania np takich samych wartości do siebie w pewnych okresach) no bo dałoby się to rozwiązać na poziomie kompilatora ale bardzo często się zakłada, że jeżeli ktoś operuje na bitach dzielących jedynkę DODANYCH do wartości całkowitej (która fakt faktem też w reprezentacji typu jest jako pierwsza połowa ciągu) – no to ktoś z założenia “CHCE ROBIC TO CELOWO” :)

      Tis not a Bug … tis is fearure

    • Kod jest oczywiście w assemblerze i tak go należy widzieć pisząc w jakimkolwiek języku a zwłaszcza w C.
      Pętla wykona się oczywiście nieskończoną ilość razy a następnie albo się wysypie albo nie da się dodać do niej żadnego bitu więcej (zależne od kompilatora).

      W momencie kiedy decydujemy się na dodanie do wartości czegokolwiek po przecinku w wypadku nieprzewidywalnej pętli lub po prostu pętli w której celowo nie deklarujemy końca, to kompilator poprawnie decyduje (w wypadku C zwłaszcza) o użyciu wyłącznie REPREZENTACJI dziesiętnej – no bo użyliśmy JAKIEJŚ pętli warunkowej która “coś robi”.

      Kompilator myśli, że robi to dlatego bo “coś w pętli” zostało zrobione celowo przez programistę i nie należy ingerować w pomysł programisty operowania na samej reprezentacji dziesiętnej – mimo, że sam kompilator jest w sanie przewidzieć te wartości zmiennych z góry nawet w takim wypadku (mądre ostatnio cholery).

      Problem z reprezentacją dziesiętną jest taki, że operując krokowo wyłącznie na niej NIE MOŻEMY DODAĆ DO SIEBIE wartości po przecinku które opierają się na zapalonych pojedynczych TYCH SAMYCH bitach.
      Np nie jest możliwe dodanie to siebie 0,5 i 0,5, no bo nie jest możliwe zapalenie dwukrotnie tego samego bitu.
      Nie możemy też dodać do siebie 0.5 + (0.25 + 0.25) no bo również nie możemy zapalić dwukrotnie drugiego bitu :) czyli 1/4.

      Operując na reprezentacji dziesiętnej można osiągnąć 0,5 ale nie można już do tego 0,5 dodać drugiej takiej samej wartości BEZ konwertowania 0,5*2 na reprezentację całkowitą którą powinien w innym wypadku wdrożyć sam kompilator.
      Co najwyżej kompilator widząc “celowy zamiar” może wygenerować rozwiązanie które w konkretnym wypadku / warunku / momencie wykonania operacji zamieni takie wyrażenie na liczbę dziesiętną (kompilatory są “świadome” dodawania floatów)

      Przykładowo:
      a=0,5;
      b=0,5;
      c=a+b;
      c=? oczywiście, że 1!!
      ale w tym konkretnym wypadku kompilator WIE, że chcemy operować na liczbach i wartościach przewidywalnych z gór a nie IO, nie na połowie typu i nie tworzyć pętlę której celem jest operowanie wyłącznie na reprezentacji dzielenia jedynki przez bity dziesiętne.

      Normalka, że w wypadku nieprzewidywalnych wartości np z IO albo niektórych pętli o niezadeklarowanej z góry długości kompilator zakłada, że chcemy celowo operować tylko na dzieleniu jedynki :).. tak właśnie POWINNO BYĆ.

    • Jeszcze sprostuję sam siebie: tzn da się dodać np 1/4 ( 2 * drugi bit) + 1/4 bo da to wynik 1/2 (pierwszy bit).
      Chodzi o to, że zapalony pierwszy bit zaraz po przecinku czyli 1/2 i próba dodania do niego 1/2 jest dla reprezentacji dziesiętnej po prostu nieskończonością.
      Dodanie 0.5+0.5 czyli próba osiągnięcia jedynki na samej reprezentacji dziesiętnej jest po prostu próbą zapalenia wszystkich bitów!!
      Następnym wynikiem po dodaniu czegokolwiek do reprezentacji dziesiętnej nigdy nie jest jedynka, tylko jedynka + reszta zapalonych bitów :)

      No a kompilator ma na uwadze tylko dodawanie na reprezentacjach dziesiętnych, bo programista wyraźnie zaznaczył, że ten fragment kodu ma charakter nieprzewidywalny z góry lub celowy.

    • @mxmm – bzdety jakieś opowiadasz, jakie znowu ‘zapalanie dwukrotnie tego samego bitu’? Chcesz dodać 0.5 do 0.5? Proszę:

      http://www.h-schmidt.net/FloatConverter/IEEE754.html

      00111111000000000000000000000000+
      00111111000000000000000000000000=
      00111111100000000000000000000000

      Bez utraty precyzji. Zupełnie nie rozumiesz, skąd się bierze problem floatów. Otóż 0.1+0.1=0.2:

      00111101110011001100110011001101+
      00111101110011001100110011001101=
      00111110010011001100110011001101?

      Zobacz wartość mantysy oraz co się dzieje w double precision. Jeżeli jeszcze nie kumasz: da się bezproblemowo operować na ułamkach binarnych – dokładnie takich, jakie sam zaproponowaleś jako przykład (0.5=1/2); nie da się natomiast operować na ułamkach dziesiętnych, które nie rozwijają się w skończony (na długości słowa, którym operujemy) szereg potęgowy liczby 2. Dlatego np. 0.03125 – jako liczba okrągła (1/32), albo 0.015625 (1/64) czy 0.125 (1/8), jako ułamek okrągły (binarnie) nie powoduje strat w precyzji.

      Na co się to przekłada w praktyce? Zmień w zaprezentowanym przykładzie krok z 0.1 (ułamek binarny nieskończony) na 0.1015625, a warunek z 1 na 13. I nawet nie zapinaj pasów, bo jazda będzie krótka – ledwie 128 przebiegów. I co, da się porównywać floaty? Jak najbardziej! Tyle tylko, że muszą być sobie równe, tymczasem w dodawaniu 0.1+0.1 kryje się – w ujęciu matematycznym, round(0.1(b),23)+round(0.1(b),23), a to mogłoby być równe round(0.2(b),23) tylko wówczas, gdyby nie było czego zaokrąglać.

    • @gotar Nie działa i nie ma prawa działać w tym konkretnym przykładzie!

      W tym konkretnym wypadku decyzją kompilatora jest nie ingerować w zamiar użytkownika – mówiący NIE DZIAŁAJ i nie konwertuj przed wykonaniem kroku na liczby całkowite! albo NIC NIE RÓB OD SIEBIE przed zmianą reprezentacji dziesiętnej.

      Wyraźnie użytkownik zaznaczył, że pętla ma charakter “nieprzewidywalny z góry” a pierwszą operacją w kolejności jest operacja na samym floacie!

      Kompilator robi w tym konkretnym wypadku celowo i programista *MUSI* dosłownie o tym wiedzieć oraz WIDZIEĆ podczas pisania co się dzieje na poziomie maszyny pod podszewką upraszczacza typu C.

      Chodzi o to że użytkownik SAMODZIELNIE wyznaczył metodę aby wartości nie były przewidywalne z góry – coś na zasadzie wejścia z IO.

      Kompilator nigdy nie zrobi jedynki w tym konkretnym wypadku bo nie tylko część dziesiętna jest pierwsza w kolejce przed kolejnym skokiem ale znaczenie ma też ROZKŁAD instrukcji – no bo mają charakter nieprzewidywalny i trzeba je rozłożyć inaczej aby po prostu nie zaciąć pipelinów.

      Tu trzeba w ogóle zacząć od wyznaczenia METODY wykonania tej pętli, która dosłownie mówi: nie ingeruj w precyzję, reprezentacja dziesiętna w pierwszym kroku, co wejdzie nawet po IO tak ma być na surowo.

    • @gotar a btw… oczywiście w wypadku operacji przewidywalnych (nawet jeżeli wejścia mają miejsce z IO przed wykonaniem pętli), kompilator zacznie stawiać w pierwszej kolejności na analize, czy dane dodawanie dziesiętnych ma być wykonane jako pierwsze i czy podnieść całkowitą po drodze – to wtedy jest dokładnie tak jak Napisałeś + dochodzi jeszcze ta normalizacja i tak dalej.
      Natomiast w tym konkretnym wypadku kolejność iteracji CELOWO ulega zmianie a wyrażenie ma charakter na surowo / dziesiętne pierwsze w kolejności.

      Właśnie dlatego ten moment 0,5 + 0,5 nigdy nie będzie równy 1 idąc liczbami innymi niż 0,5 (a w tym wypadku też prawdopodobnie to się nie uda – nie wiem).

    • @gotar
      A w wypadku operacji PRZEWIDYWALNEJ przez FOR z góry poszło:
      For – i: 0.100000
      For – i: 0.200000
      For – i: 0.300000
      For – i: 0.400000
      For – i: 0.500000
      For – i: 0.600000
      For – i: 0.700000
      For – i: 0.800000
      For – i: 0.900000
      For – i: 1.000000
      For – i: 1.100000
      For – i: 1.200000
      For – i: 1.300000
      For – i: 1.400000
      For – i: 1.500000
      For – i: 1.600000
      For – i: 1.700000
      For – i: 1.800000
      For – i: 1.900000
      For – i: 2.000000

      Tylko, że kolejność działań na OBU reprezentacjach została już wykonana przez kompilator.
      :)
      Jeszcze raz: mi chodzi głównie o to i w pierwszej kolejności, że sam użytkownik ŚWIADOMIE i CELOWO zmienił kolejność działań na rodzaj IO + zmienił rozkład instrukcji do wykonania przez procesor (sheduling) na rodzaj NIEPRZEWIDYWALNY.

      Natomiast tak jak napisałeś to prawda.. kompilator daje radę w wypadku przewidywalnych operacji i zwłaszcza przy podwójnej precyzji.

    • @gotar
      a btw ^ ten for był sterowany counterem na int cie – po prostu od 1 do 20.
      ale nawet gdyby wstawić w środku scanfa to i tak kolejność działań przy przewtwarzaniu reprezentacji całkowitej i dziesiętnej dla floata byłaby przewidywalna.

      w wypadku while kompilator już widzi nieprzewidywalny (algorytm) i zamiar operowania w inny sposób – też zależy w którym miejscu to i+= zostanie umieszczone!!!

    • @gotar
      while (i!=1){ //= 20) break; // <— odkomentuj a wygrasz 1nke w totka i poprawna precyzje
      }

      ;) hehe proszę
      btw objdump całkiem ciekawy

    • @gotar
      przepraszam coś nie wyszło.. daję tutaj:
      http://wklej.org/id/1703705/

      Objdump jest całkiem przewidywalny :)

    • @gotar
      Nie wiedząc czemu tak się dzieje, to ktoś nie powinien w ogóle podchodzić do programowania no i o tym chyba wiemy.
      Prawda jest taka że mechanizmy precyzji i mechanizmy przetwarzania przewidywalnych wartości to jedno ale fundamentem jest odczytanie ZAMIARU tego co chce zrobić programista przez kompilator.
      W tym konkretnym przykładzie powyżej to jest konkretne użycie FEATURE mówiące że programista dosłownie NIE CHCE nigdy uzyskać jedynki.

      Kupa małp potrafi klepać abstrakcje ale jeżeli ktoś nie wie PO CO te wyrażenia w C mają taką formę jaką mają i w jaki sposób to działa na wszystkich warstwach to … kończy się właśnie stadem małp klepiących banany.

    • tamto się popsuło :P

      http://wklej.org/id/1704182/

    • czemu to działa?

      http://wklej.org/id/1704264/

    • @planet
      Pierwszy BLOK tzn jako całkowity blok instrukcji: jest rodzajem nieprzewidywalnej pętli, w której w pierwszej kolejności programista kazał operować na dziesiętnych częściach alokacji zmiennej, wymuszając tez po tym test w następnej kolejności czy nie zmieniła się całkowita (kolejność działań).
      Powstaje konkretny MakroOP (a nawet kilka ich wersji i kilka floatów) skierowany na działanie jako algorytm IO z zachowaniem prawie wszystkich warunków (tyle, że warunków na końcu pętli w tym wypadku).

      Po odkomentowaniu warunku ograniczającego działanie pętli tylko do przewidywalnej wartości / ilości iteracji, cała jej zawartość też robi się przewidywalna lub częściowo przewidywalna. Wtedy zarówno kompilator jak i procesor zakłada, że chcemy skorzystać z pełnej możliwości zrobienia makra o charakterze jak najbardziej wektorowym aby wykonać całe makro jak najszybciej na pipelinach ( a nie tylko pojedyncze instrukcje ).
      Dodatkowo stara się traktować w tego RODZAJU pętli floata jako liczbę a nie jako konkretną operację!! no bo zakłada, że chodzi o “taki rozkład”.

      Właściwie po odkomentowaniu warunku makro końcowe do wykonania na pipelinach W OGÓLE nie musi zawierać warunku sprawdzającego wartość countera bo ilość wykonań jest z góry ustalona + że sheduler i inne układy mają do dyspozycji właściwie setki rejestrów i to nie tylko w cache.
      Natomiast kompilator zaczyna wtedy używać typowego feature dla rozkładu operacyjnego i stara się też traktować “i” jako “liczbę” + że sam procesor też inaczej potraktuje taki “Blok” kodu do rozłożenia.

      Też w pierwszym wypadku nie do końca wiadomo ile cykli będą potrzebowały przepływające przez potoki makra w trakcie zarządzania pipelinami. Pętla od 1 do 20 może się wykonać w 2,6,10,20 a nawet 20*16 krokach (jeżeli z jakiegoś powodu nastąpi zacięcie – w dzisiejszych czasach prawie niemożliwe).

      W drugim wypadku cały while powinien przelecieć w jednym lub kilku cyklach zegara i wyjść z pipelinów od razu z wynikiem (zależy ile ich i jaka metoda rozkładu) – tyle, że nie wiadomo ile rejestrów użyje i jak zawali cache (czyli jak mocno rozpłaszczy pętlę i zawarte w niej rozpoznane np ROP-y).

      Jeszcze inna sprawa, że jeżeli kompilator oznaczył odpowiednio wycinek kodu do zrobienia makra podczas jego dalszej kompilacji przez sam procesor, to nawet nie wiadomo w jaki sposób niskopoziomowo wykona się ten float – tutaj liczy się wynik jeżeli chcemy wypłaszczać na wektor a nie jak to sam procesor przerobi.
      On równie dobrze w serii MOP-ów które w ogóle nie posiadają żadnego warunku tylko dziesiątki przypiętych w pionie rejestrów + również w pionie ALU ( z sąsiedniego bloku )
      Właśnie dlatego oni dzisiaj często dzielą potoki na dwa kierunki: tak, że w razie operacji związanych z algorytmami IO i innymi “koniecznie tak jak użytkownik kazał” alu sobie pracuje prawie normalnie obok przypinając się sporadycznie, ale w razie czego i w razie pełnego rozkładu na całkowicie przewidywalne operacje CPU zamienia się w GPU :) jeżeli da radę daną odnogę gałęzi albo pętle rozpłaszczyć.

      Natomiast nawet jeżeli procesor potrafi to i tak kompilator może zadecydować że “wymusi” rozkład po swojemu informując o tym sheduler (metaznacznikami) i rozumiejąc niskopoziomowy rozkład samego procesora.

      Po odkomentowaniu warunku cała pętla while staje się “kernelem OpenCL” (w przenośni) do wykonania na SIMD-zie z minimalną ilością sprawdzeń warunkowych na pipelinach i często bez instrukcji warunkowych zależnych po sobie.

      Można zrobić 200 takich przewidywalnych pętli i sprawdzać czy któraś z nich na coś nie trafiła dopiero później. Tak samo można uruchomić kernel na OpenCL-u o ile samodzielnie zrobi się rozkład tego co się chciało napisać..
      GPU wypadnie szybciej ale… nie o to chodzi ;)

    • @maxmm …zamiast tych bredni może byś sobie po prostu sprawdził? Bo ja nie za bardzo nawet jestem w stanie się do tego odnieść, prezentujesz jakieś paranauki nie-stosowane! Jakie znowu decyzje kompilatora, cóż takiego on niby robi?! Nieprzewidywalne instrukcje, IO, scheduling, zatkane pipe’y? Nie umiesz wyłączyć optymalizacji i przeczytać sobie disasma?! Bzdury, bzdury i raz jeszcze bzdury…

      “Właśnie dlatego ten moment 0,5 + 0,5 nigdy nie będzie równy 1 idąc liczbami innymi niż 0,5 (a w tym wypadku też prawdopodobnie to się nie uda – nie wiem).”

      No to zmieńże sobie we własnym kodzie numerki i patrzaj:

      While – i: 0.125000
      While – i: 0.250000
      While – i: 0.375000
      While – i: 0.500000
      While – i: 0.625000
      While – i: 0.750000
      While – i: 0.875000
      While – i: 1.000000

      jakoś magicznie pętla się przerwała na warunku float==1 bez odkomentywania “magicznej” najwyraźniej dla ciebie linijki. Objdumpa to ty chyba po dobranocce widziałeś, w okolicach wchodzenia emacsem przez sendmaila.

      Tutaj masz proszę, wersję dla humanistów:

      http://wklej.org/id/1704500/

      ~: gcc -O0 -gdwarf-3 floats.c -o floats && time ./floats
      ./floats 1.08s user 0.00s system 98% cpu 1.093 total
      ~: gcc -O3 -gdwarf-3 floats.c -o floats && time ./floats
      ./floats 0.39s user 0.00s system 98% cpu 0.398 total

      – nie trzeba czytać asemblera, wystarczy chwilę pomyśleć, że jednak żadnej wysokiej magii kompilatora tutaj nie uświadczysz; przez te parę chwil procesor jednak COŚ robi, a później grzecznie kończy pracę. Nadal nie widzisz, że pętle na floatach kończą się same? No to zastanów się, dlaczego w celu wydłużenia czasu wykonania dałem wewnętrzną pętlę, zamiast warunek zmienić np. na 1300000.

      Tutaj masz wersję, na której możesz się nauczyć obsługi kompilatora oraz debugera: http://wklej.org/id/1704502/

      ~: gcc -gdwarf-3 floats.c -o floats && gdb ./floats
      (gdb) disassemble /m main

      http://wklej.org/id/1704505/?hl=d-objdump

      Mogę się jedynie domyślać, że z tym “featurem” kompilatora to chciałeś powiedzieć o zwinięciu tego rodzaju pętli:

      ~: gcc -O1 -gdwarf-3 floats.c -o floats && gdb ./floats
      (gdb) disassemble /m main

      http://wklej.org/id/1704506/

      a jedynie pomyliłeś, jaki “zamiar” kompilator wykrywa i na czym polega optymalizacja (bo na pewno nie odgadnięcie intencji “że programista dosłownie NIE CHCE nigdy uzyskać jedynki”).

      Podsumowując: przykład, który podajesz od samego początku, tj. sumowanie wartości 0.5, zachowuje bardzo długo precyzję i absolutnie zawsze uda się porównanie takiej sumy do 1 – jeżeli nie będzie to jasne już na etapie kompilacji (trywialne pętle), to na etapie wykonania nic się nie zmieni (ot, będzie użyty FPU). Taki numer nie uda się z wartością 0.1, gdyż jest to ułamek binarny nieskończony, więc utrata precyzji ma miejsce już w momencie kompilacji. Cała magia odkryta.

    • @gotar podstawy, przepraszam:)
      Nie pomyślałem, że faktycznie precyzja 0,1 już zostaje popsuta w momencie kompilacji a wynik faktycznie jest ten sam.
      Natomiast nie wiem jakie pętle na floatach kończą się same bo miałem na myśli REALNIE działająca pętle w postaci fizycznie wykonywanych przez procesor mikro opów – oraz w JAKI SPOSÓB ona zostaje wykonana – czyli jej FIZYCZNĄ reprezentację jako działań następujących w rurach po sobie typowych dla architektury superskalarnej.

      Ta pętla jest wykonywana prawdopodobnie na większości architektur w taki sposób, że zwinięty i przewidywalny blok zostaje prawie natychmiast rozwinięty na prawie całkowicie “wektorowe” tetrisy – i o to chodzi w pierwszej kolejności – absolutne podstawy architektury superskalarnej które trzeba widzieć równolegle z pracując na debugerze. – czyli zacznijmy od tego jakie są realne zasady wykonywania tej pętli bo poza tym procesor nic nie robi i na pewno procesor nie wykonuje instrukcji generowanych przez kompilator bez wcześniejszego stworzeniach ich reprezentacji na mikro opach.
      I otóż to nie bo w dzisiejszych czasach nie pojedyńcze instrukcje sa rozkładane na szerokość rur w pionie tylko CAŁA PĘTLA zostaje rozłożona jako jeden MOP – czego kolega z jakiegoś powodu nie sprawdził.

      Nie chodzi o to, że reprezentacja floata a nie float zachowuje precyzję przez jakiś czas no bo jej nie zachowywuje, tylko o ilość miejsc po przecinku które nie bez powodu wyświetla a raczej obcina printf i o to, że zoptymalizowany float JEST przechowywany przez sheduler w momencie NADANIA floatowi wartości.
      printf tych miejsce NIE OBCINA, kompilator wie, że sięga po reprezentacje floata z shedulera.
      Ten float w pamięci RAM jest taki jaki jest i jest przechowywany niedokładnie ale razem z nim obok znajduje się już przygotowana jego reprezentacja ZANIM printf zostanie wykonany.

      KAŻDA WARTOŚĆ W ARCHITEKTURZE SUPERSKALARNEJ POSIADA SWOJĄ ODLICZONĄ REPREZENTACJĘ przechowywaną obok, często nawet jeżeli ta reprezentacja nie zostanie nigdy użyta – o ile zwinięta pętla jest dla procesora przewidywalna.
      Nie dzieje się tak z powodu łatwości “podstawiania” tylko z powodu konieczności rozłożenia programu do jego super-skalarnego wykonania równolegle – i tak PROGRAMU a nie tylko pojedyńczych instrukcji.

      Mało tego jak włączyć debuger procesora to od razu można zobaczyć, że w schedulator w wypadku przewidywalnej pętli zrobił sobie nawet kilka kopi tych floatów i jeszcze jakichś dodatkowych wartości + tak samo kilka ich reprezentacji i zrobił RÓŻNĄ ilość operacji ALU.
      Druga sprawa którą zauważyłem dopiero dzisiaj, że GCC jakimś cudem wykrywa poprawnie albo z góry założył i oznaczył tą pętle jako przewidywalną (nawet bez wychodzenia przez while).

      Spójność między rozkładem na mikro opy a makro assembler dalej dla programisty ma miejsce no bo dalej działanie kodu musi być identyczne i przewidywalne na górnej warstwie co do bitu.
      Natomiast rozwiń tą pętle i daj znać kompilatorowi że “stop” jest niestwierdzalny (z -O0 – pozostawiając tyko znaczniki dla schedulera) i włącz debuger cpu a w ogóle nie połapiesz się co to za klocki lego usiadły między rurami a nawet na ilu rurach się wykonują jako nieprzewidywalna pętla w danym momencie.
      Jeszcze wywal NOP na końcu skoku a wtedy dopiero wypłynie jak wygląda zacięcie i już W OGÓLE żadnego rozkładu na MOP-y nie będzie.

      Oczywiście, że procesor w wypadku przewidywalnej pętli zadziała inaczej a w wypadku pętli nieskończonej zadziała dosłownie inaczej przy czym wynik ma być logicznie ten sam. Oczywiście, że wynik POWINIEN być ten sam ale wykonany zostanie w inny sposób i w zależności od danego stanu rozkładu będzie mniej lub bardziej czytelny podczas debugowania samego CPU i zostanie w RÓŻNYCH warunkach wykonany w RÓŻNYM czasie oraz zajmie RÓŻNĄ ilość rejestrów wewnętrznych i stworzy RÓŻNĄ ilość kopii tego floata.

      Oczywiście, że gapiąc się w makro assembler w wypadku tej prostej pętli wynik będzie dokładnie taki sam dla programisty a czas wykonania będzie prawie niemierzalny ale PROGRAM NIE zostanie wykonany w taki sam sposób a po drodze sam programista nie będzie świadomy jakie wartości są “sprzętowo” podstawiane w reakcji nawet na proste “ucinanie” bitów w konkretnych sekwencjach instrukcji!!! i dlaczego print wyświetlił floata z taką ilością zer i z taką precyzją.

      Już sam procesor nie może tylko MUSI działać mechanizmami konwersji floata na jego reprezentacje ze względu na naturę rozkładu makrokodu na mikroopy a nie tylko dlatego żeby ktoś sobie mógł łatwiej np czarować inta z floata albo robić sobie printf (“%f”); bez określania precyzji.

      Znaczenie ma JAK to działa o czym piszemy chociaż wynik MUSI pozostać wysokopoziomowo praktycznie ten sam a przy szybkiej konwersji na reprezentacje zera zostają ucięte dokładnie w miejscu gdzie REPREZENTACJA floata w pamięci schedulatora posiada określoną precyzję. mało tego w tym konkretnym przypadku to z góry alokowane są w tej pętli DWA FLOATY i dwie reprezentacje! – z natury działania schedulatora.

      Jeszcze raz: nie chodzi o to co się dzieje z floatem – chodzi o to co się fizycznie dzieje w procesorze z bitami którymi jest ten float i operacją którą jest co najmniej kilka przejść tej pętli przez potok – i w związku z czym DLACZEGO printf ucina precyzję, której “realnie” nie ucina tylko sięga po jej reprezentację.

      Chodzi w skrócie o to na ile ma miejsce współpraca samego kompilatora z problemem FIZYCZNEGO wykonywania pętli przez sam procesor – a z tym w JAKI SPOSÓB printf sięga po tą wartość która i tak już istniała ZANIM w ogóle PC wskoczył na instrukcje która zrobiła odczyt tej wartości!!

      Jeżeli chodzi o zawinięcie pętli do jej odwinięcia przez procesor – Oczywiście, że w jednym i drugim wypadku kod będzie działać przewidywalnie dokładnie tak samo pod kątem wynikowym, ale będzie działać totalnie inaczej fizycznie i wykona się w innej ilości cykli w zależności od metody rozkładu na mikro-opy i wygeneruje mniej lub więcej zacięć w sytuacjach w których się znajdzie.

      Można filozofować w nieskończoność na temat koncepcji C, ale naprawdę najprościej jest po prostu właczyć debuger CPU z GDB obok i zwolnić ten jeden rdzeń na samplowanie.
      Naprawdę proponuję zobaczyć na własne oczy ILE floatów na raz zostało zaalokowanych, ile reprezentacji tych floatów zostało stworzonych w cache już z góry w momencie “i+=0;”
      Też JAK wygląda wygenerowana PĘTLA na skutek POPRAWNEGO oznaczenia skończonej pętli przez kompilator i jak wygląda kiedy koniec pętli nie zostanie określony.
      btw w wypadku tak małej pętelki to akurat nic nie zmienia, ale w wypadku setek takich pętli na różnej głebokości gałęzi, jezeli kompilator stwierdzi, że są to pętle nieskończone to… efekt będzie drastycznie widoczny.

      Aha i kompilator NIE MOŻE nieoptymalizować kodu w 100%, bo wyłączenie oznaczania końca pętli i informowanie LICZNIKA GAŁĘZI dla branch predictora spowodowałoby zacięcie nawet tej prostej pętli!!!
      A spowodowałoby zacięcie dlatego, że rozkładane na potoki nie są pojedyńcze instrukcje tylko jw ^ CAŁA PĘTLA!!

    • @gotar
      tylko się poprawie:
      “Natomiast rozwiń tą pętle i daj znać kompilatorowi że “stop” jest niestwierdzalny” – dopisać poprzez -O0 i usunięcie NOP-a po skoku warunkowym na końcu pętli

    • @gotar btw .. poprawka ..i+=1..
      Ok faktycznie wykonuje się wysokopoziomowo tak samo.

      Chodzi o podstawową znajomość architektury x86_64 – w dzisiejszym wydaniu.
      W przeszłości mogło nie mieć znaczenia czy kompilator poprawnie rozpozna rodzaj pętli skończonej czy nieskończonej a procesor rozkładał TYLKO instrukcje na poszczególne przebiegi rur wykonawczych.
      Obecnie ma to znaczenie bo rozkładane na mikro-opy są CAŁE GAŁĘZIE I PĘTLE a razem z nimi powstaje wiele DOSTĘPNYCH dla użytkownika kopii …. np floata.
      printf w tym wypadku ciągnie za już istniejącą wartość w cache. – sprawdziłem :) i właśnie czytam samego printf-a.

    • @gotar
      btw dzisiaj jak patrzyłem to pierwsze co mnie zdziwiło, to że w momencie i+=1; uruchamia się linia do simdów i do cache.
      Olśniło mnie w momencie zrobienia cast-a do inta z tego floata po printfie bo odwołał się do simd-pionów łącznie przy pierwszym przejściu trzy razy jak dodałem:
      fromfloat = (int) i;
      40069e: f3 0f 10 45 e0 movss -0x20(%rbp),%xmm0
      4006a3: f3 0f 2c c0 cvttss2si %xmm0,%eax
      4006a7: 89 45 e4 mov %eax,-0x1c(%rbp)

      no w skrócie i cvttss2si odwołuje się do już rozpakowanej w cache wartości.. która powstała w momencie deklaracji i+= czyli typowo dla rozkładu na makra, ale po co alokuje jeszcze jakieś ciągi o długości dłuższej niż float w kilku kopiach to nie wiem i sam call do printfa raczej nie jest z tym związany.

      :) serio ciekawe.

    • @gotar Ok. uważnie się wczytałem i popatrzyłem w debuger cykl po cyklu na zablokowanym rdzeniu i maksymalna precyzją samplera.

      Powiem tak: jeżeli ktoś przeczytał uważnie jak wygląda wygenerowany wysokopoziomowy kod przez GCC i niezauważył, że:
      – gcc IDEALNIE rozłożył poszczególne operacje z C na prawie POJEDYŃCZE cykle zegarowe.
      – że gcc WIE, że w takim wypadku użycie portu IO do ustawienia “zmiennej” zostanie zakolejkowane w cache

      i jednocześnie jeszcze ten ktoś wie JAK działa super-skalar czyli ma wiedzę na poziomie pdostawowym a niezauważy jednocześnie SILNEJ optymalizacji nawet z -O0, to jest idiotą który nie tyle nie powinien dostawać pensji, co za pozerstwo dawno wylądować w więzieniu.

      Mało tego rozkład tej PRZEWIDYWALNEJ pętli (imho bez testu w środku gcc też ją rozpoznaje jako przewidywalną) jest tak robiony aby nie przekroczyć szerokości pojedynczej operacji.
      To nie zmienia faktu, że wyrażenie jako pętla jest przez to GCC u mnie akurat notorycznie oznaczany jako przewidywalne no i wynik prawdopodobnie faktycznie byłby taki sam.

      Ta pętla jest wykonywana w kilku cyklach zegara a sama deklaracja i=0; …. i+=, momentalnie idalnie od razu zaznacza gotowość 4 rech rejestrów na potzreby rozkładu samej pętli.

      Ten kod jest przy -O0 DOSKONALE dopasowany so superrury i tyle. Jeżeli ktoś tego nie widzi to jest kaleką.

    • @mxmm – tracę powoli nadzieję, że zrozumiesz, ale jeszcze się nie poddaję. Otóż, żeby tak w prostych słowach: nie ma to ABSOLUTNIE ŻADNEGO ZNACZENIA, czy w procesorze jest liczydło czy kubity, czy zapisuje to sobie cyframi rzymskimi czy hieroglifami. Z takiej oto prostej przyczyny, że jak sam na szczęście zauważyłeś – na poziomie programisty wynik MUSI być zgodny ze specyfikacją. Precyzję określa np. wspomniana przeze mnie wyżej IEEE754 i tak długo, jak definicja floata czy double opiera się o system binarny, tak długo będziesz mógł dodawać 0.5 (do pewnego zakresu), a nie będziesz mógł dodawać 0.1 (w żadnym zakresie). Jak stworzysz architekturę opartą o system trójkowy, to powstaną nowe standardy …i nadal nie będzie to nikogo [za wyjątkiem ludzi, którzy budują/debugują same procesory oraz przy mikrooptymalizacji] obchodziło, jak to działa pod spodem – bo taki też jest cel zastosowania odrębnych warstw.

      “Nie chodzi o to, że reprezentacja floata a nie float zachowuje precyzję przez jakiś czas no bo jej nie zachowywuje”

      No to zmień sobie w moim kodzie warunek na 1300000 i wytłumacz różnicę w działaniu. Podpowiem: nie będzie to się 10 razy dłużej wykonywało, niż 130000.

      “tylko o ilość miejsc po przecinku które nie bez powodu wyświetla a raczej obcina printf […] printf tych miejsce NIE OBCINA”

      Zamiast zgadywać (nieskutecznie) to może byś tak sięgnął do źródła? Masz całe formatowanie w vprintf.c, a tam prosto w komentarzu odnośnik do printf_fp.c – no to zaglądamy do nagłówka i czytamy:

      This is an implementation of a restricted form of the `Dragon4′ algorithm described in “How to Print Floating-Point Numbers Accurately”, by Guy L. Steele, Jr. and Jon L. White, presented at the ACM SIGPLAN ’90 Conference on Programming Language Design and Implementation.

      i już masz swoją odpowiedź. W 1990 roku SIMD był w superkomputerach, a “jakoś” magicznie to również działało (zresztą widziałeś gdzieś %xmm w moim dumpie?). Więc printf korzysta z jakiegoś algorytmu do wypluwania floatów, a porównanie wartości liczb w kodzie to zwyczajny komparator. Wartości zwróconych łańcuchów znakowych, nawet jeżeli są takie same, nie mają najmniejszego znaczenia dla wartości porównania w kodzie. Nie rozumiem, co za magię widzisz w printfie – zrób sobie po prostu dumpa pamięci: http://wklej.org/id/1705327/ i będziesz wiedział, że 0+0.1=0.100000001; a teraz wskaż mi miejsce, gdzie zgodnie ze swoją teorią wszechrzeczy umieściłeś (znaczy procesor) “zaokrągloną wartość dla printfa, żeby nie musiał ucinać”.

      “Można filozofować w nieskończoność na temat koncepcji C, ale naprawdę najprościej jest po prostu właczyć debuger CPU z GDB obok i zwolnić ten jeden rdzeń na samplowanie.”

      Po co, pokaż po prostu skąd printf bieże tę “reprezentację”, którą “scheduler” trzyma “obok samego floata”. Bo debuger mówi coś innego, źródła też nie kłamią. Tylko bez lania wody, pokaż kod – chcę zobaczyć binarną wartość 1.0 zgodnie z tym, co wypluwa printf obok wartości 1.00000012, jaka znajdzie się wtedy w pamięci.

      Sugestie o jakimś cudacznym robieniu pętli ‘nieprzewidywalnych’ pozwolę sobie skwitować: a weźże po prostu zamień linijkę na “while(1)” – takiej żaden kompilator ani procesor nigdy nie zakończy, ustaw breakpointa, napisz nową teorię.

      A jak będziesz miał tę teorię już gotową, to sprawdź czy nie wysypie się na float a=1.00000012.

      Przerażające jest, że zaraz potem rzucasz mocne słowa o idiotach nierozumiejących twoich superskalarów, skoro sam nie ogarniasz trywialnej matematyki rządzącej floatami (bo że tej nietrywialnej nie rozumiesz, to nic dziwnego – w końcu to procesor magicznie skraca liczby, przechowując dwie wartości zmiennej gdzieś w pamięci nie-RAM).

    • @mxmm skoro nie umiesz debugerem to masz proszę, zobacz co się dzieje na ekranie, a co w pamięci: http://wklej.org/id/1705328/ – zdajesz sobie sprawę, że reprezentacja 1.000000 pochodzi z TEGO SAMEGO ADRESU PAMIĘCI, co wartość 3f800001, czyli 1.00000012? Domyślasz się już, co ucina printf? Tak! Otóż algorytm wyświetlania liczb zmiennoprzecinkowych usuwa część zawierającą niepewność, nie ma tu żadnych ‘wewnętrznych setek wartości’ i równoległego wszechświata. Dobranoc.

    • Uprzedzając jeszcze kolejny referat o potokach, które nie mają żadnego związku z takim a nie innym zachowaniem floatów – usuń całkiem z kodu te pętle, ustaw wartość zmiennej przez inline asm (albo ustaw debugerem – żeby kompilator nic nie mógł ‘przewidzieć’ ani ‘zoptymalizować’), powtórz eksperyment. Wyłącz cache, odpal kod na i386 czy czymkolwiek bez FPU, moźesz to nawet przesymulować na jakimś emulatorze czy bibliotece do floatów na maszyny stałoprzecinkowe; rób cokolwiek tylko uważasz za stosowne. Znajomość architektury x86-64 nadal do niczego nie będzie potrzebna, bo wynik będzie wciąż deterministyczny (z poprawką na ewentualne błędy implementacyjne).

      Choćby nie wiem jak te potoki się dwoiły i troiły, choćby było w cache pierdylion reprezentacji tego floata, to liczba niewymierna w danym systemie liczbowym się tam NIE ZMIEŚCI, z kolei liczba wymierna w pewnym zakresie zachowa ABSOLUTNĄ dokładność (np. 0.5). Oczywiście nic nie stoi na przeszkodzie, aby zrobić bilion-precision albo stworzyć algebrę operującą na ułamkach zwykłych, ale takie rzeczy to nie w procesorze ogólnego zastosowania.

    • Nie o liczby niewymierne i wymierne mi chodziło, tylko ułamki nieskończone i skończone.

    • @gotar cześć :) wychodzi z tego dłuższa zagwozdka – przynajmniej dla mnie.
      Przy okazji i tylko z twojej i wyłacznie twojej winy odkryłem, że w GCC da się sterować generowaniem cisco-x64owych makr warunkowo i to działa.

      Gotar ja mówię o NISKOPOZIOMOWYM działaniu procesora i debugowaniu działania KODU – a nie MAKROKODU który widzisz w GDB w wypadku tej pętli tylko mikrokodu lub opkodu który powinieneś zobarzyć na debugerze procesora.
      Odpalić, zerknąć, zaręczam, że to nie zaboli :) a da konkretny pogląd jak działa dzisiaj komputer i jak złożone tricki stosuje procesor REKOMPILUJĄC tą pętle na RISC-owy język.

      No więc masz racje co do kwestii, że na wynikowe zachowanie wstawienie tego warunku aby poinformować GCC o skończoności pętli nie ma wpływu – bo GCC generuje makra w tym wypadku w taki sposób, że robi grzebień między pionem a poziomem.
      Kod zostanie wykonany dając faktycznie taki sam wynik, ale jego FIZYCZNE wykonanie w przewidywalnej i nieprzewidywalnej pętli będzie inne – to bardzo proste.

      Znajomość PODARCHITEKTURY x86_64 JEST potrzebna praktycznie wszędzie i stanowi absolutną PODSTAWĘ PROGRAMOWANIA.
      Bez niej nie da się nawet programować!!! – bo nawet zwykły developer pracujący przy grze musi zdawać sobie sprawę z tego jak poprawnie wygenerować makra w danej sytuacji aby zostały wykonane w PEŁNEJ PRĘDKOŚCI ZEGARA i to DLA DANEJ PODARCHITEKGURY – kiedy jedna rura nie przekracza w dzisiejszych czasach prędkości sięgającej do 500 MHz – lub ledwo przekracza.
      Oczywiście najczęściej -mtune działa skutecznie, a metoda makrowania x86_64 i integracja z riscową warstwą jest dla użytkownika mocno skalowalna.

      Reasumując, masz absolutnie rację, że kod się wykona skutkowo dokładnie tak jak starożytnim CISCU ze prawdawnych lat i skutek będzie za każdym razem taki sam na ekranie!! ale czas wykonania, metoda wykonania W OGÓLE KOD WYNIKOWY tego makra w wielu wypadkach może być TOTALNIE INNY (i to nawet po wstawieniu w nieopowiednie miejsce nopa – bo procesor może to potraktować jako celową chęc wrzucenia go na jeden cykl w jeden wewnętrzny rdzeń).

      Też miałeś racje, że GCC jest na tyle świadomy, że WIE o skończoności pętli i robi sobie grzebienie między poziomem a pionami i dodatkowo WIE, że przy okazji do cache może sobie zakolejkować IO które jest obsługiwane w tym samym segmencie kodu (przed wykryciem znacznikiem gałęzi).

      Gotar, po prostu w dzisiejszych czasach jeżeli z rozłożeniem makra coś pójdzie nie tak i będzie szłonie tak w postaci cyklicznej, to o pełnej prędkości wykonania równoległego kodu na wszystkie potoki można pomarzyć – co oznacza, że dany program nie będzie mógł działać z pełną prędkością zegara procesora.
      Procesory nie mają takiej prędkości jaka jest zadeklarowana na pudełkach, a jedyną możliwością osiągnięcia pełnego rozkładu na krytyczną i ryzykowną wręcz ilość rur wykonawczych jest współpraca z kompilatorem.

      Właściwie to dla niedających się poprawnie rozłożyć wyrażeń – i zwłaszcza wyrażeń z użyciem ALU… gdzie powiedzmy ten rozkład nie nastąpi a pętla cykl po cyklu zostanie wykonana jako pętla co nie, no to trzeba po prostu podzielić prędkość zegara procesora przez 16 pip dla każdego cyklu.

      btw 16 to takie założone ekstremum przez inżynierów (prędkość wykonania równoległego całych makr VS prostota rozkładu i koszty zacięcia).

      Nie da się programować w ogóle niczego nie wiedząc tego… bo realnie producenci procesorów zostawili świadomość tego jak są rozkładane wysokopoziomowe makra które widzisz w GDB nam.
      Jeżeli tego nie rozłożymy poprawnie lub zrobimy zbyt wiele np celowo nierozkładalnych pętel to mamy przerypane bo możemy nawet na setki cykli ograniczyć prędkość jednostki do 1/16.

    • @gotar a btw… Intel daje fajniejsze narzędzia do debugowania niż AMD no i jest ładne GUI

    • @gotar pardą, ale w tej chwili siedzimy w ponad 30 osób i wałkujemy te makra w pobliżu komunikacji z shaderami :) przez sterownik gpu.

      Bez tej absolutnie podstawowej wiedzy z zakresu informatyki jak te makra x86_64 są rozkładane na riscowy język i na ilu rdzeniach równolegle – jeszcze raz – bo nie tylko same pojedyńcze instrukcje ale CAŁE MAKRA i CAŁE PĘTLE Z TYCH MAKR przez sheduler NIE DA SIĘ NAWET SKUTECZNIE jednego elementu sterującego shaderem napisać.

      Koszty zacięcia jednej podgałęzi mogą być tak wysokie, że jedna gałąź może zadecydować o spadku prędkości do 1/16 dla CAŁEGO silnika graficznego.
      Po prostu dali nam możliwość integrowania i sami zrobili bardziej złożony mechanizm składania RISC-owych makr, ale niestety my też w tym momencie możemy bardzo mocno napsuć.

      Naprawdę polecam zerknąc sobie na mapę tych makr (ROP) x86 i odpalić debugger procesora. ;)

      Btw:
      =====
      int licznik=0; // nadajemy wartosc aby zresetowac alokacje
      400531: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
      float i=0; // tutaj zmiennoprzecinkowa
      400538: 8b 05 da 00 00 00 mov 0xda(%rip),%eax # 400618
      40053e: 89 45 fc mov %eax,-0x4(%rbp)

      // petelka
      for ( licznik=1;licznik<=20;licznik++ ) {
      400541: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%rbp)
      400548: eb 25 jmp 40056f
      i+=0.1; // meczymy bity dzielenia w petli
      40054a: f3 0f 10 45 fc movss -0x4(%rbp),%xmm0
      40054f: 0f 5a c0 cvtps2pd %xmm0,%xmm0
      400552: f2 0f 10 0d c6 00 00 movsd 0xc6(%rip),%xmm1 # 400620
      400559: 00
      40055a: f2 0f 58 c1 addsd %xmm1,%xmm0
      40055e: 66 0f 14 c0 unpcklpd %xmm0,%xmm0
      400562: 66 0f 5a d0 cvtpd2ps %xmm0,%xmm2
      400566: f3 0f 11 55 fc movss %xmm2,-0x4(%rbp)
      int licznik=0; // nadajemy wartosc aby zresetowac alokacje
      float i=0; // tutaj zmiennoprzecinkowa

      // petelka
      for ( licznik=1;licznik<=20;licznik++ ) {
      40056b: 83 45 f8 01 addl $0x1,-0x8(%rbp)
      40056f: 83 7d f8 14 cmpl $0x14,-0x8(%rbp)
      400573: 7e d5 jle 40054a
      i+=0.1; // meczymy bity dzielenia w petli
      }
      =====
      Jest grzebień w poziomie i w pionie?
      Jedno przejście tej pętli to DWA CYKLE wzsystkich 16 rdzeni RISC procesora.
      Ile instrukcji zajmie samo podbjianie licznika w petelce / rur / rdzeni w wypadku starego x86?
      addl = 3
      cmlp = 4
      jle :) nie wiem dużo

      Ile instrukcji w wypatku tej konwencji GCC w grzebieniu który zrobił zajmie rozłożenie addl + cmlp + jle w takiej postaci i przy śledzeniu rejestrów na makro ROP?
      Uwaga. JEDNĄ.
      Gdzie ona jest?
      W poziomie na ostatnich rurze pod simdami na górze :)

      Co potrafi GCC, to obalić szczękę do dołu……
      To nie jest po prostu dobrze zrobiony grzebień, tylko normalna regularna ELEGANCJA.

    • @gotar ^ a btw poprawie sam siebie DWA cykle i to podczas odrębnego wykonania.
      Shedulator może sobie umeiścić tak ładnie złożone makra DOKŁADNIE JEDNO POD DRUGIM.
      Jeżeli zrobi to poprawnie i sobie zapisze ich strukturę w cachefile to mamy wtedy JEDEN CYKL na wszystkich 16tu riscowych procesorach w rdzeniu :)

      Patrz na usta: JE DEN CYKL. Równolegle = pełna prędkość zegara. ;D

    • @maxmm, gotar – czekam na kolejne wypociny, co prawda maxmm trochę za bardzo się rozciąga w swoich tłumaczeniach, ale fajnie się Was czyta, no i chcę zobaczyć kto ma w końcu rację ;D

    • @maxmm
      To nie jest monolog!

      Co nie znaczy, że skoro nikt nie ma chcęci, aby Ci odpowiedzieć na ten twój bełkot, który nie reprezentuje żadnych konkretnych danych, nie znaczy, że masz rację. Żyj dalej w sci-fi.

    • @gotar
      Wyraźnie Tobie napisałem, że nie chodzi mi o skutek wykonania programu, tylko o SZKOLNY fakt z wiedzy podstawowej jak ten program ZOSTANIE FIZYCZNIE wykonany a co do skutku wykonania tych twoich “basicowych” makr z objdumpa przyznałem ci rację.

      Jeżeli nie rozumiesz w jaki sposób działa procesor to wyjedź sobie z polski i pójdź do normalnej szkoły. Na końcu zamiast się wgapiać w makra generowane przez GCC i twierdzić, że jest to co ci komputer wykona, będziesz nawet potrafił napisać program za który pieniądze dostaniesz a nie je wyłudzisz narażając na koszt pracodawcę.

    • @gotar właśnie dobrze napisałeś: żyjesz w SciFi do tego stopnia, że nie potrafisz nawet przeczytać co się do ciebie mówi – i że chodzi o FIZYCZNE wykonanie tego programu przez procesor.
      Oczywiście nigdy nie przeczytasz żadnego złożonego zdania, bo ciągłość czasu ci na to nie pozwala. Dodatkowo nigdy nie zobaczysz w całości jak wykonywany jest RZECZYWIŚCIE program, bo wylecisz prawdopodobnie z każdego szkolenia zanim zaczniesz.

      Sorry, ale nie nawet oszustów, tylko tego rodzaj CHORYCH psychicznie osób jest na pęczki i może właśnie dlatego przy ostatnich szkoleniach firmy robiły tak mocną selekcje aby w ogóle ujawnić informacje patentowe zainteresowanym.

      Z wiedzą na twoim poziomie i wgapianiem się makro assembler proponowałbym jednak zamiast kraść w kraju, znaleźć sobie bardziej pracę przy miotle.

    • Kochani to jest niestety poważny problem o którym mowią dzisiaj wszyscy specjaliści z jakiejkolwiek ścisłej branży.
      Jeden z nich to Bill Gaede, który rozpędził jedną z firm produkującą procesory.

      Osoby chore psychicznie potrafią widzieć WZROKOWO koncepcje i nigdy nie zadadzą sobie nawet pytania jakich relacji obiektowych one dotyczą, ale nigdy nie będą w stanie nawet zadać prostego ludzkiego pytania (raczej ich umysł im go nie zada) jak to działa.

      Dzięki właśnie takim znachorom mamy dzisiaj elektrony, fotony, lub ASSEMBLER (x86) który nawet NIE JEST assemblerem niskopoziomowym, a jest przedstawiany jako obiekt.

      Oczywiście te świry naprawdę potrafią się realnie WGAPIAĆ w kod, widzieć foton jako obiekt czy innego koncepcje na podstawie RELIGIJNEJ jako zwykłe duchy.
      Problem tych wariatów jest powszechnie znany i warto na jego temat choćby poczytać aby nie zatrudnić w przyszłości takiego półgłówka za pensję przy pracy.

      Co do działania tych wszystkich świrów, to razem z WIARĄ w te koncepcje typu foton, elektron, assembler x86, demony czy duchy, przedstawianych końcowo jako obiekty – shizofrenicy zamieniają definicje w obiekty.. to niestety tacy ludzie słyną też z faktu, że w swojej shizofrenii nie wystarcza im CIĄGŁOŚCI CZASU aby przeczytać bardziej złożone zdanie w jednej całości, wliczając barwę tonu którą ono zawiera.

      Matka boska duchy, demony, potwory, elektrony, fotony i inne koncepcje. Oczywiście nikt się nawet nie zastanowi CZEGO :)

      Tego rodzaju osoby choroby psychiczne są problemem właśnie z tego powodu. Jeżeli ktoś jest ciekawy jak skutecznie dyskredytować takie osoby jak ten troll powyżej to zapraszam do odrobienia podstaw nt izolacji FILOZOFII religijnej od nauki, którą fakt faktem zaczął w postaci publicznej po długim działaniu w podziemiu sam Bill Gaede.

      Współczucia dla pracodawców, w tym dla mojego :) od którego postanowiłem pobierać tylko połowę stawki godzinowej i to mimo, że z jakiegoś “dziwnego i niewyjaśnionego powodu” płaci za tą godzinę całkiem sporo zerową kwotę.

      Może płaci te parę tysięcy zielców za godzinkę z prostego powodu: takiego, że osoby ZDROWE psychicznie posiadają zdolność postrzegania równoległego i nie zastanawiają się nad żadnym kodem ani jego fizycznym wykonaniem, tylko po prostu GO WIDZĄ z tym wykonaniem równolegle.
      Świrom o których mówią dzisiaj pracownicy firm produkujących procesory jednak nie da się tego w żaden sposób wyjaśnić.

      Tylko przepraszam za swoją arogancję, bo pomyliłem tego gówniarza z dorosłym i sprawnym intelektualnie człowiekiem, spamując niepotrzebnie temat.

    • a pomijając same nie=dorozwinięcia i udawanie przez tego typu ludzi, że w ogóle one ROZUMIEJĄ co robią… to jako osoba współodpowiedzialna za jeden z bardzo dużych dziwnych projektów teraz zostałem zmuszony do studiowania psychiatrii w wyciętym przez pracodawcę zakresie.

      Szczerze wszystkim polecam lekturę CZEMU osoby niedorozwinięte umysłowo nie potrafią przeczytać normalnie “CZOŁOWO” napisanego złożonego tekstu.
      Jest to opisane nie tylko pod ogólnym zespołem shizofrenii jak można by początkowo sądzić, ale bardzo dobrze opisane jako Split Korzybskiego… i model postrzegania przez takich ludzi rzeczywistości.
      Natomiast nawet Freud,Korzybski po nich instytut NIST a następnie dopiero szpiedzy i naukowe podziemie nie dokonało takiego przełomu jaki obecnie ma miejsce w celu dyskredytacji i odsunięcia tego elementu od życia społecznego.

      Korzybski nie mając możliwości technologicznych zauważył, że ten element nie tylko w nieciągnącej się depresji nie potrafi czytać “lateralnie” czołowo żadnego tekstu i widzi w ludzkim tekście niezawierającym depresyjnych uprzedzeń zwykły bełkot, ale zauważył że “mózg limbiczny” “nie pompuje” u tego elementu ciągłości czasu, wraz z brakiem możliwości “widzenia równoległego” warstw na których osoba operuje koncepcyjnie.

      Warto przestudiować te lektury z takiego samego powodu z którego ta wiedza jest czynnie wykorzystywana dzisiaj przy prowadzeniu projektów i rekrutacji.

      Ja akurat chciałem przeprosić na koniec, bo niestety jestem jedną z tych osób, która jest również strategicznie odpowiedzialna za filtrowanie takiego elementu od poważniejszych zadań, dostając za to :) satysfakcjonujące pieniądze których nie warto się wstydzić.
      Niestety zdarza mi się jeszcze uciąć z tymi religijnie upośledzonymi cwaniaczkami dyskusję.

      Moredator: jak ci się podoba to wywal to w cholerę… bo to moja wina :) że pogdybałem sam do siebie słuchając gdakania nierozumiejącej co się do niej mówi zwykłej upośledzonej małpy….
      My ich w ostatnich latach robimy na kilotony…… kurna.

    • Pomijając wariatów innych czubków widzących koncepcje assemblera jako obiekty końcowe, to gdyby ktoś był ciekawy w jaki sposób wykonuje się ten float w pętli w rzeczywistym świecie – podzielony między pionem i poziomem można przeczytać tutaj (objdump):
      http://en.wikipedia.org/wiki/Micro-operation
      http://umcs.maine.edu/~cmeadow/courses/cos335/COA15.pdf

      Szczerze ludziska polecam nie nabierać się na świrów widzących magicznie wykonujący się assembler, bo tego jest multum i jest specyficzny upośledzony model który posiada dobrze rozbudowaną logikę ale nie potrafi zazwyczaj myśleć (plaga).

      Debugery i dokumentacje są dostępne na stronach producentów procesorów. Szkolenia organizują zewnętrzne firmy i oczywiście uczelnie (takie normalne a nie udawane pod autyzm jak w Polsce).

      Warto się tym zainteresować jeszcze zanim zatrudni się ludzi do pracy i to zanim ci ludzie napiszą cokolwiek.
      Zatrudnianie znahorów widzących “magicznie” działające makra x86 może się skończyć z uruchomieniem programu zdegradowanym do prędkości 1/(16*16) zegara a nawet gorzej bo koszt zacięcia to kilkanaście cykli i może być wykonywany na jednym rdzeniu – a to z kolei w firmie uwalnia całą kaskadę decyzyjną która prowadzi do błędu z powodu praktykowania magii przez programistów.

    • @Przemysław – a nie umiesz sobie skompilować tego kodu i samemu sprawdzić, kto ma rację?

      @maxmm – najwyraźniej posiadana przez ciebie wiedza nie pozwoliła ci przewidzieć wykonania programu, od którego zaczęła się ta dyskusja. Ja natomiast, mimo iż takiej “szkolnej, podstawowej wiedzy” wg ciebie nie posiadam, prawidłową odpowiedź dałem od razu. Niech to samo w sobie świadczy o tym, jak bardzo nie potrafisz swojej “wiedzy” wykorzystać, w związku czym nie jesteś żadnym programistą (raczej za kilka $ na godzinę), a teoretykiem-bajarzem.

      FYI: ja się uczyłem jeszcze czegoś takiego, jak zachowanie procesora w stanie błędu, np. przy zwartych konkretnych nóżkach – ale nigdy w życiu nie wpadłoby mi do głowy, żeby analizować poziomy napięć na scalaku podczas wykonywania kodu w perlu, takie zachowanie to powinien przeanalizować, ale specjalista od głowy.

      No i wreszcie te końcowe majaczenia o fotonach, elektronach i matkach boskich chyba potwierdzają powyższą diagnozę. Którą zresztą znasz dobrze, skoro studiujesz (tylko znowu – pomyliłeś “pracodawcę” z “lekarzem”).

      BTW to nie ja napisałem, żebyś żył dalej w sci-fi, ale to chyba przez to równoległe widzenie świata nie zauważyłeś (po raz kolejny) “oczywistej oczywistości”.

      Linki, które dałeś, nie wnoszą oczywiście NIC do dyskusji (8085, poważnie?!) – zapewne ich po prostu nie zrozumiałeś, bo ani objdump się tam nie przewija, ani żadne “zrównoleglanie”; raczej sugerują, że terminy CISC/RISC to znasz z okładek książek, których nigdy nie przeczytałeś. Bredni na temat równoległego wykonywania takiej pętli na wielu rdzeniach to nie chce mi się nawet komentować – to również może sobie sprawdzić każdy sam w domu, wystarczy jeden z powyższych programów uruchomić na “kilku” rdzeniach, a później wyłączyć dodatkowe i porównać czas wykonania na jednym. Nie wiem jaki szok przeżyjesz, gdy kiedyś dotrzesz do literek N-U-M-A.

    • @maxmm czy tam mxmm – no tak, Bill Gaede, czyli doskonale trafiłem z paranaukami:) O tym człowieku nie wiem, co myśleć – doskonale manipuluje definicjami (poza zakresem ich stosowania bądź w innej dziedzinie), desygnatami, sprytnie ukrywa abstrakcję za jakąś tam ograniczoną jej manifestacją (żeby zaraz potem zagrać tymi ograniczeniami), ignoruje eksperyment (podstawową metodę weryfikacji teorii naukowych), samemu zmieniając …jedynie “wizualizację” modelu. Lawirować w ten sposób może jedynie ktoś, kto ma rzeczywistą wiedzę w danym temacie (w przeciwieństwie do twoich bredni dotyczących zrównoleglania operacji), więc widzę dwie opcje – albo koleś postanowił wykorzystać swoją wiedzę do zarobienia jakiejś kasy na ludziach ułomnych-acz-aspirujących naukowo (pełno tego szwęda się po internetach, patrz w lustro), albo za dużo w życiu już spalił/wypił/wciągnął. Za to doskonale wiem, co sądzić o jego “wyznawcach”.

      Bo jego sztuczki odkryć można bardzo szybko z wiedzą na poziomie szkoły średniej. Trochę więcej trzeba wiedzieć, żeby wykryć szwindel przy wyjaśnieniu paradoksu EPR za pomocą jego mechanizmu lin – kierunek obrotu (CW/CCW) jest w tym wytłumaczniu niczym innym, jak zmienną ukrytą; zakładając istnienie zmiennych ukrytych, cały paradoks można wyjaśnić dowolną teorią (nawet gdybym na poczekaniu wymyślił małpy porozumiewające się telegrafem). Problem w tym, że owe zmienne nie są zgodne z eksperymentem – czyli liny z nich korzystające nie są zgodne, więc cała jego teoria nadaje się do piachu. Dalej – skwantowanie poziomów energetycznych elektronu w atomie: dlaczego jego lina skracać się może tylko o cały węzeł? Znam jeden twór, który musi utrzymać się w węzłach, aby się nie wygasić – fale; ale on tymi linami chce właśnie fale E-M zastąpić! Czyli jedynie zmienia terminologię i wizualizację, nie wnosząc nic nowego do aparatu.

      To zbierzmy twoje błędy dotyczące “fizycznego” wykonania tego programu /na wstępie, jak komuś się nie chce czytać, polecam skok do pkt. 25/:

      0. fizyczne to jest na tranzystorach, a nie w RISC-u i ALU, ale nie będę się czepiał,

      1. nie ma żadnych “półbitów” ani bitu n/2 – po prostu nie wiesz, jak komputery trzymają liczby zmiennoprzecinkowe (“w pamięci”?),

      2. “zapalenie drugi raz” tego samego bitu oznacza wygaszenie go i włączenie bitu wyższego – aż do overflowa, to chyba dzieci wiedzą,

      3. kompilator nie używa żadnej “reprezentacji dziesiętnej”, printf również nie korzysta z tej “obciętej wersji”,

      4. metoda wykonania pętli nie ma żadnego znaczenia, więc całą część “fizyczną” rozpocząłeś tylko dla zamaskowania swojej niewiedzy z wcześniejszych komentarzy; w kolejnych odsłonach widziałeś jakąś magię odcinającą ostatnie miejsca ułamkowe przy wyświetlaniu printem, czym się sam ponownie prosiłeś o lanie,

      5. przy zrównoleglaniu danych (pipeline’y oraz ALU) kolejność wykonywania commitowanych operacji NA JEDNEJ WARTOŚCI NIE BEDZIE ZMIENIONA przynajmniej w zakresie ich przemienności matematycznej – mogą zostać złączone (jak FMA),

      6. “programista kazał operować na dziesiętnych częściach alokacji zmiennej” – ten bełkot to z translatora?

      7. “Powstaje konkretny MakroOP” – wręcz przeciwnie, z MOP-a robi się zestaw instrukcji RISC-owych dla potoków,

      8. “chcemy skorzystać z pełnej możliwości zrobienia makra o charakterze jak najbardziej wektorowym aby wykonać całe makro jak najszybciej na pipelinach ( a nie tylko pojedyncze instrukcje)” – takie rzeczy z automatu udają się tylko dla bardzo prostych pętli operujących na wektorach, nie ma zastosowania dla pojedynczych zmiennych (jak sama nazwa SIMD wskazuje). I chodzi nie o przyspieszenie na pipeline’ach, tylko na długich (bitowo) instrukcjach wektorowych; to się oczywiście dzieje na etapie kompilacji, więc widoczne jest w “moich” makrach asemblerowych, procesor sam nie wektoryzuje! W naszym przypadku i tak nie ma czego, bo do wykonania operacji N potrzebny jest wynik N-1, więc nie ma możliwości wykonania tego w jednym cyklu.

      9. “sheduler i inne układy mają do dyspozycji właściwie setki rejestrów i to nie tylko w cache.” – te “setki” rejestrów to nie są do dyspozycji schedulera ani nie znajdują się w cache ani w niczym innym (żadnym “nie tylko”),

      10. “ile cykli będą potrzebowały przepływające przez potoki makra” – w potokach nie ma makr,

      11. “czyli jak mocno rozpłaszczy pętlę i zawarte w niej rozpoznane np ROP-y” – kolejne bełkotliwe coś świadczące o nikłej biegłości w temacie, ROB-ów się nie “rozpoznaje”, tylko zwyczajnie wykorzystuje do OoO, chyba że RO”P” to jakieś inne coś? Zapewne, RISC-OP? To też ich się nie “rozpoznaje” ani nie są w pętli “na przykład”, tylko są jedynie one po zdekodowaniu. Na prawdę ciężko czytać coś tak nieprecyzyjnego, nie wiem co można w pętli rozpoznać, co by miało taki skrót.

      12. “w dzisiejszych czasach nie pojedyńcze instrukcje sa rozkładane na szerokość rur w pionie tylko CAŁA PĘTLA zostaje rozłożona jako jeden MOP – czego kolega z jakiegoś powodu nie sprawdził.” – zdradzę, że “jakimś powodem” był brak jakichkolwiek wzmianek na ten temat w jakiejkolwiek znanej mi publikacji. Owszem, wiem że wykrywanie pętli stosuje się dla odciążenia dekoderów, ale nic ponadto. Znaczy mówisz, że funroll-loops do śmieci?

      13. “KAŻDA WARTOŚĆ W ARCHITEKTURZE SUPERSKALARNEJ POSIADA SWOJĄ ODLICZONĄ REPREZENTACJĘ przechowywaną obok” – obok procesora? gdzieś na płycie głównej leży, może na radiatorze?

      14. “jak włączyć debuger procesora to od razu można zobaczyć, że w schedulator w wypadku przewidywalnej pętli zrobił sobie nawet kilka kopi tych floatów i jeszcze jakichś dodatkowych wartości + tak samo kilka ich reprezentacji i zrobił RÓŻNĄ ilość operacji ALU.” – słyszałem, że jak się najeść odpowiednich grzybków, to mozna zobaczyć fajniejsze rzeczy.

      15. >>po drodze sam programista nie będzie świadomy jakie wartości są “sprzętowo” podstawiane w reakcji nawet na proste “ucinanie” bitów w konkretnych sekwencjach instrukcji!!! i dlaczego print wyświetlił floata z taką ilością zer i z taką precyzją.<< bo taki jest algorytm wyświetlania floatów, nie ma to nic wspólnego z procesorem,

      16. "Już sam procesor nie może tylko MUSI działać mechanizmami konwersji floata na jego reprezentacje ze względu na naturę rozkładu makrokodu na mikroopy" – ALU obsługuje IEEE,

      17. "przy szybkiej konwersji na reprezentacje zera zostają ucięte dokładnie w miejscu gdzie REPREZENTACJA floata w pamięci schedulatora posiada określoną precyzję" – ten "schedulator" zajmuje się nieco innymi rzeczami, niż pamiętanie o precyzji floata, a ta wartość określona jest samym floatem,

      18. "w JAKI SPOSÓB printf sięga po tą wartość która i tak już istniała ZANIM w ogóle PC wskoczył na instrukcje która zrobiła odczyt tej wartości" – zazwyczaj wartość musi istnieć przed instrukcją, która ją odczytuje, w przeciwnym wypadku mamy niespodziewanki na m.in. niebezpieczniku.

      19. "będzie działać totalnie inaczej fizycznie i wykona się w innej ilości cykli w zależności od metody rozkładu na mikro-opy i wygeneruje mniej lub więcej zacięć w sytuacjach w których się znajdzie" – a jakie to ma znaczenie dla odpowiedzi na pytanie: "ile razy wykona się pętla"?

      20. "jak złożone tricki stosuje procesor REKOMPILUJĄC tą pętle na RISC-owy język" – to jest bardzo ciekawe, ale jak widziałeś, piszę z systemu 32-bitowego. Dlaczego nie wrzuciłeś żadnych dumpów? Chcętnie się przekonam, jak wygląda ten rozkład!

      21. "Znajomość PODARCHITEKTURY x86_64 JEST potrzebna praktycznie wszędzie i stanowi absolutną PODSTAWĘ PROGRAMOWANIA." – programiści perla, railsów, javy oraz androida, nie martwcie się, on bredzi. Od robienia optymalizacji są kompilatory, czasy optymalizowania asemblera się skończyły, bo obecnie:
      a) mikrokod RISC może być różny na różnych procesorach (zasadniczo dlatego zachowana jest ISA CISC+rozszerzenia), więc nie sposób tego ogarnąć – nikt nie będzie optymalizował na dziesiątki procesorów,
      b) algorytmy branch prediction też są zmienne – podobnie jak liczba rejestrów wewnętrznych, możliwości/opóźnienia ALU, czy w końcu zestawy rozszerzeń
      – no chyba że pracujecie dla NSA nad łamaniem kryptografii tak jak nasz bohater (albo piszecie kompilator),

      22. "Bez niej nie da się nawet programować!!!" – a to nie wystarczy przeczytać sobie "Intel/AMD … optimization guide"? Bo coś mi się zdaje, że którąś z nich przeczytałeś i teraz kozaczysz…

      23. "Procesory nie mają takiej prędkości jaka jest zadeklarowana na pudełkach" – sprawdziłeś to oscyloskopem czy googlem?

      24. "Naprawdę polecam zerknąc sobie na mapę tych makr (ROP) x86" – zapodaj proszę linka, żeby inni czytelnicy mogli się sami zapoznać.

      25. "Jedno przejście tej pętli to DWA CYKLE wzsystkich 16 rdzeni RISC procesora." – teraz nie kpię, będę poważnie pytał: co TY masz za procesor?! Bo może ja faktycznie jestem tak ostro do tyłu z wiedzą – ostatnio żeby wykorzystać kilka rdzeni albo SMT trzeba było robić wątki. Co z cache locality, kontekstami, synchronizacją – teraz CPU robi wszystko SAM?! Bo jeżeli miałeś na myśli jednostki wykonawcze a nie rdzenie (unit a nie core), to masz pod każdym zaledwie 3 ALU do FP, specjalizowane zresztą, więc zasadniczo taką pętlę robisz na 1 rdzeniu i 1 ALU.

      26. "przy śledzeniu rejestrów na makro ROP" – że co?! Jakie znowu makro ROP (makro-mikro opcode)? Jakie znowu śledzenie rejestrów? – to ja znowu nie wiem, czy pisząc ROP masz na myśli uOP czy ROB…

      27. "W poziomie na ostatnich rurze pod simdami na górze" – pisanie w polska język znacząco ułatwiać przyszła komunikacja, może nawet sprawiać, że odbierać was jako mniej bzurna.

      28. "Na końcu zamiast się wgapiać w makra generowane przez GCC i twierdzić, że jest to co ci komputer wykona" – no a wyobraź sobie, że DOKŁADNIE TO komputer wykona, bo inaczej byłby niedeterministycznym złomem. Ty sobie tutaj dywagujesz nie CO ale JAK wykona, co jest bezprzedmiotowe i wtrąciłeś jedynie dla zatuszowania swojej niekompetencji w zrozumieniu trywialnego kodu, ale także i w tej materii masz spore braki. Nie bez powodu architektura AMD64 nie odeszła od modelu CISC (mimo wewnętrznego RISC od dłuższego czasu), a interfejsy bezpośrednio do RISC NIE SĄ UDOSTĘPNIANE. W związku z tym procesory tej architektury są programowane opcodami tego asemblera, a kompilator może co najwyżej wygenerować szybsze (mniejsze opóźnienia), lepiej zrównoleglane (pipeline), bardziej przewidywalne (branche), łączone (fuse) itp. "makra", czyli ułatwić pracę procesora, ale nadal nie ma bezpośredniej kontroli nad RISC.
      Ale nawet gdyby założyć, że kogokolwiek tutaj interesowało "fizyczne" wykonanie – pominąłeś całkiem RAT-y, ROB-y, RS, wygasanie instrukcji, loopbacki, pobieranie danych z pamięci, writebacki i i całą masę innych rzeczy, które dzieją się wewnątrz. Podawanie tego co napisałeś jako "prawdziwą prawdę" o wykonaniu kodu jest takim samym skrótem, jak oryginalna pętla z pytania.

      29. "osoby ZDROWE psychicznie posiadają zdolność postrzegania równoległego i nie zastanawiają się nad żadnym kodem ani jego fizycznym wykonaniem, tylko po prostu GO WIDZĄ z tym wykonaniem równolegle" – no to jak jesteś taki chojrak, to proszę pokaż które ALU, z jakim opóźnieniem, działanie AGU, narysuj diagram czasowy, przelicz cykle… Bo masz rację – ja całego procesu wykonania takiej nawet trywialnej pętli wewnątrz procesora NIE UMIEM ogarnąć. Więcej, uważam – że podobnie jak z naszą rodzimą ustawą VAT-owską, nie ma na świecie osoby, która potrafiłaby ot ręki podać sposób jej całego wykonania na współczesnym "superskalarze". Trzeba przeanalizować poszczególne bloki, stany jednostek wykonawczych, policzyć cykle, składać cegiełki do kupy – tymczasem bez określenia, o którym dokładnie procesorze mówimy, nie wiadomo nawet jak długi jest potok!
      Liniowe podawanie kolejnych stanów procesora przy wykonywaniu określonego zestawu instrukcji przy określonym stanie początkowym to ostatnio robilem na piechotę na jakiejś Motoroli, już na Alphie to było porywanie się z motyką na słońce. Jeżeli TY twierdzisz, że umiesz takie rzeczy dzisiaj, to wybacz – ale śmiech we mnie wzbiera. Przy takiej liczbie błędów, jakie popełniłeś, zaczynając od elementarnego ucięcia precyzji liczby 0.1, to tobie się może co najwyżej WYDAWAĆ, że "widzisz" jak to działa. Zresztą, gdybyś miał w głowie taki symulator procesora, to nie siedzielibyście w 15 nad jakimś problemem.

      30. "uruchomieniem programu zdegradowanym do prędkości 1/(16*16) zegara" – no takiego cudeńka to bym na pewno nie wyrzeźbił nawet celowo. Ale jako profesjonalista "strategicznie odpowiedzialny" na pewno masz ciekawe przykłady kodu zdegradowanego przynajmniej do 1/16, którymi się zaraz z czytelnikami podzielisz, prawda?

    • @gotar – umiem skompilować i sprawdzić, to nie jest problem ;) Po prostu poruszaliście takie tematy, o których nie mam zbytnio pojęcia i miło się czytało, chociaż po ostatnich wywodach maxmm o religii, chorych umysłowo, etc. każdy normalny uzmysłowiłby sobie, że on jednak też należy do tych ostatnich… Gotar, co za studia, kierunki, szkolenia przeszedłeś, by mieć taką wiedzę?

    • @Przemysław – na katedrze elektroniki (obecnie widzę, że metrologii i elektroniki) krakowskiego AGH w bardzo specyficzny sposób uczy dr. inż. Bogusław Wiśniewski. Przykładowo ‘bajcik’ studentów (znaczy ósemka) siedzi w rzędzie i kolejno wykonuje program albo coś (czasem dostanie im się przerwaniem, czasem jakiś błąd wystąpi). Jak ktoś się pomyli, to kolejny ma to wychwycić. Jak kilku z rzędu nie wychwyci, to robi się coraz trudniej – bo trzeba odtworzyć cały stan (stosy, rejestry, stany przerwań). Na labolatoriach programowało się za pomocą klawiatury szesnastkowej (plus parę klawiszy kontrolnych, typu adres+, adres-, enter, escape) – więc nawet bez mnemoników asemblerowych, tylko wprost wpisywanie kodów instrukcji oraz wartości argumentów (a przy zmiennej długości rozkazu jeden pominiety bit oznacza przeliczenie i ponowne wpisanie całego programu). Dla kogoś, kto się procesorami nie interesuje, to jest istna męczarnia, ale osobie zainteresowanej tego rodzaju “przeszkolenie” uświadamia parę rzeczy. Ucząc się do egzaminu wprost z instrukcji architektury jakiegoś procesora (bo książek opisujących ‘beletrystycznie’ takie detale nie ma) opanowujesz w zasadzie cały aparat niezbędny do tego, aby faktycznie projektować układy korzystające z takich procesorów. Zrozumienie ich działania to zaledwie mały element uboczny.

      W szkolenia żadne nie wierzę (tzn. takie firmowe) – nie spotkałem jeszcze kompetentnego prowadzącego, bo żeby temat mieć całkiem rozpracowany, to potrzeba nie dość, że pasjonata, to jeszcze takiego, który zęby zjadł w swojej dziedzinie; ze świecą takich szukać w każdej branży. Z nauką jest jak z innymi dyscyplinami – poziom mistrzowski można osiągnąć po przepracowaniu nad tematem ok. 10 tys. godzin (to jest jakieś 5 lat pełnego etatu); co oczywiście nie znaczy, że każdy po 5 latach jest mistrzem, właśnie pasjonatowi tyle to zajmie.

      A po latach siedzenia w branży jakąś tam wiedzę po prostu się zdobywa przy okazji, bo ciągle coś nowego jest potrzebne. Ja na przykład gdzieś tak co 4-5 lat zmieniam nieco swój podstawowy profil, na początku były to ogółnie komputery (sprzęt+oprogramowanie), później typowo Linux, kolejno sieć, bazy danych, telewizja cyfrowa. Z tego jedynie dwa osobne zagadnienia nie wiążą się ze sobą, pozostałe wszystkie zależą silnie od poprzednich, przy wdrażaniu wszystkich w praktyce trzeba było bardzo dobrze rozpoznać możliwości sprzętowe (np. konsekwencje wprowadzenia QPI przez Intela), wszystkie związane są z programowaniem i wymagają olbrzymiej wydajności. Co znamienne, nie mogę polecić żadnych książek – wiele jest równie słabych, jak szkoleniowcy, ciężko o coś polecanego, więc to co się liczy, to doświadczenie, praktyka i czytanie publikacji oraz maili na listach pochodzących od najlepszych fachowców. Tutaj olbrzymi problem jest z telewizją, bo nikt nie dyskutuje o tym na forach i jedyną lekturą są 1000-stronicowe specyfikacje ETSI, ale można opanować szybkie czytanie serii takich dokumentów.

  11. W historii zawodowej pamiętam podobny “błąd” zupełnie niezamierzony, ale brzemienny w skutki. Otóż, było sobie oprogramowanie, które współpracowało z bazą danych.
    Aplikacja współpracująca – przetwarzane rekordy połączone z innymi rekordami na podstawie wspólnego klucza. Prosta sprawa. Oprogramowanie było testowane na różne sposoby. Działało bez żadnego problemu. Na podstawie informacji z systemu realizowane były wysyłki do klientów (zamówienie-towar).

    Wszystko było fajnie, dopóki liczb w kluczu było < 10. Początkowo zbiorów towarów nie było wiele w asortymencie – rzadko się zdarzało, że klienci zamawiali więcej niż kilka rodzajów towarów na raz. Ale przyszedł taki moment, że liczba towarów przekroczyła wartość krytyczną. Przesyłki realizowane zbiorczo raz na miesiąc.

    No i się stało. Raport zewnętrzny jaki był wypluwany z uwagi na ograniczenia związane z integracją, poprzesuwał wszystkie zamówienia – co spowodowało całkowicie błędną wysyłkę. Oczywiście kosztowało to firmę kupę kasy.

    Analiza problemu: okazało się, że jeden jełop inaczej nazywany administratorem baz danych, zmienił samowolnie typ kolumny w jednej z tabel z INT na STRING. Procedura pobierania danych i łączenia tabel oczywiście zwracała dane przesortowane niekoniecznie tak jak by wskazywała logika (1,2…10,11) ale (1,10,11,..,19,2,20). Liczby się porozjeżdżały. To były czasy gdy bazy jeszcze nie obsługiwały INNER JOIN-ów czy tego typu wynalazków.
    Czyli oprogramowanie X działało ok, oprogramowanie Y działało ok, współpracowały ze sobą, ale nikt nie wymyślił takiego przypadku testowego, który wykryłby kwestię zmiany typu kolumny w bazie.
    Nauczka na przyszłość: jakakolwiek modyfikacja oprogramowania zewnętrznego może rozwalić cały proces. Nawet drobna.

    W takiej elektrowni jądrowej procesy są dużo bardziej skomplikowane, skutki potecjalne błędów dużo gorsze – miejmy tylko nadzieję, że ci co je tworzyli znali się na swojej robocie bo inaczej to "dupa blada"…

    • W systemach krytycznych za kontrolę sensowności podejmowanych działań odpowiadają zewnętrzne systemy. Jeżeli oprogramowanie centralne każe np. zwiększyć temperaturę do 2147483648 stopni, to zareagować ma system monitorujący temperaturę, a dopiero później na podstawie logów można na spokojnie określić, co było przyczyną. A przynajmniej chciałbym w to wierzyć, bo paradoksalnie dzięki rozwojowi branży IT i zwiększeniu możliwości przemiału informacji aż chce się takie systemy integrować niepoprawnie – np. żeby ten system nadzorujący porównywał temperaturę z czujnika nie do tej, jaka jest “rozsądna”, tylko do tej, którą …kazał ustawić system centralny.

      W projektach mechanicznych takie wpadki to były zwyczajne “choroby wieku dziecięcego”, błędy wychodzą na jaw relatywnie szybko (coś się rozlatuje, albo jest zauważalne podczas przeglądu), natomiast w przypadku oprogramowania o braku błędów świadczy wyłącznie to, przez jak długi czas nie zaobserwowano żadnego skutku takiego błędu – w żadnym przeglądzie nikt nie będzie analizował wartości zmiennych oraz zrzutów pamięci, więc każde potencjalne przekręcenię wartości oznacza problem w konkretnym czasie, niekiedy bardzo długim. W mechanizmach wykrywania overflowów nie upatrywał bym większej nadziei (przynajmniej tak długo, jak można przechwycić wyjątek w celu olania go), bardziej pocieszają mnie w tej kwestii liczniki 64-bitowe, które przekręcą się dopiero na złomowisku.

    • Zachęcam do poczytania o wypadku w elektrowni jądrowej Three Mile Island:

      “Po spadku ciśnienia do poziomu optymalnego czujniki w centrali wykazały, iż zawór jest zamknięty. Ale czujnik nie wskazywał rzeczywistego stanu zaworu, a jedynie obecność impulsu elektrycznego zamykającego zawór, co zostało zinterpretowane jako fakt zamknięcia się zaworu. Bezpośredni czujnik stanu zaworu bezpieczeństwa został wyeliminowany z oryginalnego projektu z powodów oszczędnościowych.”

      Więcej: http://pl.wikipedia.org/wiki/Wypadek_w_elektrowni_jądrowej_Three_Mile_Island

  12. Wojsko działa na podstawie procedur. Więc jeżeli w instrukcji było napisane, że wykonać restart to powinni go wykonać. Jeżeli nie było nic w temacie restartu to nie wykonali.

    • @Radzik, “A jedzie mi tu czołg i dwie armaty?” wskazując na oko… Niejednokrotnie coś jest olewane, bo przełożony kazał, w wojsku, w policji, czy w firmie… Nie ma ludzi idealnych i w wojsku też…

  13. Nie było procedury nawkazującej restart, bo twórcy nie zakładali, że mobilne wyrzutnie będą działać w jednym miejscu dłużej niż 8 godzin. Jak Izraelczycy przekazali informacje procedura została stworzona, ale nie dotarła do jednostki na czas.
    Tu znajdziesz więcej szczegółów:
    http://www.konflikty.pl/technika-wojskowa/na-ladzie/co-sie-stalo-w-dhahranie/

  14. Katastroficzny może być film, natomiast skutki błędów programistycznych bywają katastrofalne.

  15. Ile trwa reset baterii Patriot ?
    W przypadku B787, to chyba skrót myslowy ? Wystarczy ‘reset’ generatorów, które zapewne są widziane jako osobny komponent przez pokładową sieć ‘typu CAN’, zwaną common core: http://www.adacore.com/customers/787-dreamliner-common-core-system/

  16. Ja czytałem tylko jedną ‘instrukcję do samolotu’ i tam było napisane by dobrze oczyścić powierzchnię przed sklejeniem, kleić w wentylowanym miejscu i w obecności dorosłego … więc te ‘instrukcje do samolotu’ nie są zbyt skomplikowane ;)

  17. Bardzo dobrze napisane i naprawdę świetnie się czytało

  18. O CZE GOTAR WBIJAJ NA WIADOMY !KANAL

  19. Fajny i ciekawy artykuł, bo zawiera kilka barwnych historyjek, natomiast to czego brakuje, to zaznaczenia, że są pewne konteksty, w których takie kwestie są kluczowe a w innych mniej. Teraz mniej doświadczeni adepci programowania, zaczną programować skrajnie defensywnie bez względu na rodzaj rozwijanego systemu. Powiedzmy sobie szczerze – są różne klasy systemów, które wymagają różnego poziomu zabezpieczeń i weryfikacji poprawności. Mam hipotezę, że 95% osób czytający ten wpis, nie pracuje nad tak newralgicznymi systemami (jak wojsko, sterowanie samolotów, medycyna decydująca o życiu).
    Dlatego – bądźmy świadomi zagrożeń, ale dopasowujmy podejście do kontekstu. Amen.

Twój komentarz

Zamieszczając komentarz akceptujesz regulamin dodawania komentarzy. Przez moderację nie przejdą: wycieczki osobiste, komentarze nie na temat, wulgaryzmy.