logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Różne oblicza optymalizacji

TechEkspert 26 Sty 2024 21:07 1080 10
  • Różne oblicza optymalizacji
    Wraz z dostępnością coraz większych mocy obliczeniowych oraz pojemności pamięci, często słyszałem narzekanie, że teraz programy nie są optymalizowane, tak jak kiedyś. Programiści idą na skróty, korzystają z bibliotek a kiedyś to było :) Czasami było to prawdą i łatwość tworzenia oprogramowania okupiony był zwięszkonymi wymaganiami sprzętowymi. Warto pamiętać o trzech parametrach projektu: koszt, czas, jakość. Optymalizacja, która dotyczy tych parametrów może np. zakładać szybsze dostarczenie produktu gdy będziemy wymagali większych zasobów sprzętowych.

    Optymalizacja wielkości programu i zapotrzebowania na RAM często wymuszona była przez skromne zasoby pamięci dostępnego mikrokontrolera. Optymalizacja szybkości wykonania kodu często była konieczna, aby rozwiązanie zadziałało na dostępnym sprzęcie.

    Obecnie warstwy abstrakcji i narzuty na wykonanie programu są często wręcz konieczne, ułatwiają szybkie tworzenie rozwiązań, współdzielenie infrastruktury, zapanowanie nad złożonymi systemami. Kiedyś mając do dyspozycji modem dial-up nie było sensu tworzyć usługi YouTube, gdy przepustowość łącz do internetu znacząco się zwiększyła, wykreowało to potrzeby i możliwości nowych usług.

    Kiedyś produkowane były komputery szachowe. Były to fizyczne szachownice z wbudowanym komputerem obliczającym ruchy. Obecnie znacznie lepiej zagra program uruchomiony na smartfonie, a jeszcze lepiej działający w chmurze dostępny online i często korzystający z AI. Tutaj znajdziecie materiał filmowy o komputerze szachowym na Z80 pod każdym polem znajdował się hallotron wykrywający położenie bierek, LEDy sygnalizowały ruchy komputera. W złącze rozszerzeń można było włożyć pamięć z otwarciami gry lub inny moduł z zakończeniami gry. Wtedy inaczej się nie dało. Robi wrażenie ile wysiłku (czasu) należało włożyć w opracowanie takiego urządzenia. Rozwiązanie musiało być zoptymalizowane aby w ogóle zadziałało i w rozsądnym czasie obliczyło ruch. Podejrzewam, że było to urządzenie dość drogie, droższe i mniej dostępne niż obecna aplikacja na komputer lub smatrfon, nie wspominając o grze przez przeglądarkę.

    Tutaj prostszy model Hanimex HCG 1700 oparty o Hitachi HD44840
    PCB urządzenia jest dość proste:
    https://www.schach-computer.info/wiki/index.php?title=Datei:Hanimex_HCG1700_07.jpg
    https://www.schach-computer.info/wiki/index.php?title=Datei:Hanimex_HCG1700_06.jpg

    Taktowanie 600kHz, RAM 128B, ROM 5k i co ciekawe to mikrokontroler 4 bitowy.

    Jakim cudem to działało?!

    Optymalizacja musiała być naprawdę silna, gracz wybierał 1 z 8 poziomów gry (5s do 14min "myślenia" komputera nad ruchem).
    Ten komputer szachowy osiągał siłę gry 1090 CElo.
    Czy to była ewaluacja najlepszej pozycji i losowe lub iteracyjne sprawdzanie kolejnych ustawień w założonym czasie?

    Prostszy i pewnie tańszy CXG-223 osiągał siłę gry 849 CElo na 4 bitowym HD44801 400KHz, 80B RAM, 2,7k ROM.

    Kolejne urządzenia korzystały z coraz większych dostępnych zasobów sprzętowych Mephisto Europa A 8 bitowy mikrokontroler, 8MHz taktowanie, 16kB ROM i 256B RAM dawało siłę gry 1722 CElo.

    Tutaj można porównać siłę gry różnych komputerów szachowych te na ARM Cortex M7 300 MHz dochodzą do 2594 CElo. Zaskoczyło mnie to, że takie urządzenia nadal są produkowane.

    Patrząc na zasoby jakie posiadały pierwsze przenośne komputery szachowe, podejrzewam że większe wymania może mieć program na Arduino wyświetlający 'hello world' na wyświetlaczu OLED... Zasoby są potrzebne większe, ale czasu potrzeba mniej a i efekt może być dość złożony.

    Czy optymalizowaliście kod aby zmieścić się w 2048B lub ilość instrukcji po wywołaniu przerwania aby zdążyć zareagować na jakieś zdarzenie?
    Na jakie zadania optymalizacyjne natrafiliście?

    Fajne? Ranking DIY
    O autorze
    TechEkspert
    Redaktor
    Offline 
    W moich materiałach znajdziecie testy i prezentacje sprzętu elektronicznego, modułów, sprzętu pomiarowego, eksperymenty. Interesuje mnie elektronika cyfrowa, cyfrowe przetwarzanie sygnałów, transmisje cyfrowe przewodowe i bezprzewodowe, kryptografia, IT a szczególnie LAN/WAN i systemy przechowywania i przetwarzania danych.
    Specjalizuje się w: mikrokontrolery, rozwiązania it
    TechEkspert napisał 5819 postów o ocenie 4623, pomógł 15 razy. Jest z nami od 2014 roku.
  • #2 20930616
    pawlik118
    Poziom 32  
    Jako przykład podam program dla 8051 napisany przeze mnie w asemblerze realizujący funkcje zegara:
    - obsługa 4 wyświetlaczy 7seg poprzez rejestry szeregowe 74595
    - obsługa 5 przycisków przez rejestry 74165
    - obsługa przerwania do generowania dźwięku "piknięcia" przy naciskaniu przycisków, czasu lampki i synchronizacji DCF, wszystko na jednym liczniku
    - funkcja czasowej lampki nocnej
    - odbiór sygnału DCF-77 z sumami kontrolnymi i synchronizacją czasu (po wybraniu funkcji aktualizacji)
    - ręczne ustawianie czasu z zmienną szybkością inkrementacji sekund i godzin w przód i tył
    - obsługa i2c w celu komunikacji z PCF8583

    i pewnie jeszcze kilka innych drobnych funkcji
    Wykorzystanie niecałe 2kB :)


    Asembler daje ogromne możliwości. Niemniej jednak jestem pełen podziwu jak to robili mając zmienne 4 bitowe.
  • #3 20930644
    TechEkspert
    Redaktor
    Robi wrażenie. Wykorzystanie 8051 w czasach TTL dawało możliwość dodawania kolejnych funkcji tylko kosztem zajętości pamięci programu. No i w porównaniu do TTL można było zrobić zegarek wielkości wyświetlacza LED i zamknąć w obudowie wielkości nie większej niż np. 2-3 pudełka zapałek. To było coś :)
  • #4 20930714
    pawlik118
    Poziom 32  
    Mało kto pamięta, jak wielkim ułatwieniem było chociażby programowanie ISP :)
    Swego czasu pracowałem w firmie produkującej fotele stomatologiczne. Główny procesor 8051. Program w całości napisany w notatniku -równo 12kB wsadu. Wykorzystane było dosłownie wszystko w procesorze może poza pojedynczymi bajtami pamięci. Po wydrukowaniu program zajmował około 100 kartek A4. Taka to historia sprzed dwóch dekad.
  • #6 20931201
    TechEkspert
    Redaktor
    Ciekawy konkurs i osiągnięcie, może zaprezentujesz też na elektroda.pl tetrisa 1kB?
    Kojarzy mi się to z demosceną i demami 64kB.

    Co do optymalizacji AI i GPT może być optymalizacją czasu i kosztu przy obniżeniu jakości odpowiedzi ;)
  • #7 20931912
    Mlody_Zdolny
    Poziom 30  
    TechEkspert napisał:
    teraz programy nie są optymalizowane, tak jak kiedyś. Programiści idą na skróty, korzystają z bibliotek a kiedyś to było

    Korzystanie z bibliotek wcale nie oznacza mniejszej optymalizacji. Biblioteki są rozwijane i posiadają najbardziej efektywne algorytmy, napisane raz a dobrze.
  • #8 20933233
    satanistik
    Poziom 27  
    Co do współczesnych programów - kiedyś pobrałem tetrisa na androida, telefon grzał się niemiłosiernie, a gra nie chodziła idealnie. A kolega napisał tetrisa na atmega8 z generowaniem obrazu vga w locie.
  • #9 20933361
    jarekgol
    Poziom 38  
    Też pisałem w asmie na 8051 i miło to wspominam, ale ostatnio robiłem dla siebie obługe modemu na avr/arduino i musiałem zrobić parser w locie, bo modem potrafi przysłać całkiem sporo bajtów "ciągiem", z których większość mi nie potrzeba, a zaczynało brakować ramu żeby je tam wsadzić i potem przeszukiwać.
  • #10 20934349
    katakrowa
    Poziom 23  
    Warto wspomnieć, że najmniejsze szachy w c++ napisał Pan Toledo:
    A najmniejsze szachy w HTML / JS: https://nanochess.org/chess4.html

    Więcej pod adresem: https://nanochess.org/

    
    <script>//(c)2009 Oscar Toledo G.
    var B,i,y,u,b,I=[],G=120,x=10,z=15,M=1e4,l=[5,3,4,6,2,4,3,5,1,1,1,1,1,1,1,1,9,9
    ,9,9,9,9,9,9,13,11,12,14,10,12,11,13,0,99,0,306,297,495,846,-1,0,1,2,2,1,0,-1,-
    1,1,-10,10,-11,-9,9,11,10,20,-9,-11,-10,-20,-21,-19,-12,-8,8,12,19,21];function
    X(w,c,h,e,S,s){var t,o,L,E,d,O=e,N=-M*M,K=78-h<<x,p,g,n,m,A,q,r,C,J,a=y?-x:x;
    y^=8;G++;d=w||s&&s>=h&&X(0,0,0,21,0,0)>M;do{if(o=I[p=O]){q=o&z^y;if(q<7){A=q--&
    2?8:4;C=o-9&z?[53,47,61,51,47,47][q]:57;do{r=I[p+=l[C]];if(!w|p==w){g=q|p+a-S?0
    :S;if(!r&(!!q|A<3||!!g)||(r+1&z^y)>9&&q|A>2){if(m=!(r-2&7))return y^=8,I[G--]=
    O,K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);while(n<=t){L=r?l[r&7|32]-h-q:0;if(
    s)L+=(1-q?l[(p-p%x)/x+37]-l[(O-O%x)/x+37]+l[p%x+38]*(q?1:2)-l[O%x+38]+(o&16)/2:
    !!m*9)+(!q?!(I[p-1]^n)+!(I[p+1]^n)+l[n&7|32]-99+!!g*99+(A<2):0)+!(E^y^9);if(s>h
    ||1<s&s==h&&L>z|d){I[p]=n,I[O]=m?(I[g]=I[m],I[m]=0):g?I[g]=0:0;L-=X(s>h|d?0:p,L
    -N,h+1,I[G+1],J=q|A>1?0:p,s);if(!(h||s-1|B-O|i-n|p-b|L<-M))return W(),G--,u=J;
    J=q-1|A<7||m||!s|d|r|o<z||X(0,0,0,21,0,0)>M;I[O]=o;I[p]=r;m?(I[m]=I[g],I[g]=0):
    g?I[g]=9^y:0;}if(L>N||s>1&&L==N&&!h&&Math.random()<.5){I[G]=O;if(s>1){if(h&&c-L
    <0)return y^=8,G--,L;if(!h)i=n,B=O,b=p;}N=L;}n+=J||(g=p,m=p<O?g-3:g+2,I[m]<z|I[
    m+O-p]||I[p+=p-O])?1:0;}}}}while(!r&q>2||(p=O,q|A>2|o>z&!r&&++C*--A));}}}while(
    ++O>98?O=20:e-O);return y^=8,G--,N+M*M&&N>-K+1924|d?N:0;}B=i=y=u=0;while(B++<
    120)I[B-1]=B%x?B/x%x<2|B%x<2?7:B/x&4?0:l[i++]|16:7;for(a=
    "<table cellspacing=0 align=center>",i=18;i<100;a+=++i%10-9?
    "<th width=40 height=40 onclick=Y("+i+") style='border:2px solid #aae' id=o"+i+
    " bgcolor=#"+(i*.9&1?"9090d0>":"c0c0ff>"):(i++,"<tr>"));
    a+="<th colspan=8><select id=t><option>Q<option>R<option>B";
    document.write(a+"<option>N</select></table>");
    function W(){B=b;for(p=21;p<99;++p)if(q=document.getElementById("o"+p)){q.
    innerHTML="<img width=40 src="+(I[p]&z)+".gif>";q.
    style.borderColor=p==B?"#ff0":"#aae";}}W();
    function Y(s){i=(I[s]^y)&z;if(i>8){b=s;W();}else if(B&&i<9){b=s;i=I[B]&z;if((i&
    7)==1&(b<29|b>90))i=14-document.getElementById("t").selectedIndex^y;X(0,0,0,21,
    u,1);if(y)setTimeout("X(0,0,0,21,u,2/*ply*/),X(0,0,0,21,u,1)",250);}}
    </script>
    


    
    #define    F getchar())
     #define H(z)*n++=z;
           #include        <setjmp.h>
        #define v main(0,0,0
               #define Z while(
                                                     #define _ if(
    #define o(d)(S=63,l[d]=6^e,q=1e4>v,u[l]=0),l[d]=0,u[l]=e^6,S=b,q)
    #define I(H,n) { _ r=l[x=H],!r|(r^e)<-1){ _ j=u[l],-7==r|6==r\
    ){ n; e=~e; return 1e5-443*f; } u[l]=0,t=j+1,i=j-1; _!i&89<\
    x)i=j,t=6; _-1==t&30>x)t=j,i=-7; Z++i<t){ d =0; S&= 63; \
    a=((j^e)!=1?6!=(j^e)?O[32+x/10]-O[u/10+32]-q:(S|=6!=j?8\
    :1,2==u-x)*9+9*(x-u==2):(d=1==j?x-u:u-x)/8+!(!((x-u)%\
    10)|r)*99+(j==1?90<x:29>x)*(9*O[28+i]-288))+O[r+28\
    ]*9-288+O[x%10+33]-f-O[33+u%10]; x[l]=i; S|=(21=\
    =u|21==x)*2+(u==28|28==x)*4+(91==u|x==91)*16+32\
    *(u==98|x==98)+(20==d)*64*x; a-=k>f?main(a,f+1\
    ,M,k):0; _ i==c&u==h&!f&N&a>-1e4&x==y)longjm\
    p(z,1); S=b; _!N|f&&(a>M||!f&a==M&&1&rand()\
    )){ _!f){ _ k){ c=i; h=u; y=x; } } else _ \
    L-a<N){ n; e=~e; u[l]=j; x[l]=r; return\
     a; } M=a; } } x[l]=r; u[l]=j; n; } }
    typedef int G; char J [ 78 ], O [ ]
    =   "HRQAMS#-smaqrh[UTZYTU[|TBA("
    "$#(ABT|ba`gg`ab8>GK[_`fFDZXEYR"         "L\t####"
    "##B#A#@#G#F#E#D#K\t\3Zlv#tjm"         "\3J#tjm\3Pwb"
    "ofnbwf\3Joofdbo\3)&`&`.&`&`"         "#+&g*\t"; G y,
    c,h,e,S,*s,l[149]; jmp_buf z         ; G main(G L,G f,
    G N,G k){ G u=99,p,q,r,j,i,x         ,t,a,b=S,d,M=-1e9
    ; char *n; if( *l){ e=~e; Z       u >21){ q= l[--u]^e;
    _!-- q){ _!l[p=e?u-10:u+10]){   I(p,)_ e?u>80   & !l[p
    -=10]:u<39&!l[p+=10])I(p,)} _ l[p=e?u-11:9+u]   )I(p,)
    else _ u-1==S>>6){ l[u-1]=0; I(p,l[u-1]=-2^e);  } _ l[
    p=e?u-9:11+u])I(p,)else _ S>>6==1+u){ l[1+u]=0; I(p,l
    [1+u]=e^-2); } } _!--q){ n=O+41; Z++n<50+O)I(u+80-*n,
    )} _ 0<q&4>q){  n=q==2?53+O:O+49; Z++n<O+(q!=1)*4+54
    ){ p=u; do I(p-=*n-80,)Z!p[l]); } } _ 4==q){ n=49+O
     ; Z++n<O+58)I(u-*n+80,)_ e&!(S&24)|!e&!(S&3)   &&
     !l[u-2]&!l[u-1]&!l[u-3]&&o(u)&o(u-1)){ l[u-1]= 4
      ^e; l[u-4]=0; I(u-2,l[u-1]=0; l[u-4]=e^4); } _
      e&!(S&40)|!e&!(S&5)   &&!l[u+1]&!l[2+u]&&o(u)&
       o(1+u)){ l[u+1]=e^4; l[3+u]=0;   I(u+2,l[1+u
       ]=0; l[u+3]=4^e); } } } e=~e;   return M; }
        Z h<130){l[h]=-(21>h|98<h|2       >(h+1 )%
        10); O[h++]^=3; } n=O +14;       s=20+l; Z
         ++s<29+l){ 10[s]=1; 70[s]=~    ( * s = *
          n++ -+84); 60 [ s] =-2; } Z  n=J){ puts
           (58+O); u=19; Z++u<100){ H(32)_!( u%10
           ))H(32)H(O[7+l[u]])_(9+u)%10>7){ H(58
            -u/10)H(32)_ u&1)puts(n=J); } } puts
             (O+58); _-1e4 >v , 1)){ e=~e; puts
              (O+(v,0)> 1e4?e?90:82:96)); break
               ; } _ 1<L&e) { d=v,2+L); printf
                (O+114,h%10+64,58-h/10,y%10+64
                 ,58 -y/10,d); } else{ putchar
                  (62 ) ; h= (95 & F-44; c=l[h
                    +=(56-F *10]; y=(95&F-44; y
                       +=(56-F*10; Z 10!=(u=(95
                        &F)){ c=5; Z--c>1&&u!=c
                          [O]); c=e^c-7; } } _!
                             setjmp(z)){ v+1,1);
                                   puts(   106+
                                    O); }   } Z
                                     10!=
                                      F; }
    
  • #11 20935756
    sundayman
    Poziom 26  
    Mój pierwszy komputer to było ZX81 z 1kB ramu. Przy czym ten 1 kB był na wszystko - łącznie z pamięcią obrazu. Pisząc grę miało się do dyspozycji kilkaset bajtów. I to nieduże kilkaset.

    Dziś w mcu w sterowniku, który robię mam 256kB na sam program. I muszę się pilnować żeby nie przesadzić a czasem nawet eliminować już zbyteczne rzeczy, bo się nie mieści :)
REKLAMA