hw brickbench: Benchmark test for NXT and EV3

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

hw brickbench: Benchmark test for NXT and EV3

Post by HaWe »

hey @all,
I wrote a benchmark test including several test functions:
- simple basic integer arithmetics (+,-,*,/),
- real and transcendental float arithmetic functions (sqrt,sin,cos, exp),
- advanced matrix algebra for more-dim array manipulation (matrix product + determinant, built-in or imported)
- randomize alg (low-level bit- and-byte-operations like AND, XOR, SHIFT-left/right)
- quick high-level sort algs (Shellsort, built-in or imported),
- a text-output and a 2D-graphics test for graph + shape + fill computation and lcd output stressing.

Platforms and source codes:

Meanwhile 7 test platforms have been almost finished:

1) NXT + NXC, BCC 3.3.8.11, JH's EFW
2) EV3 + gpp C (CSLite 2009), BCC 3.3.8.11, Lego std FW (i.e., Lego VM running parallely)
3) NXT + nxtOSEK / TOPPERS/ATK C/C++
4) NXT + RobotC 3.62
5) NXT + leJOS 0.9x beta
6) EV3 + leJOS 0.8x alpha
7) EV3 + RobotC 4.x pre-alpha

max execution speed is sought of course, but no buffers are allowed, display output refresh has to be adjusted for max speed (e.g., for nxtOSEK), and measures must be taken to avoid that the compiler optimizes out calculations ((e.g., for "real" C by defining variables as "volatile" ).


########################################################################################################


NXT + NXC:

Code: Select all

// hw brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: NXC, Enhanced Firmware 2013
// Autor: (C) Helmut Wunder 2013
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.08

unsigned long runtime[8];
int a[500], b[500], c[500], t[500];

//--------------------------------------------
// Mersenne Twister
//--------------------------------------------
const int N_MTW = 25;
const int M_MTW = 7;
const unsigned long A_MTW[] = {0, 0x8ebfd028};

unsigned long y_MTW[25];
int i_MTW;
char virgin_MTW=TRUE, new_MTW=FALSE;

void InitMTW() {
  i_MTW = N_MTW+1;
}


unsigned long randM(void) {
  unsigned long r, s, e;
  int k;

  if (virgin_MTW) {virgin_MTW=FALSE; InitMTW(); }

  if (i_MTW >= N_MTW) {
      if ((i_MTW > N_MTW) && !new_MTW) {
         r = 9;
         s = 3402;
         for (k=0 ; k<N_MTW ; ++k) {
           r = 509845221 * r + 3;
           s *= s + 1;
           y_MTW[k] = s + (r >> 10);
         }
      }
      for (k=0 ; k<N_MTW-M_MTW ; ++k)
         y_MTW[k] = y_MTW[k+M_MTW] ^ (y_MTW[k] >> 1) ^ A_MTW[y_MTW[k] & 1];
      for (; k<N_MTW ; ++k)
         y_MTW[k] = y_MTW[k+(M_MTW-N_MTW)] ^ (y_MTW[k] >> 1) ^ A_MTW[y_MTW[k] & 1];
      i_MTW = 0;
  }

  new_MTW=false;
  e = y_MTW[i_MTW++];
  e ^= (e << 7)  & 0x2b5b2500;
  e ^= (e << 15) & 0xdb8b0000;
  e ^= (e >> 16);
  return e;
}

//--------------------------------------------
// Matrix Algebra
//--------------------------------------------

#define ArrayInit2D(array, tmp, init_val, dimx, dimy) { \
  ArrayInit(tmp, init_val, dimy);  \
  ArrayInit(array, tmp, dimx);     \
  ArrayInit(tmp,0,0);              \
}


void MatrixMatrixMult(float A[][], float B[][], float &C[][], int N, int M, int K){
  int i, j, s;                  // matrix A: N x M // B: M x K // C: N x K
  float tmp[];
  ArrayInit2D(C,tmp, 0, N, K);
  for (i=0; i<N; ++i) {
    for (j=0; j<K; ++j) {
       C[i][j]=0;
       for (s=0; s<M; ++s) {
         C[i][j]=C[i][j] + A[i][s]*B[s][j];
      }
    }
  }
}




float MatrixDet1x1(float A[]) {                 // Determinante 1x1
   return ( A[0]);
}


float MatrixDet2x2(float A[][]) {               // Determinante 2x2
   return ( A[0][0]*A[1][1]- A[0][1]*A[1][0] );
}


float MatrixDet3x3(float A[][]) {               // Determinante 3x3
   return (A[0][0]*A[1][1]*A[2][2]
          +A[0][1]*A[1][2]*A[2][0]
          +A[0][2]*A[1][0]*A[2][1]
          -A[0][2]*A[1][1]*A[2][0]
          -A[0][1]*A[1][0]*A[2][2]
          -A[0][0]*A[1][2]*A[2][1]);
}



//--------------------------------------------
// benchmark test procedures
//--------------------------------------------


int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   long s=0;
   for(int x=0;x<10000;++x) {
     s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}



long test_Int_Mult() {

  long s;

  for(int y=0;y<2000;++y) {
    s=1;
    for(int x=1;x<=13;++x) { s*=x;}
    for(int x=13;x>0;--x) { s/=x;}

  }
  return s;
}


float test_float_math() {

  float s=PI;

  for(int y=0;y<5000;++y) {
     s*=sqrt(s);
     s=sin(s);
     s*=cos(10.5*s);
     s=sqrt(s);
     s=exp(s);
  }
  return s;
}


long test_rand_MT(){
  unsigned long s;

  for(int y=0;y<5000;++y) {
     s=randM()%10001;
  }
  return s;
}


float test_matrix_math() {
  float A[2][2], B[2][2], C[2][2];
  float O[3][3], T[3][3];
  unsigned long s;

  for(int x=0;x<250;++x) {

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    B[0][0]=10;  B[0][1]=30;
    B[1][0]=20;  B[1][1]=40;

    MatrixMatrixMult(A,B,C, 2,2,2);

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    MatrixDet2x2(A);

    O[0][0]=1;   O[0][1]=4;  O[0][2]=7;
    O[1][0]=2;   O[1][1]=5;  O[1][2]=8;
    O[2][0]=3;   O[2][1]=6;  O[2][2]=9;

    MatrixDet3x3(O);

  }

  s=(O[0][0]*O[1][1]*O[2][2]);
  return s;
}


long test_Sort(){
  int y;

  for(y=0;y<30;++y) {
    ArraySort(t, a, NA, NA);
    ArraySort(t, b, NA, NA);
    ArraySort(t, c, NA, NA);
  }
  return y;
}



long test_TextOut(){
  unsigned long s;

  for(int y=0;y<20;++y) {
    ClearScreen();
    NumOut(0,56, 0); NumOut(12,56, 1000); TextOut(44,56, "int_Add");
    NumOut(0,48, 1); NumOut(12,48, 1010); TextOut(44,48, "int_Mult");
    NumOut(0,40, 2); NumOut(12,40, 1020); TextOut(44,40, "float_op");
    NumOut(0,32, 3); NumOut(12,32, 1030); TextOut(44,32, "randomize");
    NumOut(0,24, 4); NumOut(12,24, 1040); TextOut(44,24, "matrx_algb");
    NumOut(0,16, 5); NumOut(12,16, 1050); TextOut(44,16, "arr_sort");
    NumOut(0, 8, 6); NumOut(12, 8, 1060); TextOut(44, 8, "displ_txt");
    NumOut(0, 0, 7); NumOut(12, 0, 1070); TextOut(44, 0, "testing...");  Wait(20);
                                                                   // sum=20*20
  }
  return 99;
}


long test_graphics(){
  int x;
  for(int y=0;y<100;++y) {
    ClearScreen();
    CircleOut(50, 40, 10);
    CircleOut(30, 24, 10, DRAW_OPT_FILL_SHAPE);
    LineOut(10, 10, 60, 60);
    LineOut(50, 20, 90, 70);
    RectOut(20, 20, 40, 40);
    RectOut(65, 25, 20, 30, DRAW_OPT_FILL_SHAPE);
    EllipseOut(70, 30, 15, 20);                    Wait(20);
                                                   // sum=20*100
  }
  return x;
}


void displayValues() {
    NumOut(0,56, 0); NumOut(12,56, runtime[0]); TextOut(44,56, "int_Add");
    NumOut(0,48, 1); NumOut(12,48, runtime[1]); TextOut(44,48, "int_Mult");
    NumOut(0,40, 2); NumOut(12,40, runtime[2]); TextOut(44,40, "float_op");
    NumOut(0,32, 3); NumOut(12,32, runtime[3]); TextOut(44,32, "randomize");
    NumOut(0,24, 4); NumOut(12,24, runtime[4]); TextOut(44,24, "matrx_algb");
    NumOut(0,16, 5); NumOut(12,16, runtime[5]); TextOut(44,16, "arr_sort");
    NumOut(0, 8, 6); NumOut(12, 8, runtime[6]); TextOut(44, 8, "displ_txt");
    NumOut(0, 0, 7); NumOut(12, 0, runtime[7]); TextOut(44, 0, "graphics");
}


task main(){

  unsigned long time0, x, y;
  float s;

  TextOut(0,56, "hw brickbench");
  TextOut(0,48, "(C)H.Wunder 2013");
  TextOut(0,32, "initializing...");

  for(int y=0;y<500;++y) {
    a[y]=randM()%30000; b[y]=randM()%30000; c[y]=randM()%30000;
  }

  ClearScreen();

  time0=CurrentTick();
  s=test_Int_Add();
  runtime[0]=CurrentTick()-time0;
  NumOut(0,56, 0); NumOut(12,56, runtime[0]); TextOut(44,56, "int_Add");

  time0=CurrentTick();
  s=test_Int_Mult();
  runtime[1]=CurrentTick()-time0;
  NumOut(0,48, 1); NumOut(12,48, runtime[1]); TextOut(44,48, "int_Mult");

  time0=CurrentTick();
  s=test_float_math();
  runtime[2]=CurrentTick()-time0;
  NumOut(0,40, 2); NumOut(12,40, runtime[2]); TextOut(44,40, "float_op");

  time0=CurrentTick();
  s=test_rand_MT();
  runtime[3]=CurrentTick()-time0;
  NumOut(0,32, 3); NumOut(12,32, runtime[3]); TextOut(44,32, "randomize");

  time0=CurrentTick();
  s=test_matrix_math();
  runtime[4]=CurrentTick()-time0;
  NumOut(0,24, 4); NumOut(12,24, runtime[4]); TextOut(44,24, "matrx_algb");

  time0=CurrentTick();
  s=test_Sort();
  runtime[5]=CurrentTick()-time0;
  NumOut(0,16, 5); NumOut(12,16, runtime[5]); TextOut(44,16, "arr_sort");

  time0=CurrentTick();
  s=test_TextOut();
  runtime[6]=CurrentTick()-time0-(20*20); // minus wait states
  ClearScreen();
  displayValues();

  time0=CurrentTick();
  s=test_graphics();
  runtime[7]=CurrentTick()-time0-(20*100); // minus wait states
  ClearScreen();
  displayValues();

  getchar();

  ClearScreen();
  y=0;
  for(x=0;x<8;++x) {y+= runtime[x];}

  TextOut(0,56, "gesamt ms:"); NumOut(66,56, y);
  TextOut(0,40, "benchmark:"); NumOut(66,40, 50000000/y);

  TextOut(0, 8, "quit: press btn...");

  getchar();

}

########################################################################################################

EV3 + BCC/C

Code: Select all

// hw brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: gpp CSLite C/C++, C-API and BCC by John Hansen
// Autor: (C) Helmut Wunder 2013
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.08.1

#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include "lms2012.h"
#include "ev3_button.h"
#include "ev3_lcd.h"
#include "ev3_constants.h"
#include "ev3_command.h"
#include "ev3_timer.h"
#include "ev3_lcd.h"
#include "ev3_sound.h"
#include "ev3_output.h"


unsigned long runtime[8];

int a[500], b[500], c[500], t[500];


//--------------------------------------------
// Mersenne Twister
//--------------------------------------------

unsigned long randM(void) {
   const int M = 7;
   const unsigned long A[2] = { 0, 0x8ebfd028 };

   static unsigned long y[25];
   static int index = 25+1;

   if (index >= 25) {
     int k;
     if (index > 25) {
        unsigned long r = 9, s = 3402;
        for (k=0 ; k<25 ; ++k) {
          r = 509845221 * r + 3;
          s *= s + 1;
          y[k] = s + (r >> 10);
        }
     }
     for (k=0 ; k<25-M ; ++k)
        y[k] = y[k+M] ^ (y[k] >> 1) ^ A[y[k] & 1];
     for (; k<25 ; ++k)
        y[k] = y[k+(M-25)] ^ (y[k] >> 1) ^ A[y[k] & 1];
     index = 0;
   }

   unsigned long e = y[index++];
   e ^= (e << 7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return e;
}

//--------------------------------------------
// Matrix Algebra
//--------------------------------------------

// matrix * matrix multiplication (matrix product)

void MatrixMatrixMult(int N, int M, int K, double A[][M], double B[][K], double C[][K]){
  int i, j, s;                                       // matrix A: N x M // B: M x K // C: N x K
  for (i=0; i<N; ++i) {
    for (j=0; j<K; ++j) {
       C[i][j]=0;
       for (s=0; s<M; ++s) {
         C[i][j]=C[i][j] + A[i][s]*B[s][j];
      }
    }
  }
}


// matrix determinant

double MatrixDet(int N, double A[N][N])
{
    int i,j,i_count,j_count, count=0;
    double Asub[N-1][N-1], det=0;

    if(N==1) return A[0][0];
    if(N==2) return (A[0][0]*A[1][1] - A[0][1]*A[1][0]);

    for(count=0; count<N; count++)
    {
        i_count=0;
        for(i=1; i<N; i++)
        {
            j_count=0;
            for(j=0; j<N; j++)
            {
                if(j == count) continue;
                Asub[i_count][j_count] = A[i][j];
                j_count++;
            }
            i_count++;
        }
        det += pow(-1, count) * A[0][count] * MatrixDet(N-1,Asub);
    }
    return det;
}


//--------------------------------------------
// shell sort
//--------------------------------------------

void shellsort(int size, int* A)
{
  int i, j, increment;
  int temp;
  increment = size / 2;

  while (increment > 0) {
    for (i = increment; i < size; i++) {
      j = i;
      temp = A[i];
      while ((j >= increment) && (A[j-increment] > temp)) {
        A[j] = A[j - increment];
        j = j - increment;
      }
      A[j] = temp;
    }

    if (increment == 2)
       increment = 1;
    else
       increment = (unsigned int) (increment / 2.2);
  }
}

//--------------------------------------------
// benchmark test procedures
//--------------------------------------------


int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   int x;
   volatile long s=0;
   for(x=0;x<10000;++x) {
     s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}



long test_Int_Mult() {
  int x,y;
  volatile long s;

  for(y=0;y<2000;++y) {
    s=1;
    for(x=1;x<=13;++x) { s*=x;}
    for(x=13;x>0;--x) { s/=x;}

  }
  return s;
}


#define PI  M_PI


float test_float_math() {

  volatile float s=PI;
  int y;

  for(y=0;y<5000;++y) {
     s*=sqrt(s);
     s=sin(s);
     s*=cos(10.5*s);
     s=sqrt(s);
     s=exp(s);
  }
  return s;
}


long test_rand_MT(){
  volatile unsigned long s;
  int y;

  for(y=0;y<5000;++y) {
     s=randM()%10001;
  }
  return s;
}


float test_matrix_math() {
  int x;

  double A[2][2], B[2][2], C[2][2];
  double O[3][3], T[3][3];
  unsigned long s;

  for(x=0;x<250;++x) {

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    B[0][0]=10;  B[0][1]=30;
    B[1][0]=20;  B[1][1]=40;

    MatrixMatrixMult(2,2,2, A,B,C);

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    MatrixDet(2, A);

    O[0][0]=1;   O[0][1]=4;  O[0][2]=7;
    O[1][0]=2;   O[1][1]=5;  O[1][2]=8;
    O[2][0]=3;   O[2][1]=6;  O[2][2]=9;

    MatrixDet(3, O);

  }

  s=(O[0][0]*O[1][1]*O[2][2]);
  return s;
}



// for array copy using void *memcpy(void *dest, const void *src, size_t n);

long test_Sort(){
  unsigned long s;
  int y, i;
  int t[500];

  for(y=0;y<30;++y) {
    memcpy(t, a, sizeof(a));
    shellsort(500, t);
    
    memcpy(t, a, sizeof(b));
    shellsort(500, t);
    
    memcpy(t, a, sizeof(c));
    shellsort(500, t);
  }

  return y;
}



long test_TextOut(){

  int  y;
  char buf[120];

  for(y=0;y<20;++y) {
    LcdClearDisplay();
    sprintf (buf, "%3d %4d  int_Add",    0, 1000); LcdText(1, 0,10, buf);
    sprintf (buf, "%3d %4d  int_Mult",   0, 1010); LcdText(1, 0,20, buf);
    sprintf (buf, "%3d %4d  float_op",   0, 1020); LcdText(1, 0,30, buf);
    sprintf (buf, "%3d %4d  randomize",  0, 1030); LcdText(1, 0,40, buf);
    sprintf (buf, "%3d %4d  matrx_algb", 0, 1040); LcdText(1, 0,50, buf);
    sprintf (buf, "%3d %4d  arr_sort",   0, 1050); LcdText(1, 0,60, buf);
    sprintf (buf, "%3d %4d  displ_txt",  0, 1060); LcdText(1, 0,70, buf);
    sprintf (buf, "%3d %4d  testing...", 0, 1070); LcdText(1, 0,80, buf);

  }
  return 99;
}


long test_graphics(){
  int x, y;
  for(y=0;y<100;++y) {

    LcdClearDisplay();

    CircleOut(50, 40, 10);
    CircleOutEx(30, 24, 10, DRAW_OPT_FILL_SHAPE);
    LineOut(10, 10, 60, 60);
    LineOut(50, 20, 90, 70);
    RectOut(20, 20, 40, 40);
    RectOutEx(65, 25, 20, 30, DRAW_OPT_FILL_SHAPE);
    EllipseOut(70, 30, 15, 20);

  }
  return x;
}


inline void displayValues() {

  char buf[120];

    sprintf (buf, "%3d %4d  int_Add",    0, runtime[0]); LcdText(1, 0,10, buf);
    sprintf (buf, "%3d %4d  int_Mult",   1, runtime[1]); LcdText(1, 0,20, buf);
    sprintf (buf, "%3d %4d  float_op",   2, runtime[2]); LcdText(1, 0,30, buf);
    sprintf (buf, "%3d %4d  randomize",  3, runtime[3]); LcdText(1, 0,40, buf);
    sprintf (buf, "%3d %4d  matrx_algb", 4, runtime[4]); LcdText(1, 0,50, buf);
    sprintf (buf, "%3d %4d  arr_sort",   5, runtime[5]); LcdText(1, 0,60, buf);
    sprintf (buf, "%3d %4d  displ_txt",  6, runtime[6]); LcdText(1, 0,70, buf);
    sprintf (buf, "%3d %4d  graphics",   7, runtime[7]); LcdText(1, 0,80, buf);
}


void Handler(int sig)               /// ???
{
  //printf("handler %d\n", sig);    /// ???
}

int main(){

  unsigned long time0, x, y;
  float s;
  char  buf[120];
  int   i;

  SetTimerCallback(ti1sec, &Handler); /// ???

  ClearTimer(0);
  ClearTimerMS(0);

  ButtonLedInit();
  LcdInit();
  LcdClean();


  LcdText(1, 0,10, "hw brickbench");
  LcdText(1, 0,20, "(C)H.Wunder 2013");
  LcdText(1, 0,50, "initializing...");

  for(y=0;y<500;++y) {
    a[y]=randM()%30000; b[y]=randM()%30000; c[y]=randM()%30000;
  }


  LcdClearDisplay();

  time0= TimerMS(0);;
  s=test_Int_Add();
  runtime[0]=TimerMS(0)-time0;
  sprintf (buf, "%3d %4d  int_Add",    0, runtime[0]); LcdText(1, 0,10, buf);

  time0=TimerMS(0);
  s=test_Int_Mult();
  runtime[1]=TimerMS(0)-time0;
  sprintf (buf, "%3d %4d  int_Mult",   0, runtime[1]); LcdText(1, 0,20, buf);

  time0=TimerMS(0);
  s=test_float_math();
  runtime[2]=TimerMS(0)-time0;
  sprintf (buf, "%3d %4d  float_op",   0, runtime[2]); LcdText(1, 0,30, buf);

  time0=TimerMS(0);
  s=test_rand_MT();
  runtime[3]=TimerMS(0)-time0;
  sprintf (buf, "%3d %4d  randomize",  0, runtime[3]); LcdText(1, 0,40, buf);

  time0=TimerMS(0);
  s=test_matrix_math();
  runtime[4]=TimerMS(0)-time0;
  sprintf (buf, "%3d %4d  matrx_algb", 0, runtime[4]); LcdText(1, 0,50, buf);


  time0=TimerMS(0);
  s=test_Sort();
  runtime[5]=TimerMS(0)-time0;
  sprintf (buf, "%3d %4d  arr_sort",   0, runtime[5]); LcdText(1, 0,60, buf);

  time0=TimerMS(0);
  s=test_TextOut();
  runtime[6]=TimerMS(0)-time0;
  LcdClearDisplay();
  displayValues();

  time0=TimerMS(0);
  s=test_graphics();
  runtime[7]=TimerMS(0)-time0;
  LcdClearDisplay();
  displayValues();


  LcdText(1, 0,100, "cont: press btn < LEFT...");

  while(ButtonWaitForAnyPress(100) != BUTTON_ID_LEFT);

  LcdClearDisplay();
  y=0;
  for(x=0;x<8;++x) {y+= runtime[x];}

  sprintf (buf, "gesamt ms: %d ", y);           LcdText(1, 0,10, buf);
  sprintf (buf, "benchmark: %d ", 50000000/y ); LcdText(1, 0,20, buf);

  LcdText(1, 0,40, "quit: press btn < LEFT...");   // <<<<<<<<< no reaction, just for left + ESC !

  while(ButtonWaitForAnyPress(100) != BUTTON_ID_LEFT);

  LcdExit();
  ButtonLedExit();
  return 1;

}

########################################################################################################


NXT + nxtOSEK:

Code: Select all

// hw brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: nxtOSEK TOPPERS/ATK C/C++
// Autor: (C) Helmut Wunder 2013
// Ported to nxtOSEK by Martin Aumair
// http://roboticsaumair.jimdo.com/
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.08

extern "C" {
#include "../../../toppers_osek/include/kernel.h"
#include "kernel_id.h"
#include "../../../ecrobot/c/ecrobot_interface.h"
#include "../../../lejos_nxj/src/nxtvm/platform/nxt/mytypes.h"
}

#include "../../../NXtpandedLib/src/LcdDrawer.hpp"

#include "../../../../GNUARM/arm-elf/sys-include/math.h"
//#include "../../../../GNUARM/arm-elf/sys-include/stdio.h"

DeclareTask(TaskMain);

/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////OSEK HOOKS/IRS///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

extern "C" {

// nxtOSEK hook to be invoked from an ISR in category 2
void user_1ms_isr_type2(void) { }

// hooks
void ecrobot_device_initialize(void);
void ecrobot_device_terminate(void);

bool btnhit() {
   return (ecrobot_is_RUN_button_pressed() || ecrobot_is_ENTER_button_pressed());
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////BENCHMARK FUNCTIONS////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

using namespace nxpl; // NXtpandedLib

int a[500], b[500], c[500];
NLcd lcd;

//--------------------------------------------
// Mersenne Twister
//--------------------------------------------

unsigned long randM(void) {
   const int M = 7;
   const unsigned long A[2] = { 0, 0x8ebfd028 };

   static unsigned long y[25];
   static int index = 25 + 1;

   if (index >= 25) {
      int k;
      if (index > 25) {
         unsigned long r = 9, s = 3402;
         for (k = 0; k < 25; ++k) {
            r = 509845221 * r + 3;
            s *= s + 1;
            y[k] = s + (r >> 10);
         }
      }
      for (k = 0; k < 25 - M; ++k)
         y[k] = y[k + M] ^ (y[k] >> 1) ^ A[y[k] & 1];
      for (; k < 25; ++k)
         y[k] = y[k + (M - 25)] ^ (y[k] >> 1) ^ A[y[k] & 1];
      index = 0;
   }

   unsigned long e = y[index++];
   e ^= (e << 7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return e;
}


void MatrixMatrixMult(int N, int M, int K, float A[][2], float B[][2], float C[][2]) {
   int i, j, s;
   for (i = 0; i < N; ++i) {
      for (j = 0; j < K; ++j) {
         C[i][j] = 0;
         for (s = 0; s < M; ++s) {
            C[i][j] = C[i][j] + A[i][s] * B[s][j];
         }
      }
   }
}



// no VLA!
float MatrixDet(int N, float A[]) {
   int i, j, i_count, j_count, count = 0;
   float Asub[N - 1][N - 1], det = 0;

   if (N == 1)
      return *A;
   if (N == 2)
      return ((*A) * (*(A+1+1*N)) - (*(A+1*N)) * (*(A+1)));

   for (count = 0; count < N; count++) {
      i_count = 0;
      for (i = 1; i < N; i++) {
         j_count = 0;
         for (j = 0; j < N; j++) {
            if (j == count)
               continue;
            Asub[i_count][j_count] = *(A+i+j*N);
            j_count++;
         }
         i_count++;
      }
      det += pow(-1, count) * A[0+count*N] * MatrixDet(N - 1, &Asub[0][0]);
   }
   return det;
}


//--------------------------------------------
// shell sort
//--------------------------------------------

void shellsort(int size, int* A)
{
  int i, j, increment;
  int temp;
  increment = size / 2;

  while (increment > 0) {
    for (i = increment; i < size; i++) {
      j = i;
      temp = A[i];
      while ((j >= increment) && (A[j-increment] > temp)) {
        A[j] = A[j - increment];
        j = j - increment;
      }
      A[j] = temp;
    }

    if (increment == 2)
       increment = 1;
    else
       increment = (unsigned int) (increment / 2.2);
  }
}


//--------------------------------------------
// benchmark test procedures
//--------------------------------------------

int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   int x;
   volatile long s=0;
   for(x=0;x<10000;++x) {
     s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}






long test_Int_Mult() {
  int x,y;
  volatile long s;

  for(y=0;y<2000;++y) {
    s=1;
    for(x=1;x<=13;++x) { s*=x;}
    for(x=13;x>0;--x) { s/=x;}

  }
  return s;
}



float test_float_math() {
   float s = M_PI;
   int y;

   for (y = 0; y < 5000; ++y) {
      s *= sqrt(s);
      s = sin(s);
      s *= cos(10.5 * s);
      s = sqrt(s);
      s = exp(s);
   }
   return s;
}


long test_rand_MT() {
   volatile unsigned long s;
   int y;

   for (y = 0; y < 5000; ++y) {
      s = randM() % 10001;
   }
   return s;
}

float test_matrix_math() {
   int x;

   float A[2][2], B[2][2], C[2][2];
   float O[3][3], T[3][3];
   unsigned long s;

   for (x = 0; x < 250; ++x) {

      A[0][0] = 1;
      A[0][1] = 3;
      A[1][0] = 2;
      A[1][1] = 4;

      B[0][0] = 10;
      B[0][1] = 30;
      B[1][0] = 20;
      B[1][1] = 40;

      MatrixMatrixMult(2, 2, 2, A, B, C);

      A[0][0] = 1;
      A[0][1] = 3;
      A[1][0] = 2;
      A[1][1] = 4;

      MatrixDet(2, &A[0][0]);

      O[0][0] = 1;
      O[0][1] = 4;
      O[0][2] = 7;
      O[1][0] = 2;
      O[1][1] = 5;
      O[1][2] = 8;
      O[2][0] = 3;
      O[2][1] = 6;
      O[2][2] = 9;

      MatrixDet(3, &O[0][0]);

   }

   s = (O[0][0] * O[1][1] * O[2][2]);
   return s;
}


long test_Sort(){
  unsigned long s;
  int y, i;
  int t[500];

  for(y=0;y<30;++y) {
    for(i=0; i<500;++i) {t[i]=a[i];}
    shellsort(500, t);
    for(i=0; i<500;++i) {t[i]=b[i];}
    shellsort(500, t);
    for(i=0; i<500;++i) {t[i]=c[i];}
    shellsort(500, t);
  }
  return y;
}


// helper functions for output
// normally with cout our sprintf but I think in a benchmark we take the fastest method
void NumOut(int x, int y, int num, U32 places) {
   display_goto_xy(x, y);
   display_int(num, places);
}

void TextOut(int x, int y, const char *str) {
   display_goto_xy(x, y);
   display_string(str);
}

long test_TextOut() {
   int y;

   for (y = 0; y < 20; ++y) {
      display_clear(0);

      // x,y value is line not pixel! nxtOSEK use fast dma update in chars,lines!
      NumOut(0,0, 0, 1); NumOut(2,0, 1000, 4); TextOut(8,0, "int_Add");
      NumOut(0,1, 1, 1); NumOut(2,1, 1010, 4); TextOut(8,1, "int_Mult");
      NumOut(0,2, 2, 1); NumOut(2,2, 1020, 4); TextOut(8,2, "float_op");
      NumOut(0,3, 3, 1); NumOut(2,3, 1030, 4); TextOut(8,3, "rand_array");
      NumOut(0,4, 4, 1); NumOut(2,4, 1040, 4); TextOut(8,4, "matrx_algb");
      NumOut(0,5, 5, 1); NumOut(2,5, 1050, 4); TextOut(8,5, "arr_sort");
      NumOut(0,6, 6, 1); NumOut(2,6, 1060, 4); TextOut(8,6, "displ_txt");
      NumOut(0,7, 7, 1); NumOut(2,7, 1070, 4); TextOut(8,7, "testing...");
      display_update();  // not really good because we can update hardware only every 16 ms
   }
   return 99;
}


long test_graphics() {
   int x = 0;
   for (int y = 0; y < 100; ++y) {
      display_clear(0);

      // no official functions, its my actual project: NXtpandedLib

      drawCircle(lcd, NPoint(50, 40), 10);
      drawCircleFilled(lcd, NPoint(30, 24), 10);
      drawLine(lcd, NPoint(10, 10), NPoint(60, 60));
      drawLine(lcd, NPoint(50, 20), NPoint(90, 70));
      drawRectangle(lcd, NPixelBox(NPoint(20, 20), 40, 40));
      drawRectangleFilled(lcd, NPixelBox(NPoint(65, 25), 20, 30));
      drawEllipse(lcd, NPoint(70, 30), 15, 20);

      display_update(); // not really good because we can update hardware only every 16 ms
   }
   return x;
}



U32 runtime[8];

void displayValues() {
   display_clear(0);

   NumOut(0,0, 0, 1); NumOut(2,0, (int)runtime[0], 5); TextOut(8,0, "int_Add");
   NumOut(0,1, 1, 1); NumOut(2,1, (int)runtime[1], 5); TextOut(8,1, "int_Mult");
   NumOut(0,2, 2, 1); NumOut(2,2, (int)runtime[2], 5); TextOut(8,2, "float_op");
   NumOut(0,3, 3, 1); NumOut(2,3, (int)runtime[3], 5); TextOut(8,3, "rand_array");
   NumOut(0,4, 4, 1); NumOut(2,4, (int)runtime[4], 5); TextOut(8,4, "matrx_algb");
   NumOut(0,5, 5, 1); NumOut(2,5, (int)runtime[5], 5); TextOut(8,5, "arr_sort");
   NumOut(0,6, 6, 1); NumOut(2,6, (int)runtime[6], 5); TextOut(8,6, "displ_txt");
   NumOut(0,7, 7, 1); NumOut(2,7, (int)runtime[7], 5); TextOut(8,7, "grafics");
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////TASKS ///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////


TASK(TaskMain) {
   //test_graphics();
   //display_update();


   unsigned long time0, x, y;
   float s;

   display_clear(1);

   TextOut(0, 0, "hw brickbench");
   TextOut(0, 1, "(C)H.Wunder 2013");
   TextOut(0, 3, "nxtOSEK port:");
   TextOut(0, 4, "Martin Aumair");
   TextOut(0, 5, "initializing...");
   display_update();
   systick_wait_ms(3000);

   for (y = 0; y < 500; ++y) {
      a[y] = randM();
      b[y] = randM();
      c[y] = randM();
   }

   TextOut(0, 6, "done .. go!");
   display_update();
   systick_wait_ms(2000);
   display_clear(1);

   time0 = systick_get_ms();
   s = test_Int_Add();
   runtime[0] = systick_get_ms() - time0;
   NumOut(0,0, 0, 1); NumOut(2,0, (int)runtime[0], 5); TextOut(8,0, "int_Add");
   display_update();

   time0 = systick_get_ms();
   s = test_Int_Mult();
   runtime[1] = systick_get_ms() - time0;
   NumOut(0,1, 1, 1); NumOut(2,1, (int)runtime[1], 5); TextOut(8,1, "int_Mult");
   display_update();

   time0 = systick_get_ms();
   s = test_float_math();
   runtime[2] = systick_get_ms() - time0;
   NumOut(0,2, 2, 1); NumOut(2,2, (int)runtime[2], 5); TextOut(8,2, "float_op");
   display_update();

   time0 = systick_get_ms();
   s = test_rand_MT();
   runtime[3] = systick_get_ms() - time0;
   NumOut(0,3, 3, 1); NumOut(2,3, (int)runtime[3], 5); TextOut(8,3, "rand_array");
   display_update();

   systick_wait_ms(1500);

   time0 = systick_get_ms();
   s = test_matrix_math();
   runtime[4] = systick_get_ms() - time0;
   NumOut(0,4, 4, 1); NumOut(2,4, (int)runtime[4], 5); TextOut(8,4, "matrx_algb");
   display_update();

   systick_wait_ms(1500);

   time0 = systick_get_ms();
   s = test_Sort();
   runtime[5] = systick_get_ms() - time0;
   NumOut(0,5, 5, 1); NumOut(2,5, (int)runtime[5], 5); TextOut(8,5, "arr_sort");
   display_update();

   time0 = systick_get_ms();
   s = test_TextOut();
   runtime[6] = systick_get_ms() - time0;
   display_update();


   time0 = systick_get_ms();
   s = test_graphics();
   runtime[7] = systick_get_ms() - time0;

   displayValues();

   while (! btnhit() );  //  <<<<< wait for btnpress

   display_clear(1);
   y = 0;
   for (x = 0; x < 8; ++x) {
      y += runtime[x];
   }

   TextOut(0,0, "sum ms:");    NumOut(8,0, y, 7);
   TextOut(0,1, "benchmark:"); NumOut(8,1, 50000000/y, 7);

   systick_wait_ms(1000);
   while (! btnhit() );  //  <<<<< wait for btnpress

   TerminateTask();
}

}


########################################################################################################

NXT + RobotC 3.62

Code: Select all

// hw brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: ROBOTC 3.62 for NXT
// Autor: (C) Helmut Wunder 2013
// Ported to ROBOTC by Xander Soldaat
// http://botbench.com
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.08alpha


/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////BENCHMARK FUNCTIONS////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

int a[500], b[500], c[500];
unsigned long runtime[8];

//--------------------------------------------
// Mersenne Twister
//--------------------------------------------

// just for this specific implementation:
// always starting with the same seed at either run => so always identical PRN series !

unsigned long randM(void) {
   const int M = 7;
   const unsigned long A[2] = { 0, 0x8ebfd028 };

   static unsigned long y[25];
   static int index = 25 + 1;

   if (index >= 25) {
      int k;
      if (index > 25) {
         unsigned long r = 9, s = 3402;
         for (k = 0; k < 25; ++k) {
            r = 509845221 * r + 3;
            s *= s + 1;
            y[k] = s + (r >> 10);
         }
      }
      for (k = 0; k < 25 - M; ++k)
         y[k] = y[k + M] ^ (y[k] >> 1) ^ A[y[k] & 1];
      for (; k < 25; ++k)
         y[k] = y[k + (M - 25)] ^ (y[k] >> 1) ^ A[y[k] & 1];
      index = 0;
   }

   unsigned long e = y[index++];
   e ^= (e << 7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return e;
}

// A[Ra x Ca] * B[Rb x Cb] = C[Ra x Cb]
// N = Ra
// M = Ca, Rb
// K = Cb
void MatrixMatrixMult(int N, int M, int K, float *A, float *B, float *C) {
   int i, j, s;
   for (i = 0; i < N; ++i) {
      for (j = 0; j < K; ++j) {
         C[i*K+j] = 0;
         for (s = 0; s < M; ++s) {
            C[i*K+j] = C[i*K+j] + A[i*N+s] * B[s*M+j];
         }
      }
   }
}



//float MatrixDet1x1(float *A) {                 // Determinante 1x1
//   return ( A[0]);
//}


float MatrixDet2x2(float *A) {               // Determinante 2x2
   return ( A[0*2+0]*A[1*2+1]- A[0*2+1]*A[1*2+0] );
}


float MatrixDet3x3(float *A) {               // Determinante 3x3
   return (A[0*3+0]*A[1*3+1]*A[2*3+2]
          +A[0*3+1]*A[1*3+2]*A[2*3+0]
          +A[0*3+2]*A[1*3+0]*A[2*3+1]
          -A[0*3+2]*A[1*3+1]*A[2*3+0]
          -A[0*3+1]*A[1*3+0]*A[2*3+2]
          -A[0*3+0]*A[1*3+2]*A[2*3+1]);
}


//--------------------------------------------
// shell sort
//--------------------------------------------
void shellsort(int size, int *A)
{
   int mid = 0;
   for(int m = size/2 ; m > 0; m /= 2)
   {
     for(int j = m; j < size; j++)
     {
       for(int i = j - m; i >= 0; i -= m)
       {
         if(A[i + m] >= A[i])
           break;
         else
         {
           mid = A[i];
           A[i] = A[i + m];
           A[i + m] = mid;
         }
       }
     }
   }
}





//--------------------------------------------
// benchmark test procedures
//--------------------------------------------

int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   int x;
   volatile long s=0;
   for(x=0;x<10000;++x) {
      s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}



long test_Int_Mult() {
  int x,y;
  volatile long s;
  for(y=0;y<2000;++y) {
    s=1;
    for(x=1;x<=13;++x) { s*=x;}
    for(x=13;x>0;--x) { s/=x;}
  }
  return s;
}


float test_float_math() {
   float s = PI;
   int y;

   for (y = 0; y < 5000; ++y) {
      s *= sqrt(s);
      s = sin(s);
      s *= cos(10.5 * s);
      s = sqrt(s);
      s = exp(s);
   }
   return s;
}


long test_rand_MT() {
   volatile unsigned long s;
   int y;

   for (y = 0; y < 5000; ++y) {
      s = randM() % 10001;
   }
   return s;
}

float test_matrix_math() {
   int x;

   float A[2][2], B[2][2], C[2][2];
   float O[3][3]; //, T[3][3];
   unsigned long s;

   for (x = 0; x < 250; ++x) {

      A[0][0] = 1;
      A[0][1] = 3;
      A[1][0] = 2;
      A[1][1] = 4;

      B[0][0] = 10;
      B[0][1] = 30;
      B[1][0] = 20;
      B[1][1] = 40;

      MatrixMatrixMult(2, 2, 2, A, B, C);

      A[0][0] = 1;
      A[0][1] = 3;
      A[1][0] = 2;
      A[1][1] = 4;

      MatrixDet2x2(&A[0][0]);

      O[0][0] = 1;
      O[0][1] = 4;
      O[0][2] = 7;
      O[1][0] = 2;
      O[1][1] = 5;
      O[1][2] = 8;
      O[2][0] = 3;
      O[2][1] = 6;
      O[2][2] = 9;

      MatrixDet3x3(&O[0][0]);

   }

   s = (O[0][0] * O[1][1] * O[2][2]);
   return s;
}


long test_Sort(){
  unsigned long s;
  int y, i;
  int t[500];

  for(y=0;y<30;++y) {
    for(i=0; i<500;++i) {t[i]=a[i];}
    shellsort(500, t);
    for(i=0; i<500;++i) {t[i]=b[i];}
    shellsort(500, t);
    for(i=0; i<500;++i) {t[i]=c[i];}
    shellsort(500, t);
  }

  return y;
}

long test_TextOut() {
   int y;

   for (y = 0; y < 20; ++y) {
      eraseDisplay();

      nxtDisplayTextLine(0, "0, %5d, int_Add", 1000);
      nxtDisplayTextLine(1, "1, %5d, int_Mult", 1010);
      nxtDisplayTextLine(2, "2, %5d, float_op", 1020);
      nxtDisplayTextLine(3, "3, %5d, rand_array", 1030);
      nxtDisplayTextLine(4, "4, %5d, matrx_algb", 1040);
      nxtDisplayTextLine(5, "5, %5d, arr_sort", 1050);
      nxtDisplayTextLine(6, "6, %5d, displ_txt", 1060);
      nxtDisplayTextLine(7, "7, %5d, testing...", 1070);
   }
   return 99;
}


long test_graphics() {
   int x = 0;
   for (int y = 0; y < 100; ++y) {
      eraseDisplay();

      // ROBOTC does not have a draw circle equivalent
      //Drawer::drawCircle(lcd, 50, 40, 10, DrawOpt::draw());
      nxtDrawEllipse(50, 40, 60, 30);

      //Drawer::drawCircleFilled(lcd, 30, 24, 10, DrawOpt::draw());
      nxtFillEllipse(30, 24, 40, 14);

      //Drawer::drawLine(lcd, 10, 10, 60, 60, DrawOpt::draw());
      nxtDrawLine(10, 10, 60, 60);

      //Drawer::drawLine(lcd, 50, 20, 90, 70, DrawOpt::draw());
      nxtDrawLine(50, 20, 90, 70);

      //Drawer::drawRectangle(lcd, 20, 20, 40, 40, DrawOpt::draw());
      nxtDrawRect(20, 20, 40, 40);

      //Drawer::drawRectangleFilled(lcd, 65, 25, 20, 30, DrawOpt::draw());
      nxtFillRect(65, 25, 20, 30);

      //Drawer::drawEllipse(lcd, 70, 30, 15, 20, DrawOpt::draw());
      nxtDrawEllipse(70, 30, 15, 20);
   }
   return x;
}





void displayValues() {
   eraseDisplay();

   nxtDisplayTextLine(0, "0, %5d, int_Add", runtime[0]);
   nxtDisplayTextLine(1, "1, %5d, int_Mult", runtime[1]);
   nxtDisplayTextLine(2, "2, %5d, float_op", runtime[2]);
   nxtDisplayTextLine(3, "3, %5d, rand_array", runtime[3]);
   nxtDisplayTextLine(4, "4, %5d, matrx_algb", runtime[4]);
   nxtDisplayTextLine(5, "5, %5d, arr_sort", runtime[5]);
   nxtDisplayTextLine(6, "6, %5d, displ_txt", runtime[6]);
   nxtDisplayTextLine(7, "7, %5d, graphics", runtime[7]);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////TASKS ///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////


task main {
   unsigned long time0, x, y;
   float s;

   eraseDisplay();

   nxtDisplayTextLine(0, "HaWe_Bench");
   nxtDisplayTextLine(1, "(C)H.Wunder 2013");
   nxtDisplayTextLine(3, "ROBOTC port:");
   nxtDisplayTextLine(4, "Xander Soldaat");
   nxtDisplayTextLine(5, "initializing...");

   //wait1Msec(3000);

   for (y = 0; y < 500; ++y) {
      a[y] = randM();
      b[y] = randM();
      c[y] = randM();
   }

   nxtDisplayTextLine(6, "done .. go!");
   wait1Msec(2000);
   eraseDisplay();

   time0 = nSysTime;
   s = test_Int_Add();
   runtime[0] = nSysTime - time0;
   nxtDisplayTextLine(0, "1, %5d, int_Add", runtime[0]);

   time0 = nSysTime;
   s = test_Int_Mult();
   runtime[1] = nSysTime - time0;
   nxtDisplayTextLine(1, "1, %5d, int_Mult", runtime[1]);

   time0 = nSysTime;
   s = test_float_math();
   runtime[2] = nSysTime - time0;
   nxtDisplayTextLine(2, "2, %5d, float_op", runtime[2]);

   time0 = nSysTime;
   s = test_rand_MT();
   runtime[3] = nSysTime - time0;
   nxtDisplayTextLine(3, "3, %5d, rand_array", runtime[3]);

   time0 = nSysTime;
   s = test_matrix_math();
   runtime[4] = nSysTime - time0;
   nxtDisplayTextLine(4, "4, %5d, matrx_algb", runtime[4]);

   time0 = nSysTime;
   s = test_Sort();
   runtime[5] = nSysTime - time0;
   nxtDisplayTextLine(5, "5, %5d, arr_sort", runtime[5]);

   time0 = nSysTime;
   s = test_TextOut();
   runtime[6] = nSysTime - time0;

   time0 = nSysTime;
   s = test_graphics();
   runtime[7] = nSysTime - time0;

   displayValues();
   
   
   while (nNxtButtonPressed == kNoButton) ;
   
   
   eraseDisplay();
   y = 0;
   for (x = 0; x < 8; ++x) {
      y += runtime[x];
   }

   nxtDisplayTextLine(0, "sum ms: %d", y);
   nxtDisplayTextLine(1, "benchmark: %d", 50000000/y);
   while (true) EndTimeSlice();
}
########################################################################################################

Results (Version 1.08)

Results: wrote:

Code: Select all

hw brickbench test (time in ms)  NXT       NXT      NXT        NXT           EV3       EV3        EV3
progr.language, API              NXC     RobotC    leJOS    Toppers C/C++  BCC C/C++  leJOS      RobotC             
Firmware / vers.             JH's EFW      3.6     0.9.1ß   nxtOSEK BIOS*) LegoFW**)  0.8.0a    4.x pre-a   
==========================================================================================================
0 integer add/subtr             3353      1561       727        29            3          4       336  
1 integer multiply/division     6441      1150       463       182           13         11       589  
2 float operations              1716       413      2543       320           50         45       226  
3 Mersenne Tw. PRNG (&,^,>>,<<) 5372      1838        73        55            4          7      1204  
----------------------------------------------------------------------------------------------------------
4 matrix algebra (prod/determ.) 3356       585        68        39           10         60       325  
5 int array sort [500]           332     95879     18756       491          113        139     20932  
----------------------------------------------------------------------------------------------------------
6 display text                   781        32        26        17           28        218      ? ++ ?
7 display graphics               384        95     11480       182           51        371      ? ++ ?
==========================================================================================================
time                          21,735   101,553    35,117     1,362          272        855      ? ++ ?
benchmark score                2,300      ,492     1,423    36,711      183,823     58,479      ? -- ?
notes:
source codes for RobotC (fixed versions for 3.6/NXT and 4.0/EV3) and leJOS (NXT and EV3) see below !
?) some benchmarks partially missing
*) nxtOSEK graphic libs: https://github.com/martin-au/NXtpandedL ... Drawer.hpp
**) Lego EV3-G virtual machine running simultaneously!
[/size]
Last edited by HaWe on 15 May 2014, 16:36, edited 24 times in total.
holler
Posts: 23
Joined: 21 Oct 2013, 19:43

Re: hw brickbench: Benchmark test for NXT and EV3

Post by holler »

doc-helmut wrote:Meanwhile also the RobotC benchmark is finished, and there were surprises in many ways: 1st, the sort algorithm (Shellsort) has by far the worst performance of all tests and ruins the overall benchmark; a faster sort algorithm surely would be appreciated. Furthermore, most basic calculations are somewhere in between NXC and nxtOSEK, in most cases 3 or 4 times faster than NXC, but nevertheless about int and float it seems to be the same issue like for NXC. For RobotC it was an additional surprise that C-like arithmetical notation like, e.g., s+=c instead of s=s+c also leads to big additional speed performance (up to about 50% IIRC), just like it is known for "real" C.

So until now the biggest astonishment to me is the wide range of the array sort test performances compared to pure mathematical calculation speed on each single test platform.
Just use qsort() or qsort_r() instead of shellsort. You might have a look a some sort algorithm comparisons which likely would explain those differences you see.

Btw, I wonder what you mean by commercial use. Usually I just refuse to touch such source (or even look at such), because most lawyers are able to interpret almost anything as "commercial use".

Alexander Holler
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: hw brickbench: Benchmark test for NXT and EV3

Post by HaWe »

For BCC/C I indeed first tried qsort of the gpp libs but it was slower than my "own" shellsort.
For NXC John Hansen implemented shellsort anyway (on fw level, == ArraySort - pls CMIIW) , RobotC has no sort alg implemented at all.
For different implementations (e.g. for Java, NxOS or Toppers C) qsort of course could be an option, just try it out and take the fastest alg!

Commercial use to my interpretation is just if someone sells this, advertises his product with my benchmark results compared to different products and/or earns money with this code. In this case please just consult me by a mail before.

Which hardware of software platform is of your interest?
holler
Posts: 23
Joined: 21 Oct 2013, 19:43

Re: hw brickbench: Benchmark test for NXT and EV3

Post by holler »

doc-helmut wrote:Which hardware of software platform is of your interest?
Sorry, I have no interest at all.
I just wondered about that header and would suggest the use of one of the proved open source licences like BSD, (L)GPL or one of those Creative Commons licences. That would save a lot of time and questions as they are widely known.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: hw brickbench: Benchmark test for NXT and EV3

Post by HaWe »

I have no interest in that licence stuff and if you have no interest in the benchmarks then I'm curious why you post at all - or are you just trolling?
holler
Posts: 23
Joined: 21 Oct 2013, 19:43

Re: hw brickbench: Benchmark test for NXT and EV3

Post by holler »

No I did want to help you with your sorting experience. Sorry for that, will not try such again.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: hw brickbench: Benchmark test for NXT and EV3

Post by HaWe »

Your proposal about qsort vs. Shellsort was reasonable, and I explained why I took this and not the other:
- Shellsort is already implemented in NXC on fw level
- Shellsort is faster in BCC/C
- similar it's for nxtOSEK/C, so it mimics the BCC/C code
- no sort alg at all is implemented in RobotC fw, so Xander's code was meant to mimic the BCC/C code, too
now almost the same sort alg is used for either platform what's good to compare one to each other.

But the sort alg is no end in itself, it's a task among different ones used for benchmarking different platforms.
But about this underlying thing you wrote " I have no interest at all."
Well, ok, but then why grousing about stupid licence issues - that's why I suspected you're just trolling.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: hw brickbench: Benchmark test for NXT and EV3

Post by HaWe »

update -
now also first benchmark results are availabe for
NXT - leJOS
EV3 - leJOS
EV3 - RobotC
(look at the chart in the thread-opening post;
currently tests still partly incomplete and untested, as partially no published code yet (but should be coming soon, according to Xander Soldaat (RobotC) and Andy Shaw (leJOS) )

Thanks again to everyone who participated and contributed to the overview and transcodings, especially many thanks to Martin, Xander and (gloomy-) Andy for their contributions porting my code to nxtOSEK, RobotC, and Java/leJOS.

To my knowledge it is the world's very first time that various Mindstorms programming platforms can be reliably check-founded and compared by adequate, suitable, and valid software tests (admittedly always considering that no test ever may or will be perfect for all purposes of course) !

8-)


Discussion:

As it was predictable, the "real" C/C++ executables are by far the fastest machines. In view of the fact that the EV3 has the 6x cpu clock speed of the NXT, the performance of nxtOSEK executables is almost proportional to the EV3 gpp executables, and the NXT+nxtOSEK is overall about 20 times faster than the bytecode interpreter of NXT+NXC.
But one also has to consider that the EV3 always must carry around the load of the simultaneously running Lego VM which of course consumes precious cpu power...

For nxtOSEK now the published results are based on the updated 1.08 benchmark source like all the others. The benchmarks have been achieved on basis of the nxtOSEK BIOS (ROM+RAM), the runtime results of the hybrid LegoFW + nxtOSEK fw bootloader are about 20% slower, as Martin reported earlier.
The external graphic lib by Martin Aumair has been linked to.

For NXC you may recognize that the firmware is supposed to calculate always by float values: integer arithmetics don't bring a speed advantage compared to floats, just opposite to "real" C. NXC has got the slowest arithmetical and algebraic calculation speed of all test platforms so far, undoubtedly a tribute to the Lego-FW-compatibility and the NBC/NXC piggyback system, but surprisingly it got an incredible quick array sort performance!

Meanwhile also the RobotC benchmark is finished, and there were surprises in many ways: 1st, the sort algorithm (Shellsort) has by far the worst performance of all tests and ruins the overall benchmark; a faster sort algorithm surely would be appreciated. Furthermore, most basic calculations are somewhere in between NXC and nxtOSEK, in most cases 3 or 4 times faster than NXC, but nevertheless about int and float it seems to be the same thing like for NXC. For RobotC it was an additional surprise that C-like arithmetical notation like, e.g., s+=c instead of s=s+c also leads to big additional speed performance (up to about 50% IIRC), just like it is known for "real" C.

Additionally highly surprising and impressive is the extremely quick execution speed of the leJOS VM for the EV3 which almost reaches the native C compiler results (code still missing but coming soon as Andy promised ;) ).

So finally significant and noteworthy is the wide range of the array operation performances compared to pure mathematical calculation speed on each single test platform.
Just a differently weighting of the sort benchmarks would surely not be adapted to this issue but might probably lead to an investigation of it's reasons and of possible fixes and enhancements.


Outlook:

for a new 1.1 benchmark release, the following modifications could make sence:

Code: Select all

integer add/subtr                x4
integer multiply/division        x2
Mersenne bit-shift               x3

Matrix algebra:                  x3
array sort: sizes [10]x5, [100]x2, [500]x1
dickswan
Posts: 1
Joined: 20 Apr 2014, 22:06

Re: hw brickbench: Benchmark test for NXT and EV3

Post by dickswan »

These benchmarks are interesting. It would be great if the LeJOS source code could also be added. It's posted for many of the other solutions.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: hw brickbench: Benchmark test for NXT and EV3

Post by HaWe »

yes, I agree, I'm expecting them to be posted by (gloomy-) Andy, too - hopefully soon...
the benchmark results for RobotC 4.0 and Java have been published by the authors Xander Soldaat and Andy Shaw on facebook, 14 April 2015 ff, of course I can not vouch for the accuracy:
https://www.facebook.com/groups/legomin ... eam_ref=21
Andy Shaw wrote:Here are the results for the NXT:
int_Add 727
int_Mult 463
float_op 2543
randomize 447
matrx_algb 675
arr_sort 18756
text 26
graphics 11480
total ms: 35117
benchmark: 1423
The above is leJOS 0.9.1beta

and for the EV3
int_Add 4
int_Mult 11
float_op 45
randomize 7
matrx_algb 60
arr_sort 139
text 218
graphics 371
total ms: 855
benchmark: 58479
The above is leJOS EV3 0.8.0-aplha. The LCD results are poor, but not a high priority for us.

Note that in Java all of the math functions (sin/cos/sqrt etc.) return double results, not float. Also note that the sort is using the shell sort supplied in the benchmark, not any of the built in Java sort options. The Java version of the code is based on the 1.08 EV3 BCC/C version.
Xander Soldaat wrote:Helmut, this are the current values for ROBOTC 4.x pre-alpha for EV3:
HaWe_Bench
(C)H.Wunder 2013
ROBOTC port:
Xander Soldaat
initializing...
done .. go!
1, 336, int_Add
1, 589, int_Mult
2, 226, float_op
3, 1204, rand_array
4, 325, matrx_algb
5, 20932, arr_sort
0, 336, int_Add
1, 589, int_Mult
2, 226, float_op
3, 1204, rand_array
4, 325, matrx_algb
5, 20932, arr_sort
6, 0, displ_txt
7, 0, graphics
sum ms: 23612
benchmark: 2117
BTW, also the RobotC 4.0 code is missing, too (featuring display output tests)... - Xander...?
Last edited by HaWe on 22 Apr 2014, 07:05, edited 1 time in total.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest