Assignment; Speed Test of for() loop vs std::for_each()

Hello,

For a class assignment, I was asked to create a program comparing the speed of a for() loop versus a std::for_each() loop.

Below is what I came up with; it compiles and runs but is this a proper test?

Based on what I have a for_each loop is much faster but I am not sure if what I have is a correct test.

Thank you for your time:

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <ctime>

class SimpleObject {

private:

	int IntToIterate;
	float FloatToIterate;

protected:

public:

	SimpleObject();
	~SimpleObject();

	int GetInt();
	float GetFloat();

	void IterateInt();
	void IterateFloat();

};

SimpleObject::SimpleObject() {

	IntToIterate = 0;
	FloatToIterate = 0.0f;

}

SimpleObject::~SimpleObject() {



}

int SimpleObject::GetInt() {

	return IntToIterate;

}

float SimpleObject::GetFloat() {

	return FloatToIterate;

}

void SimpleObject::IterateInt() {

	IntToIterate += 1;

}

void SimpleObject::IterateFloat() {

	FloatToIterate += 1.0f;

}

std::string promptUser() {

	std::string Input;

	std::cout << "\nType in the number of iterations you wish the program to go through for testing. \n\nType in 'exit' or '0' to exit the program: ";

	while (std::getline(std::cin, Input)) {

		if (Input == "0" || Input == "exit") {

			exit(EXIT_SUCCESS);

		}
		else {

			return Input;

		}

	}

}

int main(int argc, char** argv) {
	
	while (true) {

		std::stringstream Converter(promptUser());

		int NumberOfIterations = 0;

		if (Converter >> NumberOfIterations) {

			std::cout << "\n\nWe will be performing " << NumberOfIterations << " iterations.";

			std::vector<SimpleObject> VectorOfSimpleObjects(NumberOfIterations);

			std::cout << "\n\n" << NumberOfIterations << " SimpleObjects created!";

			std::cout << "\n\nBeginning iteration of " << NumberOfIterations << " SimpleObjects by going over them " << NumberOfIterations << " times.";

			std::cout << "\n\nFirst, using old for() method.";

			clock_t begin = clock();

			for (int i = 0; i < NumberOfIterations; ++i) {

				VectorOfSimpleObjects[i].IterateFloat();
				VectorOfSimpleObjects[i].IterateInt();

			}

			clock_t end = clock();

			clock_t elapsed = end - begin;

			float Seconds = ((float)elapsed) / CLOCKS_PER_SEC;

			std::cout << "\n\nOld method took " << Seconds << " seconds in elapsed time.";

			std::cout << "\n\nNow, the new for_each method.";

			begin = clock();

			std::for_each(VectorOfSimpleObjects.begin(), VectorOfSimpleObjects.end(), [](SimpleObject& MainObject){ MainObject.IterateFloat(); });
			std::for_each(VectorOfSimpleObjects.begin(), VectorOfSimpleObjects.end(), [](SimpleObject& MainObject){ MainObject.IterateInt(); });

			end = clock();

			elapsed = end - begin;

			Seconds = ((float)elapsed) / CLOCKS_PER_SEC;

			std::cout << "\n\nNew method took " << Seconds << " seconds in elapsed time.";

		}

	}
	
}
Last edited on
I think I would rather go with something like:

(Renamed some of the methods/data members to be less cumbersome and actually reflect what they're doing - increment as opposed to iterate.)

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
91
92
93
94
95
// http://ideone.com/NXfPh5
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <ctime>

class SimpleObject 
{
    int _int;
    float _float;

public:
    SimpleObject() : _int(0), _float(0.0f) {}

    int GetInt() { return _int; }
    float GetFloat() { return _float; }

    void incrementInt() { ++_int; }
    void incrementFloat() { _float += 1.0f; }
};

std::size_t getCount(const std::string& prompt)
{
    std::string Input;

    std::cout << prompt << "\n> ";

    std::getline(std::cin, Input);

    if (Input == "exit")
        return 0;

    return std::stoi(Input);
}

void doForLoop(std::vector<SimpleObject>& v, std::size_t iterations)
{
    for (std::size_t i = 0; i < iterations; ++i)
    {
        for (auto it = v.begin(); it != v.end(); ++it)
        {
            it->incrementFloat();
            it->incrementInt();
        }
    }
}

void doForEach(std::vector<SimpleObject>& v, std::size_t iterations)
{
    for (std::size_t i = 0; i < iterations; ++i)
        for_each(v.begin(), v.end(), [](SimpleObject& o) { o.incrementFloat(); o.incrementInt(); });
}

void doRangedFor(std::vector<SimpleObject>& v, std::size_t iterations)
{
    for (std::size_t i = 0; i < iterations; ++i)
        for (auto & e : v)
            e.incrementFloat(), e.incrementInt();
}

using func_type = void(*)(std::vector<SimpleObject>&, std::size_t);
void test(const std::string& testName, func_type testme, std::size_t iterations, std::size_t objects)
{
    std::vector<SimpleObject> v(objects);

    clock_t begin = clock();
    testme(v, iterations);
    clock_t end = clock();

    std::cout << "Test \"" << testName << "\" took " << (float(end) - begin) / CLOCKS_PER_SEC << " seconds.\n";
}


int main(int argc, char** argv) 
{
    std::size_t nIterations;
    std::size_t nObjects;

    do 
    {
        nIterations = getCount("Enter the number of iterations:");
        nObjects = getCount("Enter the number of objects in the container:");

        if (nIterations && nObjects)
        {
            std::cout << "\n\nWe will be performing " << nIterations << " iterations on a container holding ";
            std::cout << nObjects << " objects.\n";

            test("for loop", doForLoop, nIterations, nObjects);
            test("for each", doForEach, nIterations, nObjects);
            test("ranged for", doRangedFor, nIterations, nObjects);
        }
    } while (nIterations && nObjects);
}


Remember to make sure you're compiling with optimizations on!
@cire your code is awesome; half the size, more functional, and a better test.

Thank you.

I'll get at your level someday :) :)
Topic archived. No new replies allowed.