Wednesday September 1, 2010
Hello-
I am looking forward to Maple-IDE release 0.0.7 and I am happy to help by searching for bugs in the code and by improving the documentation.
I decided to write simple code to compare the looping speed of the Maple and the Arduino Duemilanove (ATmega 328 chip).
I used the Maple-IDE 0.0.6 and the slightly outdated Arduino-IDE 017. My code uses simple nested For-Next loops (with and without If statements).
The results in the comparison are shown below. I did not continue with the timings once it took more than 10 seconds to complete each set of nested loops. I observed mainly expected behavior (the Maple is 4X-5X faster than the Arduino), but also a few surprises.
The speed comparison is not exact, because the code was uploaded to Maple RAM, but to Arduino FLASH memory. I am having problems with uploads to my Maple FLASH memory, and even using the "perpetual bootloader mode" does not work
Using seven "empty" nested loops both compilers optimize the code. I did not look at the object code, but I suspect both compilers simply omitted the loop code, resulting in fast 0 millisecond (0 ms) execution times.
Then I reduced the number of loops to four and in the innermost loop I added an "if" statement which prints a message on the last iteration of the loops before the loops terminate. The Maple executes the code 4X-5X faster than the Arduino Duemilanove.
Then I tried something unorthodox. I removed the innermost comparison and print statements, but I changed the "limit" variable from type int to type float. Normally, this would not be done, because float operations require more cpu cycles. Both the Maple and Arduino compilers do not optimize this code. Even though the nested loops are "empty" the amount of time to execute the loops is significantly greater than 0 ms and increases as the limit variable increases.
Is this something which should be brought to the attention of both compiler authors (avr-gcc and arm-non-eabi-gcc)? I do not know if this "bug" affects the efficiency of other functions.
Then I changed the "limit" variable to type long (both signed and unsigned) which might be done in real code. With empty loops, the Maple compiler behaves correctly for all values tested, but the Arduino compiler misbehaves when the "limit" variable is greater than 32767. The last message I see is "Start loops". I did not determine if the code crashes before the first call to millis() or if the code crashes in the nested loops.
I might expect code to misbehave if longs on the Arduino had an upper limit of 32767. However, the Arduino documentation describes a range of -2,147,483,648 to 2,147,483,647 for longs and 0 to 4,294,967,295 for unsigned longs.
What other unexpected behavior are other users finding? Note: I did not try to change the type of the "counterN" variables from int to float or long. I do not know if this will affect how the code is compiled.
Thanks!
Stephen from NYC
<start of code>
/*
Compiler Optimization Loop Bug Test
This code is currently configured to use four nested loops.
The innermost loops does not do any comparisons and does not print.
The speed comparison is not exact, because the code was uploaded to Maple RAM, but to Arduino FLASH memory.
Created 31 August 2010, last updated 01 September 2010
By leaflabs.com forums member "Stephen from NYC"
This code is released under a Creative Commons Attribution-Share Alike 3.0 license.
*/
void setup() {
/* Serial.begin() is not needed by the Maple, but is needed by the Arduino */
// Serial.begin(9600);
}
void loop() {
// SEVEN loops (withOUT comparison and call to inner loop println function)
// Maple R3 (IDE 0.0.6): int limit= 100 ( 0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): int limit= 1000 ( 0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): int limit= 10000 ( 0 ms); Arduino (IDE 017): 0 ms
// FOUR loops (with comparison and call to inner loop println function)
// Maple R3 (IDE 0.0.6): int limit= 10 ( 3 ms); Arduino (IDE 017): 28 ms
// Maple R3 (IDE 0.0.6): int limit= 20 ( 29 ms); Arduino (IDE 017): 137 ms
// Maple R3 (IDE 0.0.6): int limit= 30 ( 140 ms); Arduino (IDE 017): 601 ms
// Maple R3 (IDE 0.0.6): int limit= 40 ( 438 ms); Arduino (IDE 017): 1840 ms
// Maple R3 (IDE 0.0.6): int limit= 60 ( 2197 ms); Arduino (IDE 017): 9510 ms
// Maple R3 (IDE 0.0.6): int limit= 70 ( 4062 ms); Arduino (IDE 017): 16890 ms
// Maple R3 (IDE 0.0.6): int limit= 80 ( 6197 ms)
// Maple R3 (IDE 0.0.6): int limit= 100 (16851 ms)
// THREE loops (withOUT comparison and call to inner loop println function)
// Maple R3 (IDE 0.0.6): float limit= 50 ( 11 ms); Arduino (IDE 017): 49 ms
// Maple R3 (IDE 0.0.6): float limit= 70 ( 29 ms); Arduino (IDE 017): 133 ms
// Maple R3 (IDE 0.0.6): float limit= 80 ( 43 ms); Arduino (IDE 017): 198 ms
// Maple R3 (IDE 0.0.6): float limit= 100 ( 84 ms); Arduino (IDE 017): 384 ms
// Maple R3 (IDE 0.0.6): float limit= 200 ( 671 ms); Arduino (IDE 017): 3048 ms
// Maple R3 (IDE 0.0.6): float limit= 300 ( 2266 ms); Arduino (IDE 017): 11963 ms
// Maple R3 (IDE 0.0.6): float limit= 400 ( 5365 ms)
// Maple R3 (IDE 0.0.6): float limit= 500 (10471 ms)
// THREE loops (with comparison and call to inner loop println function)
// Maple R3 (IDE 0.0.6): float limit= 10 ( 3 ms); Arduino (IDE 017): 30 ms
// Maple R3 (IDE 0.0.6): float limit= 20 ( 19 ms); Arduino (IDE 017): 95 ms
// Maple R3 (IDE 0.0.6): float limit= 30 ( 61 ms); Arduino (IDE 017): 262 ms
// Maple R3 (IDE 0.0.6): float limit= 40 ( 143 ms); Arduino (IDE 017): 578 ms
// Maple R3 (IDE 0.0.6): float limit= 100 ( 2184 ms); Arduino (IDE 017): 8115 ms
// Maple R3 (IDE 0.0.6): float limit= 120 ( 3766 ms); Arduino (IDE 017): 13848 ms
// Maple R3 (IDE 0.0.6): float limit= 200 (17365 ms)
// FOUR loops (withOUT comparison and call to inner loop println function)
// Maple R3 (IDE 0.0.6): unsigned long limit= 1000 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): unsigned long limit= 30000 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): unsigned long limit= 32767 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): unsigned long limit= 32768 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): unsigned long limit= 50000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): unsigned long limit= 100000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): unsigned long limit= 1000000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): unsigned long limit= 10000000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// FOUR loops (withOUT comparison and call to inner loop println function)
// Maple R3 (IDE 0.0.6): long limit= 1000 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): long limit= 16384 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): long limit= 16385 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): long limit= 32767 (0 ms); Arduino (IDE 017): 0 ms
// Maple R3 (IDE 0.0.6): long limit= 32768 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): long limit= 40000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): long limit= 100000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): long limit= 1000000 (0 ms); Arduino (IDE 017): (see only "Start loops")
// Maple R3 (IDE 0.0.6): long limit= 10000000 (0 ms); Arduino (IDE 017): (see only "Start loops")
int limit=40;
int counter1=0;
int counter2=0;
int counter3=0;
int counter4=0;
int counter5=0;
int counter6=0;
int counter7=0;
unsigned long start=0;
unsigned long stop=0;
SerialUSB.println("Start loops");
// Serial.println("Start loops");
start=millis();
for (counter1=0; counter1 < limit; counter1++)
{
for (counter2=0; counter2 < limit; counter2++)
{
for (counter3=0; counter3 < limit; counter3++)
{
for (counter4=0; counter4 < limit; counter4++)
{
/* inner loops 5/6/7 */
/*
for (counter5=0; counter5 < limit; counter5++)
{
for (counter6=0; counter6 < limit; counter6++)
{
for (counter7=0; counter7 < limit; counter7++)
{
*/
/* the compare and print line needs to be edited for loop number and also Arduino/Maple println() differences */
if ((counter1==(limit-1)) && (counter2==(limit-1)) && (counter3==(limit-1)) && (counter4==(limit-1)) /* && (counter5==(limit-1)) && (counter6==(limit-1)) && (counter7==(limit-1)) */ ) SerialUSB.println("Inner loop finished");
/* closing parentheses for inner loops 5/6/7 */
/*
}
}
}
*/
}
}
}
}
stop=millis();
/* Code for Maple */
SerialUSB.println("Stop loops");
SerialUSB.print("elapsed time= ");
SerialUSB.print(stop-start);
SerialUSB.print(" ms (for limit=");
SerialUSB.print(limit);
SerialUSB.println(")\n");
/* Code for Arduino */
/*
Serial.println("Stop loops");
Serial.print("elapsed time= ");
Serial.print(stop-start);
Serial.print(" ms (for limit=");
Serial.print(limit);
Serial.println(")\n");
*/
}