Odpowiedz 
 
Ocena wątku:
  • 0 Głosów - 0 Średnio
  • 1
  • 2
  • 3
  • 4
  • 5
Porównanie języków programowania
SP5FCS Offline
Adam
*****

Liczba postów: 1,072
Dołączył: 02-02-2009
Post: #1
Porównanie języków programowania
W kilku wątkach trwała dyskusja na temat zalet i wad różnych języków programowania mikroprocesorów. Padało wiele argumentów za i przeciw na podstawie posiadanej wiedzy, doświadczeń oraz preferowanej wygody podczas tworzenia programowania. Takie opisowe porównanie jest bardzo subiektywne i utrudnia rzetelną ocenę efektywności poszczególnych języków.
Zdecydowanie lepszą metodą byłoby wykonanie kilku praktycznych testów i porównanie np. wielkość generowanego kodu oraz czasu jego wykonania. Taka metoda pozwoliłaby np. porównać same języki (assembler, bascom, C), różne kompilatory a nawet porównywać możliwości różnych mikroprocesorów. To kwestia opracowania kilku prostych zadań do wykonania oraz chęci kilku Kolegów znających różne języki programowania oraz procesory.


Assembler AVR
- darmowe środowisko producenta procesorów AVR Studio
- brak gotowej arytmetyki na długich formatach 32, 64bit, float

C w środowisku WinAVR
- darmowy kompilator zintegrowany z AVR Studio
- dostępne formaty i arytmetyka na 64bit oraz float

C w codeVision
- płatne środowisko ~829zł, demo do 4kB kodu
- dostępny format i arytmetyka na float, brak formatu 64biy

Bascom AVR
- płatne środowisko ~478zł, demo do 4kB kodu
- dostępny format i arytmetyka float oraz format 8 bajtowy double

Zadanie testowe TEST_1
Prawie w każdym języku powstało oprogramowanie do obsługi syntezy na AD9951. Ciekawe jak wypadłoby porównanie funkcji obliczającej nastawę dla AD9951, ile kodu i czasu pochłonie taka pozornie prosta funkcja ?

Kod:
Test_1 - obliczenie nastawy dla AD9951
// zmienne globalne w RAM-ie procesora
f_clock= 400000000;  //400MHZ na 4 bajtach
f_vfo   =  20000000;  //   20MHZ na 4 bajtach
FTW                       // nastawa dla DDS-a na 4 bajtach

FTW=2^32*f_vfo/f_clock   // obliczenie nastawy dla DDS-a, wynik w FTW na 4 bajtach

//wynik testu:
   - wielkość kodu w bajtach,
   - ilość taktów procesora od RESET do umieszczenia danych w zmiennej FTW

Zapraszam do udziału w teście, mogę napisać funkcje w assemblerze i C-CodeVision na procesory AVR.

73 Adam
30-03-2012 0:19
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ6OXK Offline
Paweł
****

Liczba postów: 317
Dołączył: 23-06-2010
Post: #2
RE: Porównanie języków programowania
Pomysł ciekawy, ja nawet już jakiś czas temu w innym wątku próbowałem też chciałem coś podobnego zrobić, ale na rozwiązanie problemu odpowiedział niestety tylko jeden z kolegów. Zaproponuje go tutaj również, do testu bo jest on ciekawy. Sam problem jest łatwy, ale może powodować nie lada problem (generować duży kod) w przypadku kodu napisanego w C.

Mam jednak pytanie i sugestię co do samego wyniku testu.
Czy porównujemy wielkość i czas potrzebny do wykonanie test od samego początku kodu (resetu procesora)?

Dlaczego o to pytam, jak wiesz za czym procesor wykona pierwszą linijkę naszego kodu, kompilator w kodzie wynikowym umieszcza tablice skoków przerwań, inicjalizację stosu, zmiennych, pamięci itd.

Czasami różnicę, nawet w tym samym kompilatorze, ale miedzy różnymi procesorami są bardzo duże. Przykładowo tablica przerwań miedzy takim archaicznym 90S2313, a amega162 to ze względu na ilość przerwać, oraz w przypadku atmegi trzy bajtowy rozkaz skoku, wielkość początku kodu kilkakrotnie jest dłuży dla 162.

Proponuję, aby jednak tą cześć kody i pracy procesora pominąć, można ewentualnie wykonać osobne porównanie takiej części kodu.

Proponuje, w przypadku kodu, wykonać najpierw kompilację, tzw. pustego programu, w którym były by zawarte tylko zmienne globalne i tą wartość odjąć o wynikowego kodu już całego rozwiązania testu. Podobnie jeśli chodzi o ilość taktów procesora, najpierw określić ile zajmuję taki prolog, zresetować w debugerze licznik i wykonać symulację dla głownego kodu testu.

PS. Ja będę zgłaszał funkcje napisane w bascom i WinAvr

--= SWL SP6-01-396 =--
(Ten post był ostatnio modyfikowany: 30-03-2012 7:09 przez SQ6OXK.)
30-03-2012 7:09
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP5FCS Offline
Adam
*****

Liczba postów: 1,072
Dołączył: 02-02-2009
Post: #3
RE: Porównanie języków programowania
Pawle, jak najbardziej masz rację co do wielkości kodu startowego dla różnych procesorów oraz kompilatorów. Aby było jednolicie proponuję przyjąć jakiś popularny procesor AVR np. Atmega32. Moim zdanie w teście należy uwzględniać wszystko od adresu 0000h do końca testu, może być jako suma (prolog+test).

Pomijanie wielkości kodu startowego ( tzw. prologu ) oraz czasu jego wykonania nie do końca jest słuszne. Kompilator często umieszcza tam funkcje biblioteczne, procedury optymalizacyjne, inicjuje zasoby procesora, zmienne, stos danych a potem z nich korzysta podczas realizacji głównej części programu. Dlaczego więc mielibyśmy nie uwzględniać takich ułatwień, które kompilator przygotuje sobie do dalszej pracy ?

Drugi powód to możliwości optymalizacyjne kompilatora. Dobry kompilator usunie wszystko z czego nie będzie korzystał w celu redukcji wielkości kodu, słaby zostawi całą dołączoną bibliotekę.

Trzeci powód to możliwości konfiguracyjne kompilatora. Procesor powinien inicjować to co jest wykorzystane w programie a nie to "co mu pasuje". Sam swego czasu pytałeś czy w WinAVR da się zmusić kompilator GCC aby nie omijał wektorów przerwań i umieszczał tam normalny kod programu. Może jakiś kompilator ma taką dyrektywę ?

Algorytm zadania testowego jest prosty jednak formaty danych oraz obliczenia generują wystarczająco duży kod do porównania.
Tak naprawdę chodzi o praktyczne pokazanie różnić pomiędzy językami przy realizacji tego samego algorytmu.

73 Adam
30-03-2012 12:09
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP9RQA Online
Krzysztof
****

Liczba postów: 379
Dołączył: 30-09-2009
Post: #4
RE: Porównanie języków programowania
(30-03-2012 12:09)SP5FCS napisał(a):  Trzeci powód to możliwości konfiguracyjne kompilatora. Procesor powinien inicjować to co jest wykorzystane w programie a nie to "co mu pasuje". Sam swego czasu pytałeś czy w WinAVR da się zmusić kompilator GCC aby nie omijał wektorów przerwań i umieszczał tam normalny kod programu. Może jakiś kompilator ma taką dyrektywę ?

Coś tu można miedzy wierszami się doszukać:

http://www.avrfreaks.net/index.php?name=...50&start=0
http://users.rcn.com/rneswold/avr/c433.html
http://lists.gnu.org/archive/html/avr-ch...00009.html
30-03-2012 12:35
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP5FCS Offline
Adam
*****

Liczba postów: 1,072
Dołączył: 02-02-2009
Post: #5
RE: Porównanie języków programowania
Pierwsze wyniki TEST_1 wykonane w CodeVision są bardzo słabe !!
Cały kod dla procesora ATmega32 zajmuje 890 bajtów, czas wykonania 13752 cykle zegara co przy 16Mhz daje czas około 0,9ms. Czas nie jest krytyczny ale kod jest ogromny.
Niestety CodeVision nie ma typu zmiennej long long int dlatego obliczenia trzeba robić na zmiennych typu float co widać od razu na wielkości kodu i czasie wykonania. Podobny problem wystąpi w Bascomie bo tam chyba też jest max. 4 bajty. Lepiej wygląda to w WinAVR gdzie są dostępne zmienne na 8 bajtach.

Bardzo długi czas był związany z zerowaniem RAMu, po wyłączeniu zerowania oraz rezygnacji z wektorów przerwań zyskujemy na kodzie oraz bardzo dużo na czasie. Zaletą CodeVision jest możliwość ustawienia w konfiguracji ilości wektorów przerwań, u mnie jeden (reset).
Dodatkowy minus obliczeń na zmiennych float i konwersji na long int to wpływ zaokrągleń na wynik:

Powinniśmy uzyskać nastawę: 0x0CCCCCCC a w tej wersji otrzymałem 0x0CCCCCD0, czyli o 4 za dużo.

Obecne wyniki są już bardziej obiecujące:
Kod 786 bajtów, 1395 cykli co daje czas wykonania około 90us Big Grin.

Wersja demo CodeVision do 4kB

Kod:
// Test_1 - obliczanie nastawy dla AD9951
long unsigned int    f_clk=400000000;
long unsigned int    f_vfo=20000000;
long unsigned int    FTW;

void main(void)
{
FTW = (long unsigned int) ((float) 0x100000000*f_vfo/f_clk);
}

73 Adam
31-03-2012 0:26
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP5FCS Offline
Adam
*****

Liczba postów: 1,072
Dołączył: 02-02-2009
Post: #6
RE: Porównanie języków programowania
Kolejne próby pozwoliły delikatnie poprawić wynik. Pliki do własnych prób w załączniku.

Ostateczny wynik uzyskany dla Test_1 w języku C pod CodeVision:
Kod programu : 678 (28+650) bajty
Czas wykonania: 1119 (22+997) cykli zegara
Wynik końcowy: 0x0CCCCCD0, o 4 za dużo co daje częstotliwość VFO o 0,4Hz wyższą niż wymagana, do zaakceptowania !


Załączone pliki
.zip  test_1_cv.zip (Rozmiar: 6.59 KB / Pobrań: 924)

73 Adam
31-03-2012 12:00
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ6OXK Offline
Paweł
****

Liczba postów: 317
Dołączył: 23-06-2010
Post: #7
RE: Porównanie języków programowania
Zacząłem próbować kod w WinAVR zrobić i zauważyłem niezgodność.

Z wykorzystaniem 64 bitowych liczb wynik jest prawidłowy, ale wygenerowany kod miał 4 206 B. Jego wykonanie zajęło 6 210 cykli. Oczywiście przy tych liczbach największy kod generuje dzielenie dwóch 64bit-owych liczb, wykorzystując do tego dużo dodatkowej pamięci.

Identyczny kod jak Adama w WinAVR dał wynik (u mnie jest dłuższy ze względu na przerwania)

Kod: (108+768);
Cykle: (13+742);

Niestety trudno długość kodu w tym przypadku porównywać, bo kompilowany jest bez żadnej optymalizacji (ustawiona na 0). Uruchomienie kompilacja, automatycznie powoduje czę pre-kompilator wyrzuca liczenie tej wartość, gdyż nie jest nigdzie więcej już używana. Jej użycie też nic nie zmienia, bo tedy pre-kompilator po prostu ją sobie wylicza (wszystkie dane są podane) i podstawia gotową wartość.

Dokładność uzyskałem taką samą, wynika to z faktu za małej dokładność zmiennej typu froat. W WinAVR użycie double nic nie zmienia, ale niektóre kompilatory mają ten typ danych dokładniejszy.

Adamie:
1) Sprawdź czy uda Ci się uzyskać dokładniejszy wynik z użyciem Double;
2) Podaj jaki uzyskasz kod po wyłączeniu optymalizacji.

--= SWL SP6-01-396 =--
(Ten post był ostatnio modyfikowany: 31-03-2012 23:36 przez SQ6OXK.)
31-03-2012 21:40
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ8NVF Offline
Bartłomiej
***

Liczba postów: 144
Dołączył: 05-12-2009
Post: #8
RE: Porównanie języków programowania
Dokładniej to jest: ( (float) 0x100000000 * f_vfo/f_clk ) czyli 2^32 jest rzutowane na float. A float w WinAvr był (nie wiem jak jest obecnie w AVR Toolchain od Atmela) reprezentowany na 32 bitach, podobnie jak typ double (podwójnej precyzji). Na 32 bitach można zapisać liczbę > 2^32 tylko z mniejszą dokładnością...Choć w tym przypadku chyba 2^32 jest zapisane bardzo dokładnie w typie float - wynika to akurat z wielokrotności 2.
Moim zdaniem wykorzystywanie 64 bitów na AVR to lekkie nieporozumienie - chyba, że zupełnie nie zależy nam na szybkości.
(Ten post był ostatnio modyfikowany: 31-03-2012 22:54 przez SQ8NVF.)
31-03-2012 22:54
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP5FCS Offline
Adam
*****

Liczba postów: 1,072
Dołączył: 02-02-2009
Post: #9
RE: Porównanie języków programowania
Pawle, warto byłoby zamieścić kod i wyniki dla wersji na zmiennych 64 bitowych jako przestrogę dla "miłośników długich formatów".
Napisz proszę jaki uzyskałeś wynik końcowy ?
Również chętnie rzucę okiem na pliki w wersji WinAVR (nie używam), mogą być HEX, OBJ, ASM. Wynik jest podobny choć czasy pod WinAVR są krótsze ( to pewnie zasługa pre-kompilatora WinAVR ?? ).

W ostatniej mojej wersji pod CodeVision przerzuciłem zmienne do środka głównej funkcji main() co pozwoliło zyskać na kodzie i czasie.

W oczekiwaniu na wersję w Bascomie robię na "piechotę" arytmetykę w AVR_ASM.
To największa wada assemblera, jeśli nie znajdziesz "gotowca" w necie to potrzebne procedury musisz "wyrzeźbić" samodzielnie.

----------------------------------------------------------------------
Odp:
- CodeVision nie ma formatu double ani long long int 64bit;
- w WinAVR format double to to samo co float, na 4 bajtach;
- może przerobić obliczanie FTW na funkcję ?
- koszt obliczeń na formatach 64bit to po prostu "masakra procesora"
- jakieś pomysły aby zmusić WinAVR do kompilacji kodu na formatach float?

73 Adam
31-03-2012 23:21
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ6OXK Offline
Paweł
****

Liczba postów: 317
Dołączył: 23-06-2010
Post: #10
RE: Porównanie języków programowania
Bartku, pomyliłem się, sądziłem że chodziło o użycie 32 bitowych zmiennych, a nie 64-ro. Stad moja wątpliwość.

Float i Double w WinAVR są oczywiście 32 bitowe, co zapewnia dokładność 7-dmiu pierwszych cyfr (dziesiętne).

Ciekawe czy któryś z kompilatorów dla Double, przyjmuje 64 bity.

--------------------------------------------------------------
Adamie,

W przypadku 64-bitowów uzyskałem dokładnie 0x0CCCCCCC, a w przy 32-bitach podbnie jak ty 0x0CCCCCD0


Kod wersji 64-bitowej:
Kod:
#include <stdint.h>
#include <avr/io.h>


int main(void)
{
  uint64_t Fclk=400000000;
  uint64_t Fvfo=20000000;
  uint32_t FTW;
  FTW=(uint32_t)((uint64_t)0x100000000*Fvfo/Fclk);  
  
  return 0;
};

Dodaję również pliki wynikowe, podziel się Adamie opinią o nich.



BASCOM (wer. 2.0.5.0) okazał się jeszcze inny:

Można w nim bez problemu usunąć tablicę przerwań i czyszczenie całej pamięci:

Kod testu wygląda tak:
Kod:
$noinit
$noramclear

$regfile "m32def.dat"
$crystal = 16000000

Const Fclk = 400000000
Const Fvfo = 20000000
Dim Pom As Single
Dim Pom2 As Single
Dim Ftw As Dword

Pom = &H100000000
Pom2 = Fvfo
Pom = Pom * Pom2
Pom2 = Fclk
Pom = Pom / Pom2
Ftw = Pom

End

Kod: 738 (40+698)
Cykle: 1 385 (20+1365) (~87ns)
Wynik: oczywiście 0x0CCCCCD0

BASCOM ma jednak coś o czy pisałem powyżej, czyli obsługę dokładniejszych zmiennych zmiennoprzecinkowych.

Kod z wykorzystanie lepszych zmiennych zmiennoprzecinkowych.
Kod:
$noinit
$noramclear

$regfile "m32def.dat"
$crystal = 16000000

Const Fclk = 400000000
Const Fvfo = 20000000
Dim Pom As Double
Dim Pom2 As Double
Dim Ftw As Dword

Pom = &H100000000
Pom2 = Fvfo
Pom = Pom * Pom2
Pom2 = Fclk
Pom = Pom / Pom2
Ftw = Pom

End

Okazało się że Bascom wygenerował :

Kod: 1 276 (40+1 236)
Cykle: 2 917 (20+2897) - ~182ns
Wynik: 0x0CCCCCCD

W pierwszej chwili wynik mnie zaskoczył, ale jak dokładnie policzyłem wynik dokładny to 214 748 364,8 w zaokrągleniu 214748365 czyli 0x0CCCCCCD.


Załączone pliki
.zip  test_1_wa.zip (Rozmiar: 8.02 KB / Pobrań: 832)

--= SWL SP6-01-396 =--
(Ten post był ostatnio modyfikowany: 01-04-2012 0:54 przez SQ6OXK.)
31-03-2012 23:38
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
Odpowiedz 


Skocz do:


Użytkownicy przeglądający ten wątek: 1 gości