Teensy 3.1 – dzień III – wydajność

Dziś wielkie starcie. W prawym narożniku Arduino Leonardo. Zawodnik o wadze 16 MHz. W lewym Teensy 3.1. Jego zegar to 96 MHz.

Sprawdźmy ile razy bardziej wydajne jest Teensy 3.1 w porównaniu do jednej z najbardziej popularnych płytek Arduino Leonardo.

Dzielenie liczb liczb jest jedną z najbardziej czasochłonnych operacji dla procesora. Procesor ARM Cortex M4 w Teensy 3.1 ma specjalny rozkaz, dzięki któremu dzieli liczby sprzętowo.
Procesor AVR w Arduino Leonardo nie ma dzielenia sprzętowego i musi zastępować je kilkoma innymi operacjami.

To program który porówna wydajności w dzieleniu:

unsigned long sum;

void setup()
{
  while (!Serial);
  Serial.begin(9600);
}

void loop()
{
  Serial.println(F("Start"));
  unsigned long timeBegin = millis();
  for (int a=0; a<10000; a++)
  {
    for (int b=1; b<100; b++)
    {
      sum += a / b;
    }
  }
  
  unsigned long processTime = millis() - timeBegin;
  Serial.println(F("End"));
  Serial.print(F("Czas obliczen: "));
  Serial.println(processTime);
}

Program dzieli przez siebie milion liczb i mierzy czas tej operacji.

  • Arduino Leonardo zajęło to 14,978 s
  • Teensy 3.1 zajęło to 0,127 s

Czyli w dzieleniu Teensy okazało się 118 razy szybsze.

Kolejny test jest dość zabawny. Polega na uruchomieniu na obydwu płytkach tego samego emulatora procesora 6502. Na emulatorze uruchomiłem język EhBASIC. Cały kod pochodzi z wątku na forum Arduino, o którym niedawno pisałem.

Uznałem, że emulator to dobre środowisko by przetestować różnorodne operacje. W końcu to taki duży skomplikowany program, który robi dużo obliczeń, dużo komunikuje się z pamięcią Flash i RAM. Będzie dobrze odzwierciedlał ogólną wydajność procesora.

W języku BASIC napisałem prosty program zliczający od 0 do 10000.

Czas jego działania dla każdej płytki to:

  • Arduino Leonardo: 57,22 s
  • Teensy 3.1: 9,8 s

W tym teście Teensy nie ma już takiej ogromnej przewagi. Ale nadal jest prawie 6 razy szybsze.

Na koniec zostawiłem najmocniejszy test. Wziąłem algorytmy do obliczeń GPS ze starego projektu licznika rowerowego. Jest w nich dużo liczb zmiennoprzecinkowych (float) i masa różnych funkcji trygonometrycznych typu sin, cos, tan, atan2.

W oparciu o to, napisałem program, który oblicza trasę 36km z Płocka na zachód. Co 0.0001 stopień szerokości geograficznej.

float lat = 52.512204;
float lon = 19.675606;
float lonTo = 19.143456;

float oldLat = lat;
float oldLon = lon;

float angle;
float distance;

float getDistance(float latf, float lonf, float latt, float lont)
{
  float distance = acos(cos(latf)*cos(lonf)*cos(latt)*cos(lont)+cos(latf)*sin(lonf)*cos(latt)*sin(lont)+sin(latf)*sin(latt)) * 6378.137;
  return distance;
}

float lonTox(float lon)
{
  float x = (lon + PI) / (2 * PI) * 2.0;
  return x;
}

float latToy(float lat)
{
  float y = (1.0 - log(tan(lat) + (1 / cos(lat))) / PI);
  return y;
}

float getAngle(float latf, float lonf, float latt, float lont)
{
  float xf = lonTox(lonf);
  float yf = latToy(latf);
  float xt = lonTox(lont);
  float yt = latToy(latt);
  
  float x = xt - xf;
  float y = yt - yf;
  float angle = atan2(y, x);
  return angle;
}

void setup()
{
  while (!Serial);
  Serial.begin(9600);
}

void loop()
{
  Serial.println(F("Start"));
  unsigned long timeBegin = millis();
  for (float a=lon; a>lonTo; a-=0.0001)
  {
    distance += getDistance(oldLat, oldLon, lat, a);
    angle = getAngle(oldLat, oldLon, lat, a);
    oldLat = lat;
    oldLon = a;
  }
  
  unsigned long processTime = millis() - timeBegin;
  Serial.println(F("End"));
  Serial.print(F("Czas obliczen: "));
  Serial.println(processTime);
  
  Serial.print(F("Odleglosc: "));
  Serial.println(distance);
  Serial.print(F("Kat: "));
  Serial.println(angle);
  distance = 0.0;
  angle = 0.0;
}

Program pokazuje jak dobrze sprawdza się Teensy w autopilotach i innych podobnych systemach związanych z nawigacją, położeniem i obliczeniami z przecinkiem.

  • Arduino Leonardo policzyło trasę w 10,242 s
  • Teensy 3.1 policzyło trasę w 4,215 s

W takich obliczeniach Teensy okazało się 2,6 raza wydajniejsze od Arduino Leonardo.

BTW. Jeśli interesujecie się nawigacją to w tym teście macie gotowe funkcje do obsługi GPS.

Funkcja “getDistance” oblicza odległość między dwoma punktami geograficznymi. Argumenty to długość i szerokość geograficzna punktu początkowego i długość i szerokość geograficzna punktu końcowego. Argumenty podajemy w radianach, a nie stopniach – co mi się zapomniało ;-).

Funkcja “getAngle” oblicza kąt pod jakim jest punkt geograficzny od nas względem zachodu. Jej argumenty są takie same jak “getDistance”.

Funkcje “latToy” i “lonTox” zamieniają długość i szerokość geograficzną na współrzędne punktu  x, y na płaskiej mapie.

Teensy 3.1 siłą rzeczy jest wydajniejsze od Arduino Leonardo. Dzięki testom dowiedziałeś się jak bardzo i w jakich operacjach radzi sobie najlepiej.

Pozytywnie zaskoczyło mnie dziś to, że programy pod Teensy obsługują pamięć Flash tak jak w Arduino. Można używać F() do tekstów. Autor Teensy przeniósł nawet bibliotekę “/avr/pgmspace.h”, żeby biblioteki Arduino obsługujące Flash działały na Teensy bez modyfikacji.

sprae

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.