• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przyspieszenie kodu

Object Storage Arubacloud
0 głosów
926 wizyt
pytanie zadane 24 lipca 2016 w C i C++ przez Semtex Początkujący (310 p.)
edycja 24 lipca 2016 przez Semtex

Witam. Potrzebuję przyspieszyć rutynę przerwania ponad dwukrotnie (jeśli nie macie wiedzy o niskim poziomie to i tak proszę się nie zniechęcać, rutyna to zwykły void). Timer taktuje z prędkością 2MHz i kod musi wykonać się w ciągu jednego okresu tj poniżej 500ns. Nie mierzyłem dokładnie czasu ale po wynikach wiem, że muszę go przyspieszyć około 2,5x. Rutyna jest dla procesora ATSAM3X8E.

volatile uint32_t *d;
uint32_t dat[200];
long dummy, *p;

d = &dat[0];
p = &dummy;

void TC0_Handler() {
// przyspieszyć
  *p = REG_TC0_SR0; // przeczytanie rejestru 32bity, tylko w celu wyzerowania (dane z rejestru nie są potrzebne)
  *d = REG_PIOC_PDSR; // zapis rejestru 32bity (tylko 9 pierwszych bitów jest potrzebne ale z tego co wiem to całość jest czytana za jednym taktem procka)
  d++; // przesunięcie adresu
  if (d == &dat[199]) // sprawdzenie warunku czy tablica jest cała zapisana
// koniec przyspieszenia
  {
    TC_Stop(TC0, 0);
    NVIC_DisableIRQ(TC0_IRQn);
  }
}

Do przyspieszenia jest fragment pomiędzy komentarzami "przyspieszyć" i "koniec przyspieszenia", resztę chyba opisałem w miarę czytelnie. Z góry dzięki za jakąkolwiek pomoc.

komentarz 24 lipca 2016 przez MetRiko Nałogowiec (37,110 p.)
Może zamiast warunku if(d==&dat[199]) dasz po prostu if(d==dat+199)?
W końcu zapis &dat[199] to tak na prawdę &(*(dat+199)). Niech ktoś mnie poprawi jeżeli się mylę.

4 odpowiedzi

+1 głos
odpowiedź 24 lipca 2016 przez draghan VIP (106,230 p.)

Jeśli piszesz, że procesor, na którym wykonywany jest ten kod, jest taktowany 84MHz, to tych zaledwie kilka instrukcji nie powinno zająć więcej, niż kilka taktów - a więc powinno się to wykonać w akceptowalnym czasie. To takie wstępne domysły, bo nie szukałem listy komend procesora i ich czasu trwania w taktach.

Po pierwsze, jeśli zawsze porównujesz z &dat[199], to utwórz wcześniej wskaźnik na dat[199] i używaj tego wskaźnika w porównaniu. Chyba, że tablica dat jest dynamiczna. Zaoszczędzisz odrobinę czasu na przesuwaniu wskaźnika.

Po drugie, mógłbyś wyjaśnić:

// przeczytanie rejestru 32bity, tylko w celu wyzerowania (dane z rejestru nie są potrzebne)

? Skoro dane nie są potrzebne, to dlaczego je odczytujesz?

Po trzecie - jaki kompilator, jakie flagi kompilacji?

komentarz 24 lipca 2016 przez Semtex Początkujący (310 p.)
Niestety żona teraz włączyła jakiś głupi film i muszę siedzieć i oglądać :D zamiast walczyć. Rejestr SRx po odczytaniu zeruje flagę przerwania, bez tego rutyna wykonywałaby się cały czas zamiast tylko na krawędzi zegara. Wskaźnik na dat [199] ustawiłem już po napisaniu pytania i nie edytowałem posta. Jest jeszcze jedna opcja, mogłem coś zamieszać z zegarem procesora bo trochę się bawiłem rejestrami lub tak jak słusznie radzisz kwestia kompilacji, może IDE tak zamula.
komentarz 24 lipca 2016 przez itcloud Gaduła (3,380 p.)
hahaha, pozdro dla żonki :)
komentarz 24 lipca 2016 przez Semtex Początkujący (310 p.)
Dzięki ;)
komentarz 25 lipca 2016 przez draghan VIP (106,230 p.)
Okej, rozumiem już kwestię konieczności odczytania tego rejestru. Swoją drogą zabawne, że flaga czyszczona jest przy odczycie. Jak dotąd miałem do czynienia z czyszczeniem flag poprzez zapis do rejestrów, względnie do jakiegoś bitu rejestru.

I jak tam Ci idzie walka? Może spróbuj skompilować ten fragment do asma i podziel się wynikiem - zobaczymy co za potworka Ci tam kompilator tworzy.
komentarz 25 lipca 2016 przez Semtex Początkujący (310 p.)
Właśnie poczytałem o kompilowaniu i ładowaniu do arduino, muszę powiedzieć że to nie tak hop-siup jak z .cpp teraz czytam o podstawach asemblera dla ARM i chyba będzie mi prościej napisać te dwie linijki asemblerem niż bawić się z kompilacją po każdej zmianie kodu (a będzie ich trochę). Zapisywanie do rejestrów już ogarnąłem, problem jak zwykle mam z adresowaniem ramu myślę, że jutro to rozkminię.
0 głosów
odpowiedź 24 lipca 2016 przez mbabane Szeryf (79,280 p.)
a czy switch nie bedzie szybszy od if'a?
0 głosów
odpowiedź 24 lipca 2016 przez MichuDev Pasjonat (20,300 p.)
Różne kompilatory dostarczają specjalnych flag optymalizacyjnych np. gcc ma -0x - x zamień na 1,2 lub 3, im więcej tym kod będzie bardziej zoptymalizowany.

Jeżeli myślisz o dużym wzroście wydajności w takim miejscu nie lepiej użyć wstawki assembler'a. W różnych kompilatorach są różne sztuczki do wstawek, ale można w jednolity sposób napisać kod w assemblerze i assemblować go jakimś assembler'em oraz wstawić kod maszynowy.
komentarz 24 lipca 2016 przez Semtex Początkujący (310 p.)
Właśnie myślałem żeby w asemblerze, tylko teraz uczę się C++ i boję się, że przerośnie mnie ogarniać dwa języki równocześnie. Flagi gcc znam (przynajmniej tą o której wspomniałeś -O3), niestety piszę to w Arduino IDE i nie mogłem znaleźć opcji kompilatora. Odpocznę to spróbuję skompilować to z terminala i załadować do AVR-a bez IDE. Dzięki.
komentarz 24 lipca 2016 przez jpacanowski VIP (101,940 p.)
edycja 24 lipca 2016 przez jpacanowski
-O3 nie polecam używać bo nieźle potrafi zamieszać w kodzie. Potrafi tak zoptymalizować kod, że przestaje coś działać, albo program się sypie. Polecam używać góra -O2
0 głosów
odpowiedź 24 lipca 2016 przez Semtex Początkujący (310 p.)
Chyba nic z tego nie będzie, sprawdzałem wasze podpowiedzi i wielkich zmian nie było. Podpiąłem oscyloskop i zmieniłem rutynę na:

{

b=~b; // zmiana bitu na odwrotny

REG_PIOD_ODSR=b; // ustawienie pinu w stan "b" (1/0 na zmianę)

}

Okazało się, że nawet tak mały kod (bez if'a) nie nadąża za zegarem 2MHz. Trochę to dziwne bo w ciemno stawiałem, że 84MHz taktowany procesor sobie poradzi... Niestety opóżnienie z tym kodem jest około 750ns. Jak ktoś chce to mogę w ramach podziękowania za pomoc wkleić ten mój timer z przerwaniem dla "arduino due", ja pewnie się wspomogę zewnętrznym zegarem, wtedy nie musiałbym inkrementować i sprawdzać warunku w rutynie tylko przeczytać rejestr. Dzięki za pomoc i niech to jeszcze powisi może ktoś wytknie jakiś błąd albo jak to napisać w aseblerze.

Podobne pytania

0 głosów
1 odpowiedź 408 wizyt
pytanie zadane 31 grudnia 2016 w C i C++ przez czujek22 Dyskutant (7,670 p.)
0 głosów
1 odpowiedź 133 wizyt
0 głosów
1 odpowiedź 163 wizyt
pytanie zadane 21 stycznia 2022 w C i C++ przez BKantur Nowicjusz (160 p.)

92,619 zapytań

141,468 odpowiedzi

319,791 komentarzy

62,002 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...