0

I'm a 4th year EE undergrad, so I'm more of a hardware guy than software. But concerning best programming techniques, is it "better" (more efficient/and/or equally effective) to use for loops when trying to change several items in an array by the same mathematical operation?

--OR--

Is it best to list each item out and have each operation performed by the rate at which the primary "void loop" cycles?

I'm using a Teensy 3.2 board and trying to get a DSP reverb effect working. I have an array of 8 delay tap lines, each with a different time multiplier. I'm trying to determine if it will take more time to process a for loop for each delay-tap line, versus multiplying each element in my array without the additional loop. I need to minimize processing time at all costs to avoid additional system lag.

Sample code:

  //Set delay times
  for(int i = 0; i < 8; i++) 
  {
    delay1.delay(i, pot1*pauses[i]);
  }

versus

  delay1.delay(0, pot1*pauses[0]);
  delay1.delay(1, pot1*pauses[1]);
  delay1.delay(2, pot1*pauses[2]);
  .
  .
  .

EDIT Added sample code.

  • 1
    can you give some pseudo-code for each method? – ratchet freak Nov 5 '17 at 18:31
  • 1
    Post examples of both alternatives. I'm not sure of what are you asking. – user31481 Nov 5 '17 at 18:44
  • Sure, I updated the original post. It likely seems like a trivial question since any dummy wouldn't want to write out 10 lines of repetitive code--most applications that aren't time-sensitive. But I recall trying to do something similar with my Uno board (8MHz) and drawing lines to an OLED. Using "For" loops significantly increased the drawing time. – Matt Nov 5 '17 at 18:46
2

Have a look at the compiler output.

The Loop option

The first alternative produce a preface (setting things) and the loop itself.

Preface

40201803:   21c9        s32i.n  a12, a1, 8
40201805:   3109        s32i.n  a0, a1, 12
40201807:   00a0c2          movi    a12, 0

loop

4020180a:   202cc0          or  a2, a12, a12
4020180d:   01ccc2          addi    a12, a12, 1
40201810:   ff8585          call0   4020106c <delay>
40201813:   f38c66          bnei    a12, 8, 4020180a <_Z6XYtestv+0xa>

The unfolded option

While the unfolded version is:

40201823:   020c        movi.n  a2, 0
40201825:   3109        s32i.n  a0, a1, 12
40201827:   ff8445          call0   4020106c <delay>
4020182a:   120c        movi.n  a2, 1
4020182c:   ff83c5          call0   4020106c <delay>
4020182f:   220c        movi.n  a2, 2
40201831:   ff8385          call0   4020106c <delay>
40201834:   320c        movi.n  a2, 3
40201836:   ff8345          call0   4020106c <delay>
40201839:   420c        movi.n  a2, 4
4020183b:   ff8305          call0   4020106c <delay>
4020183e:   520c        movi.n  a2, 5
40201840:   ff8285          call0   4020106c <delay>
40201843:   620c        movi.n  a2, 6
40201845:   ff8245          call0   4020106c <delay>
40201848:   720c        movi.n  a2, 7
4020184a:   ff8205          call0   4020106c <delay>

So, the loop execute 4 instructions per each array element, while the unfolded version had only 2 instructions per array element.

But you are trading speed for space and and risking an error while coding the same repetitive thing.

However, GCC (the 'Arduino' compiler) can unfold the loop by itself, so you still can write a loop but execute a sequence. Look at Tell gcc to specifically unroll a loop

Real numbers

I run a sketch (Arduino UNO) to time loop vs unfolded. The times for 1,000 execution of each method are:

loop:     6524us 
unfolded: 3808us

Quit a difference!

Sketch

int pause[8] = {1, 2, 3, 4, 5, 6, 7, 8};
typedef int (*fn)(void);

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

  Serial.print("Timing loop: ");
  Serial.print(time(met1));
  Serial.println(" us");

  Serial.print("Timing unfolded: ");
  Serial.print(time(met2));
  Serial.println(" us");
}

void loop() {

}

int time(fn f) {
  unsigned long start = micros();
  int x = 0;
  for (int i = 0; i < 1000; i++) {
    x = f();
  }
  unsigned long dif = micros() - start;
  return dif;
}

int met1() {
  int sum = 0;
  for (int i=0; i < 8; i++) {
    sum += pause[i];    
  }
  return sum;
}

int met2() {
  int sum = 0;
  sum += pause[0];
  sum += pause[1];
  sum += pause[2];
  sum += pause[3];
  sum += pause[4];
  sum += pause[5];
  sum += pause[6];
  sum += pause[7];
  return sum;
}
0

is it "better" (more efficient/and/or equally effective)

depends on your definition of "better", or "efficient", ...

for example unrolling a loop is typically more efficient speed-wise, but less so space-wise. or vice versa.

on top of that, you have other potential definitions for "efficiency", like readability, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.