Efficiency: For loop or Ordinary Addition.

Hello,
Which of the two codes is more efficient? For obvious reasons, using the for loop is easier but I think I heard addition can be pretty fast. I am just trying to add together the elements of a previously defined array and I am concerned about speed and efficiency. I will be using it for real time control on a microcontroller later.
Thanks.

1
2
3
4
  for (i=0;i<10;i++)
  {
	  dutycalc += Voltage1[i];
  }


 
  dutycalc = Voltage1[0]+Voltage1[1]+Voltage1[2]+Voltage1[3]+Voltage1[4]+Voltage1[5]+Voltage1[6]+Voltage1[7]+Voltage1[8]+Voltage1[9];
I could be wrong.

I am going to guess that not using the loop will have slightly fewer operations.
> Which of the two codes is more efficient?

The loop is more efficient (programmer efficient).

All these are more or less equally efficient (machine efficient).
The optimiser knows how to unroll these loops, and would use that knowledge to good effect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <numeric>
#include <iterator>

double Voltage1[10] {} ;

double range_based_loop() 
{
    double dutycalc = 0 ;
    for( double v : Voltage1 ) dutycalc += v ;
    return dutycalc ;
}

double classic_loop() 
{
    double dutycalc = 0 ;
    for( int i = 0 ; i < 10 ; ++i ) dutycalc += Voltage1[i] ;
    return dutycalc ;
}

double library_facility()
{
    return std::accumulate( std::begin(Voltage1), std::end(Voltage1), 0.0 ) ;
}

double manually_unrolled() 
{
    return Voltage1[0]+Voltage1[1]+Voltage1[2]+
           Voltage1[3]+Voltage1[4]+Voltage1[5]+
           Voltage1[6]+Voltage1[7]+Voltage1[8]+Voltage1[9];
}

https://godbolt.org/g/wgMhho
Thanks for the reply JL!.
It doesn't really answer your question, anyway it seems std::valarray are pretty efficient too:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <algorithm>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <numeric>
#include <valarray>

// Decrease the following constant if your pc takes too long
constexpr int DIMENSION = 10000000; // 10,000,000
double Voltage1[DIMENSION] {};
std::valarray<double> Voltage2(DIMENSION);

void range_based_loop();
void classic_loop();
void library_facility();
void whatAboutValarray();
void waitForEnter();

int main()
{
    std::iota(Voltage1, Voltage1 + DIMENSION, 0.0);
    for(size_t i{}; i<4; i++) {
        std::cout << "Voltage1[" << i << "]: " << Voltage1[i] << "; ";
    }
    std::cout << "... Voltage1[" << DIMENSION - 1 << "]: " 
              << Voltage1[DIMENSION-1] << '\n';
    std::iota(std::begin(Voltage2), std::end(Voltage2), 0.0);
    for(size_t i{}; i<4; i++) {
        std::cout << "Voltage2[" << i << "]: " << Voltage2[i] << "; ";
    }
    std::cout << "... Voltage2[" << DIMENSION - 1 << "]: " 
              << Voltage2[DIMENSION-1] << '\n';

    range_based_loop();
    classic_loop();
    library_facility();
    whatAboutValarray();
    waitForEnter();
    return 0;
}

void range_based_loop()
{
    using namespace std::chrono;
    double dutycalc {0.0};
    time_point<system_clock> start = system_clock::now();
    for(double v : Voltage1) { dutycalc += v; }
    time_point<system_clock> stop = system_clock::now();
    duration<double> seconds = stop - start;
    std::cout << "range_based_loop(): " << seconds.count() << '\n';
}

void classic_loop()
{
    using namespace std::chrono;
    double dutycalc {0.0};
    time_point<system_clock> start = system_clock::now();
    for(int i = 0; i < DIMENSION; ++i) { dutycalc += Voltage1[i]; }
    time_point<system_clock> stop = system_clock::now();
    duration<double> seconds = stop - start;
    std::cout << "classic_loop(): " << seconds.count() << '\n';
}

void library_facility()
{
    using namespace std::chrono;
    time_point<system_clock> start = system_clock::now();
    double dutycalc = std::accumulate(std::begin(Voltage1), std::end(Voltage1), 0.0);
    time_point<system_clock> stop = system_clock::now();
    duration<double> seconds = stop - start;
    std::cout << "library_facility(): " << seconds.count() << '\n';
}

void whatAboutValarray()
{
    using namespace std::chrono;
    time_point<system_clock> start = system_clock::now();
    double dutycalc = Voltage2.sum();
    time_point<system_clock> stop = system_clock::now();
    duration<double> seconds = stop - start;
    std::cout << "whatAboutValarray(): " << seconds.count() << '\n';
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Output:
Voltage1[0]: 0; Voltage1[1]: 1; Voltage1[2]: 2; Voltage1[3]: 3; ... Voltage1[9999999]: 1e+007
Voltage2[0]: 0; Voltage2[1]: 1; Voltage2[2]: 2; Voltage2[3]: 3; ... Voltage2[9999999]: 1e+007
range_based_loop(): 0.100006
classic_loop(): 0.135007
library_facility(): 0.101006
whatAboutValarray(): 0.102006

Press ENTER to continue...

Thank you very much @qwertykeyboard @JLBorges and @Enoizat.
I appreciate your kind guidance. I guess I will go ahead with the loop.
Kind regards.
David.
adding up 9 values no matter what method shouldnt be your bottleneck, are you still having performance issues? If so, something else is probably behind it, what else are you doing around the code that you are timing?



Topic archived. No new replies allowed.