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)
[/size]Results: wrote:notes: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 ? -- ?
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!