Kysymys:
Suorittaako loputon silmukka silmukan () sisällä nopeammin?
Peter Bloomfield
2014-02-21 21:36:19 UTC
view on stackexchange narkive permalink

Kun kirjoitat tyypillistä luonnosta, luotat yleensä siihen, että loop () kutsutaan toistuvasti niin kauan kuin Arduino on käynnissä. loop () -toiminnon sisään ja ulos siirtymisessä on kuitenkin oltava pieni yleiskustannus.

Tämän välttämiseksi voit luultavasti luoda oman äärettömän silmukan, kuten tämä:

  void loop () {while (true) {// tee tavaraa ...}}  

Onko se käyttökelpoinen tapa parantaa suorituskykyä? Aiheuttaako se muita ongelmia, jos loop () ei koskaan palaa?

Kaksi vastused:
#1
+18
Cybergibbons
2014-02-21 22:43:46 UTC
view on stackexchange narkive permalink

ATmega-ytimen koodin osa, joka suorittaa setup () ja loop (), on seuraava:

  #include <Arduino.h>int main (void) {init (); # jos määritetty (USBCON) USBDevice.attach (); # endif setup (); for (;;) {silmukka (); if (serialEventRun) serialEventRun (); } return 0;}  

Melko yksinkertainen, mutta siinä on sarjaEventRun (); vertaa kahta yksinkertaista luonnosta:

  void setup () {} volatile uint8_t x; void loop () {x = 1;}  

ja

  void setup () {} volatile uint8_t x; void loop () {while (true) {x = 1; }}  

X ja volatile on vain sen varmistamiseksi, että sitä ei ole optimoitu.

Tuotetussa ASM: ssä saat erilaisia ​​tuloksia: Comparison of two

Voit nähdä, kun taas (true) suorittaa vain muutaman käskyn taaksepäin rjmp (suhteellinen hyppy), kun taas loop () suorittaa vähennyslaskun, vertailun ja kutsun. Tämä on 4 ohjetta vs. 1 ohje.

ASM: n luomiseen kuten yllä, sinun on käytettävä työkalua nimeltä avr-objdump. Tämä sisältyy avr-gcc: n mukana. Sijainti vaihtelee käyttöjärjestelmän mukaan, joten se on helpoin etsiä nimen mukaan.

avr-objdump voi toimia .hex-tiedostoilla, mutta niistä puuttuu alkuperäinen lähde ja kommentit. Jos olet juuri rakentanut koodin, sinulla on .elf-tiedosto, joka sisältää nämä tiedot. Jälleen näiden tiedostojen sijainti vaihtelee käyttöjärjestelmän mukaan - helpoin tapa löytää ne on ottaa käyttöön yksityiskohtainen kääntäminen asetuksissa ja nähdä, mihin tulostetiedostot tallennetaan.

Suorita komento seuraavasti:

avr-objdump -S output.elf> asm.txt

Ja tarkista tulos tekstieditorissa.

OK, mutta eikö ole syytä kutsua serialEventRun () -funktiota? Mitä varten se on?
Se on osa HardwareSerialin käyttämää toimintoa, etkä ole varma, miksi sitä ei poisteta, kun Serialia ei tarvita.
Olisi hyödyllistä selittää lyhyesti, miten luot ASM-lähdön, jotta ihmiset voivat tarkistaa itsensä.
@Cybergibbons: tä ei koskaan oteta pois, koska se on osa Arduino IDE: n käyttämää tavallista `main.c`. Se ei kuitenkaan tarkoita, että HardwareSerial-kirjasto sisältyy luonnokseesi; Itse asiassa sitä ei sisälly, jos et käytä sitä (siksi `main ()` -funktiossa on ʻif (serialEventRun) `. Jos et käytä HardwareSerial-kirjastoa,` serialEventRun` on tyhjä, joten ei puhelua .
HardwareSerial-kirjasto sisältyy kuitenkin todennäköisesti (voisiko joku vahvistaa sen?), Jos käytät joitain arduino-toimintoja, kuten `` Serial.print () ''. Mitä tässä tilanteessa voi tapahtua, jos `loop ()` -silmukka jatkuu ikuisesti eikä siten koskaan kutsu `` serialEventRun () ''? Pelkään, että Serial ei välttämättä toimi tässä tapauksessa.
Joo, se on osa main.c: tä, kuten on lainattu, mutta odotan sen optimoivan, ellei sitä tarvita, joten mielestäni Serialin osa on aina mukana. Kirjoitan usein koodia, joka ei koskaan palaa silmukasta (), enkä huomaa Serialin ongelmia.
@Cybergibbons, `serialEventRun ()` kutsuu `serialEvent ()` eri sarjaliitännöille. Oletuksena kaikki nämä ovat [tyhjiä toimintoja] (https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/HardwareSerial.cpp), mutta käyttäjä voi [ohittaa ne] ] (http://arduino.cc/en/Tutorial/SerialEvent) tehdä jotain hyödyllistä haluttaessa. Jos et ohita sitä, sitä ei tarvitse kutsua.
#2
+6
asheeshr
2014-02-22 14:11:34 UTC
view on stackexchange narkive permalink

Cybergibbonsin vastaus kuvaa melko hienosti kokoonpanokoodin luomisen ja näiden kahden tekniikan väliset erot. Tämän on tarkoitus olla täydentävä vastaus, jossa tarkastellaan asiaa käytännön erojen suhteen, ts. Kuinka paljon eroa kummallakin lähestymistavalla on suoritusajalla .


Koodimuunnelmat

Tein analyysin, joka sisälsi seuraavat muunnelmat:

  • Basic void loop ( ) (joka käännetään inline käännöksen yhteydessä)
  • Viivoittamaton void loop () (käyttäen __attribute__ (((noinline)) )
  • Silmukka while (1) -toiminnolla (joka optimoidaan)
  • Silmukka optimoimattomalla while (1) -ominaisuudella (lisäämällä __asm__ __volatile __ (""); . Tämä on nop -käsky, joka estää silmukan optimoinnin aiheuttamatta ylimääräisiä volatile -muuttujan yleiskustannuksia)
  • Linjaamaton void -silmukka () , optimoitu while(1)
  • Linjaamaton void loop () optimoimattomalla -välillä(1)

Luonnokset voivat olla fontteja d täällä.

Kokeilu

Suoritin näitä luonnoksia 30 sekunnin ajan ja keräsin siten 300 datapistettä kukin. Jokaisessa silmukassa oli 100 millisekunnin delay -kutsu (jota ilman huonoja asioita tapahtuu).

Tulokset

Sitten laskin kunkin silmukan keskimääräiset suoritusajat, vähennin 100 millisekuntia kustakin ja piirrin sitten tulokset.

http://raw2.github.com/AsheeshR/Arduino-Loop-Analysis/master/Figures/timeplot.png

Päätelmä

  • Optimoimaton while (1) -silmukka void -silmukassa on nopeampi kuin kääntäjän optimoima void loop .
  • Aikaero optimoimattoman koodin ja Arduino-oletusoptimoidun koodin välillä on merkityksetön käytännössä . Sinun on parempi kääntää manuaalisesti käyttämällä avr-gcc ja käyttää omia optimointilippujasi sen sijaan, että riippuisit Arduino IDE: stä auttamaan sinua siinä (jos tarvitset mikrosekunnin optimointeja).

HUOMAUTUS: Todellisilla aika-arvoilla ei ole merkitystä tässä, niiden välinen ero on. ~ 90 mikrosekunnin suoritusaika sisältää kutsun Serial.println , micros ja delay.

NOTE2: Tämä tehtiin käyttämällä Arduino IDE -ohjelmaa ja sen toimittamia oletuskääntäjä-lippuja.

NOTE3: Analyysi (käyrä ja laskelmat) tehtiin käyttämällä R.

Hyvää työtä. Kaaviossa on millisekunteja, ei mikrosekunteja, mutta ei valtava ongelma.
@Cybergibbons Se on melko epätodennäköistä, koska kaikki mittaukset ovat mikrosekunteina, enkä ole vaihtanut asteikkoa missään :)


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...