Goto page Previous 1, 2, 3, 4 Next
Piotr Wyderski
Guest
Sun Sep 26, 2004 5:45 pm
Jan Dubiec wrote:
Quote:
A możesz powiedzieć jak to jest w przypadku gcc? Bo np. ja lubię
stosować goto do wyjścia z kilku zagnieżdzonych pętli - IMO kod jest
wtedy bardziej czytelny.
Ja rowniez uzywam goto do tego celu.

BTW, ja chyba
niezbyt fortunnie sformulowalem ten fragment o goto -- to
nie jest jakis demon, ktory z gory uniemozliwia prostym
algorytmom rozwiazywanie rownan przeplywu danych. Ta
instrukcja (jako chyba jedyna w C) _moze_ prowadzic do
takich problemow, ale nie musi. W wiekszosci praktycznych
przypadkow (jak m.in. Twoj, jesli myslimy o tym samym)
nie prowadzi do nieredukowalnosci grafu. Natomiast na
pytanie o GCC trzeba odpowiedziec pytaniem "w ktorej wersji?"
Ogolnie wykorzystuje sie raczej algorytmy standardowe,
bo wszystkie programy bez goto oraz wiekszosc z goto
ma grafy redukowalne (tj. szczegolnie latwe w analizie).
Quote:
No i jak wygląda sprawa w przypadku break oraz continue?
Te instrukcje zawsze prowadza do grafow redukowalnych,
wiec mozna je stosowac bez obaw, ze sie optymalizatorowi
utrudnia prace.
Quote:
W sensie szybkości wykonywania programu pewnie będzie działał dobrze
ale IMO bolączką w przypadku uC i C jest zużycie RAM-u którego ilość w
uC jest dziwnie mała w stosunku do kilobajtów FLASH-a i megaherców
zegara. I tutaj jest pole do popisu dla assemblerowych rzeźbiarzy.

.
Wlasnie o tym napisalem -- wiele kompilatorow optymalizujacych
na mikrokontrolerki wywodzi sie z duzych maszyn, gdzie wspomniane
50 bajtow w te czy w tamta strone nie ma znaczenia, wiec kompilatory
nie zawracaja sobie glowy analiza zywotnosci zmiennych statycznych.
Czlowiek wiele rzeczy sie domysla, kompilator potrafi tylko tyle, ile
go nauczono (czyt. algorytmow analizy zaimplementowano). To
oczywiscie nie znaczy, ze nie da sie takich rzeczy robic automatycznie,
tylko, ze zdecydowana wiekszosc kompilatorow tego nie potrafi.
Wlasciwie jedyne miejsce, gdzie kompilatory dbaja o wykorzystanie
pamieci, to budowanie rekordow aktywacji (czasem sie to niescisle
nazywa ramka stosu).
Quote:
Człowiek wykona taką optymalizację bez trudu, ale z tego co widzę,
kompilatory radzą sobie z tym gorzej.
W ogolnym przypadku problem jest nierozstrzygalny i nawet czlowiek
sobie nie poradzi. Zadanie sprowadza sie do udzielenia odpowiedzi na
pytanie "czy w programie istnieje sciezka przeplwu sterowania, w ktorej
program czyta dane po ich zapisie", a dowodzi sie, ze nie istnieje
algorytm potrafiacy te odpowiedz znalezc. W szczegolnych
przypadkach to sie da zrobic, tylko tu z kolei nastepuje zderzenie
z praktyka:
a) taka analiza trwa zazwyczaj co najmniej kilka minut -- jestes
w stanie tyle poczekac przy kazdej kompilacji?
b) analizator jest znacznie bardziej skomplikowany (zarowno
koncepcyjnie, jak i w wielkosci kodu) od calej reszty kompilatora
razem wzietej;
c) kto to napisze i bedzie wspierac? O ile napisanie kompilatora C
jest wlasciwie trywialne, kompilatora optymalizujacego trudne/bardzo
trudne, to takiego analizatora pasjonat spod znaku GNU nie opracuje
za przyslowiowego chinskiego boga. :-)
Quote:
Niektóre, np. kompilator Microchipa, wprowadzają rozszerzenia
standardu C (tzn. magiczne słówka kluczowe) którymi koder może
dać kompilatorowi wskazówki.
I to jest wlasciwie jedyne sensowne rozwiazanie. Jesli kompilator
zostanie z zewnatrz poinformowany o rzeczach, ktorych w ogolnosci
nie mozna (nawet teoretycznie!) wydedukowac, to reszta juz jest
prosta.
Quote:
O jakiej organizacji mówisz?
Mowie o planowaniu ukladu danych w pamieci w ogole, wiec
i o takiej, o ktorej wspomniales rowniez.
Pozdrawiam
Piotr Wyderski
point
Guest
Sun Sep 26, 2004 6:08 pm
ziel wrote:
Quote:
całość ma 7 bajtów
7 instrukcji.
Quote:
całość wykonuje się w 142 cyklach.
Pytanie.
jakim cudem kod zajmujący 316 bajtów wykonuje się w 178 cyklach?
Pewnie instrukcje są w słowach dłuższych niż 8 bitów (jak w PIC).
Przykład skompilowany pod PIC18 w hitech c:
32 bajty ROM/0 RAM/185 cykli (pętla for ma 10 instrukcji).
Jak procek ma sprzętowe mnożenie to kod z kompilatora C i napisany
ręcznie będzie praktycznie taki sam:)
--
point
ziel
Guest
Sun Sep 26, 2004 7:33 pm
On Behalf Of point
Quote:
Pewnie instrukcje są w słowach dłuższych niż 8 bitów (jak w PIC).
Oczywiście, popełniłem błąd.
Każda instrukcja tu użyta składa się z jednego word'a czyli ma dwa bajty.
Na początku należało by dołożyć jeszcze ustawienie stosu i portu.
W sumie zwiększy się o jakieś 10 bajtów. Tfu... 5 word.
Quote:
Przykład skompilowany pod PIC18 w hitech c:
32 bajty ROM/0 RAM/185 cykli (pętla for ma 10 instrukcji).
Zadziwiające.
Nigdy bym nie podejrzewał PIC'ów o tak krótki kod
i tak sprawne wykonywanie programu.
Na marginesie. PIC'ów nie lubię ze względu na małą ilość
instrukcji (a co za tym idzie dłuższego pisania
programu w asm). Że nie wspomnę o przełączaniu banków.
Ale do rzeczy.
CodeVisionAVR ver. 1.24.3b
CodeVisionAVR dla 90S8515
kod: 96 word czyli 192 bajty
cykle: 1608
CodeVisionAVR dla mega128 (ma sprzętowe mnożenie)
kod: 96 word czyli tyle samo - autor nie popisał się
cykle: 1608 dokładnie to samo.
Czego powyższe dowodzi ?
Że to autor kompilatora decyduje o wyższości jednego języka
nad drugim?
Chyba tak.
Z lenistwa ( a może z obawy, że inni pokażą dużo lepsze)
nie chce mi się wymyślać teraz jakiegoś algorytmu dla mnożenia
programowego, a upublicznienie kodów generowanych przez BASCOM
i CV jest naruszeniem warunków licencji.
Quote:
Jak procek ma sprzętowe mnożenie to kod z kompilatora C i napisany
ręcznie będzie praktycznie taki sam:)
Nigdy.
Kod pisany ręcznie dla tak prostych zadań będzie zawsze mniejszy
i szybszy od kodu dowolnego kompilatora języka wyższego rzędu.
pzdr
Artur
PS
Może to nie będzie koniec dyskusji, ale o _ostatecznej_
jakości programu decyduje programista.
Nie język użyty do jego napisania.
Mogę napisać dowolny program w BASCOM który powali
na kolana dowolny kompilator C.
Oczywiście ze wstawkami w asm

.
pzdr
Artur
--
Archiwum grupy:
http://niusy.onet.pl/pl.misc.elektronika
Jan Dubiec
Guest
Sun Sep 26, 2004 8:00 pm
On Sun, 26 Sep 2004 19:05:42 +0200, Bartosz Sarama <qu_asi.mod@wp.pl> wrote:
Quote:
Jan Dubiec napisał(a):
Chodzi mi o takie sytuacje gdy np. dwie funkcje używają np. 50
bajtowych buforów i gdy te funkcje są od siebie wzajemnie niezależne,
to można na te bufory wykorzystać ten sam kawałek RAM-u.
A mógłbyś opisać problem nieco dokładniej? Bo to na razie wygląda na
proste użycie buforów jako zmiennych lokalnych w funkcji.
Nieprecyzyjnie się wyraziłem, ale nie chodzi tu o zmiene lokalne
(czyli alokowane na stosie - a te chyba miałeś na myśli).
Wyobraźmy sobie taką sytuację: są dwie niezależne od siebie funkcje które
potrzebują tymczasowych buforów. Nie chcemy dynamicznie alokować pamięci
bo to jest kosztowne. Nie chcemy też używać zmiennych automatycznych bo
cienko u nas ze stosem. W związku z tym definiujemy te bufory jako statyczne
zmienne globalne:
static int buf1[100];
static char buf2[50];
int fun1(int x)
{
int i;
for (i = 0; i < 100; ++i)
buf1[i] = x;
return buf1[0];
}
int fun2(char x)
{
int i;
for (i = 0; i < 50; ++i)
buf2[i] = x;
return (int) buf2[0];
}
W takim przypadku kompilator (np. gcc) zarezerwuje na oba bufory w obszarze
danych niezainicjalizowanych, tj. sekcji .bss, 100*sizeof(int)+50*sizeof(char)
bajtów. A przecież wystarczyłoby tylko 100*sizeof(int) ponieważ fun1()
i fun2() są od siebie niezależne. Jak widać, dla człowieka to jest oczywiste,
ale dla kompilatora już nie. Co prawda możnaby to obejść np. przy pomocy
unii lub wskaźników ale chyba nie po to zdecywaliśmy się na użycie języka
wysokiego poziomy aby zaciemniać kod. A poza tym takie obejście to i tak
byłoby działanie podjęte przez człowieka a nie kompilator. :-)
Regards,
/J.D.
--
Jan Dubiec, jdx#slackware.pl, mobile: +48 506 790442
Głęboka wiara wymaga płytkiego rozumu i nikłej wiedzy.
Thomek
Guest
Sun Sep 26, 2004 8:53 pm
Quote:
Nie chcemy też używać zmiennych automatycznych bo
cienko u nas ze stosem. W związku z tym definiujemy te bufory jako
statyczne
zmienne globalne:
static int buf1[100];
static char buf2[50];
int fun1(int x)
{
int i;
for (i = 0; i < 100; ++i)
buf1[i] = x;
return buf1[0];
}
int fun2(char x)
{
int i;
for (i = 0; i < 50; ++i)
buf2[i] = x;
return (int) buf2[0];
}
W takim przypadku kompilator (np. gcc) zarezerwuje na oba bufory w
obszarze
danych niezainicjalizowanych, tj. sekcji .bss,
100*sizeof(int)+50*sizeof(char)
bajtów. A przecież wystarczyłoby tylko 100*sizeof(int) ponieważ fun1()
i fun2() są od siebie niezależne. Jak widać, dla człowieka to jest
oczywiste,
ale dla kompilatora już nie.
Poza absurdalnoscia podanych funkcji nalezy zauwazyc ze jest cos takiego jak
przerwania
ktore sa nieprzewidywalne ;]. A jezeli przerwanie poprzez jakies zaleznosci
wywola funkcje fun2
w trakcie przerwanej fun1. Jak widac kompilator nie moze tego przewidziec ok
moze ale w tym wypadku
poprostu lepiej uzyc wskaznikow do wspolnej pamieci i samemu zajac sie tym
problemem.
Pozdrawiam
Thomek
Piotr Wyderski
Guest
Sun Sep 26, 2004 8:59 pm
Jan Dubiec wrote:
Quote:
Wyobraźmy sobie taką sytuację: są dwie niezależne od siebie funkcje które
potrzebują tymczasowych buforów. Nie chcemy dynamicznie alokować pamięci
bo to jest kosztowne. Nie chcemy też używać zmiennych automatycznych bo
cienko u nas ze stosem. W związku z tym definiujemy te bufory jako
statyczne
zmienne globalne:
[ciach] o tym wlasnie przypadku napisalem ponizej. W skrocie: mozna
udowodnic, ze w ogolnym przypadku nie mozna udowodnic [

], ze
zmienna globalna nie bedzie potrzebna innej procedurze w przyszlosci
(rozwaz np. skok posredni przez wskaznik na funkcje...) i tym samym
pozwolic sobie na jej powtorne wykorzystanie. Ten problem obchodzi
sie poprzez przyjecie zalozenia, ze zmienne globalne zyja wiecznie.
Pozdrawiam
Piotr Wyderski
Piotr Wyderski
Guest
Sun Sep 26, 2004 9:03 pm
Jan Dubiec wrote:
A poza tym w C++ mozna sobie przeciazyc operator new,
by zwracal wskaznik na ta "wielokrotnie uzywalna" pamiec,
albo jeszcze lepiej uzyc placement new. Zostaw C, to jest
tak bardzo przestarzaly jezyk programowania, ze az boli. :-)
Pozdrawiam
Piotr Wyderski
Maksymilian Dutka
Guest
Sun Sep 26, 2004 9:34 pm
Użytkownik Krzysztof Rudnik napisał:
Quote:
Maksymilian Dutka wrote:
Program testowy:
--- avr-gcc ---
char I;
for(I=1;I<=20;I++)
{
PORTB=12*I;
}
a probowales
for (I=1; I<=240; I+=12)
Odpuszczasz sobie mnozenie.
Kompilator z optymalizacja sam moze dosc do
podobnych wnioskow.
Krzysiek Rudnik
Po przejrzeniu kodu po deassembleracji okazało się że kompilator C
właśnie tak zrobił, Bascom nie wpadł na ten pomysł
Maksymilian Dutka
Guest
Sun Sep 26, 2004 9:34 pm
Użytkownik mlodedrwale napisał:
Quote:
Maksymilian Dutka wrote:
Wyniki:
WinAVR | Bascom
Ilosc cykli: 178 | 2700
jak to zmierzyć?
Zrobiłem symulację w AvrStudio (pod Win)
Maksymilian Dutka
Guest
Sun Sep 26, 2004 9:40 pm
Użytkownik WJ napisał:
Quote:
Wyniki:
WinAVR | Bascom
Ilosc cykli: 178 | 2700
Rozmiar prog.: 316B | 418B
I co Wy na to?
No, C jest bardziej wydajne od Basic'a. Spróbuj to samo napisać w
assemblerze, a zobaczysz, że wyniki będą jeszcze lepsze

Pozdrawiam
--
WJ
Nie dokładnie, zauważyłem że GCC jest "sprytny" potrafi pominąć operację
które i tak nic nie zmieniają w efekcie działanie programu, oczywiście
dobry programista mający dużo czasu nie będzie pisał "nadmiarowego"
kodu, niestety przeważnie nie ma zbyt dużo czasu na pisanie programu co
za tym idzie na: optymalizację działań matematycznych, doszukiwanie się
pewnych zależności itp.
Maksymilian Dutka
Guest
Sun Sep 26, 2004 9:43 pm
Użytkownik ziel napisał:
Quote:
On Behalf Of Maksymilian Dutka
WinAVR | Bascom
Ilosc cykli: 178 | 2700
Rozmiar prog.: 316B | 418B
I co Wy na to?
Nie pisz bzdur, jak nie wiesz co porównujesz!
To było dla "procesora" 90S2313 (który nie posiada mnożenia).
Marek Dzwonnik
Guest
Sun Sep 26, 2004 9:56 pm
Użytkownik "Maksymilian Dutka" <maxdutka@usunonet.pl> napisał w
wiadomości news:cj7ghp$gua$1@atlantis.news.tpi.pl
Quote:
niestety przeważnie nie ma zbyt dużo czasu na
pisanie programu co za tym idzie na: optymalizację działań
matematycznych, doszukiwanie się pewnych zależności itp.
A do tego na pisanie _obszernych_ komentarzy. (IMHO) ręczna optymalizacja
ma tą szczególną cechę, że po miesiącu za cholerę nie wiadomo co autor miał
na myśli ;-)
--
Marek Dzwonnik, GG: #2061027 - zwykle jako 'niewidoczny'
(Uwaga Gadu-Gadulcowicze: Nie odpowiadam na anonimy.)
Piotr Wyderski
Guest
Sun Sep 26, 2004 10:19 pm
Marek Dzwonnik wrote:
Quote:
(IMHO) ręczna optymalizacja ma tą szczególną cechę, że po
miesiącu za cholerę nie wiadomo co autor miał na myśli
To sie nazywa "Rambo-style programming" -- wpasc,
zrobic swojem odejsc i nigdy do tego nie wracac. :->
Pozdrawiam
Piotr Wyderski
J.F.
Guest
Sun Sep 26, 2004 10:36 pm
On Mon, 27 Sep 2004 00:03:32 +0200, Piotr Wyderski wrote:
Quote:
A poza tym w C++ mozna sobie przeciazyc operator new,
by zwracal wskaznik na ta "wielokrotnie uzywalna" pamiec,
albo jeszcze lepiej uzyc placement new. Zostaw C, to jest
tak bardzo przestarzaly jezyk programowania, ze az boli.
Taa - a program obslugi nowego operatora zajmie 20 KB :-)
J.
J.F.
Guest
Sun Sep 26, 2004 10:36 pm
On Sun, 26 Sep 2004 23:59:06 +0200, Piotr Wyderski wrote:
Quote:
[ciach] o tym wlasnie przypadku napisalem ponizej. W skrocie: mozna
udowodnic, ze w ogolnym przypadku nie mozna udowodnic [

],
W ogolnym. Ale zakladamy ze programista jest rozsadny i nie naduzywa
...
Quote:
ze zmienna globalna nie bedzie potrzebna innej procedurze w przyszlosci
(rozwaz np. skok posredni przez wskaznik na funkcje...) i tym samym
pozwolic sobie na jej powtorne wykorzystanie. Ten problem obchodzi
sie poprzez przyjecie zalozenia, ze zmienne globalne zyja wiecznie.
Ale one chyba tak maja zyc. Szczegolnie w takich malych prockach,
gdzie przerwania sie uzywa.
J.
Goto page Previous 1, 2, 3, 4 Next