-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBenchmark.cpp
More file actions
executable file
·177 lines (134 loc) · 5.08 KB
/
Benchmark.cpp
File metadata and controls
executable file
·177 lines (134 loc) · 5.08 KB
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
* Benchmark.cpp
*
* Created on: Nov 11, 2019
* Author: joseph
*/
#include "Benchmark.h"
void producerTask(void * params) {
Computation *comp = (Computation*) params;
comp->compute();
yield();
delete comp;
vTaskDelete( NULL );
}
Benchmark::Benchmark(int durationCycles, int coolDownTimer, int queueSize) {
this->durationCycles = durationCycles > 0 ? durationCycles : 4;
this->coolDownTimer = coolDownTimer > 0 ? coolDownTimer : 1500;
this->upperLimitSum = 50000;
this->upperLimitMul = 10000;
queue = new QueueHandle_t();
this->queueSize = queueSize;
*queue = xQueueCreate( queueSize, sizeof( long ) );
maxNumOfThreads = queueSize;
}
Benchmark::~Benchmark() {
Serial.println();
delete queue;
}
int Benchmark::getUpperLimitMul() {
return upperLimitMul;
}
void Benchmark::setUpperLimitMul(int upperLimitMul) {
this->upperLimitMul = upperLimitMul;
}
int Benchmark::getUpperLimitSum() {
return upperLimitSum;
}
void Benchmark::setUpperLimitSum(int upperLimitSum) {
this->upperLimitSum = upperLimitSum;
}
void Benchmark::setMaxNumOfThreads(int maxNumOfThreads) {
this->maxNumOfThreads = maxNumOfThreads;
}
float Benchmark::performBenchmark(int numOfThreads) {
delay(coolDownTimer);
if (numOfThreads > maxNumOfThreads) {
Serial.println("[bench] error: Number of maximal threads reached!");
Serial.print("[bench] error: running with maxNumOfThreads => ");
Serial.println(maxNumOfThreads);
return runComputationWith(maxNumOfThreads, durationCycles);
} else {
return runComputationWith(numOfThreads, durationCycles);
}
}
float Benchmark::runComputationWith(int numOfThreads, int numOfCycles) {
long average = 0;
long result = 0;
for (int i = 0; i < numOfCycles; i++) {
// declarations
Computation *c[numOfThreads];
/*
* =============================================================================
* =================================
*/
long start = millis();
for (int j = 0; j < numOfThreads; j++) {
int lowLimSum = (getUpperLimitSum() / numOfThreads) * j;
int uppLimSum = (getUpperLimitSum() / numOfThreads) * (j + 1);
int uppLimMul = getUpperLimitMul();
if(getUpperLimitSum() % numOfThreads != 0 && j == numOfThreads - 1) {
uppLimSum += (getUpperLimitSum() % numOfThreads);
}
c[j] = new Computation(lowLimSum, uppLimSum, 0, uppLimMul, *queue);
Serial.print("[task] Thread ");
Serial.print(j);
Serial.print(" on core [");
Serial.print((j+2)%2);
Serial.print("] -> ");
Serial.print(c[j]->getLoopOneStart());
Serial.print(";");
Serial.println(c[j]->getLoopOneEnd());
// Serial.print(" -> stack size allocation : ");
// Serial.println(sizeof(c[j]) * 32 * 8); /* https://github.com/espressif/arduino-esp32/issues/1745 */
/* https://www.arduino.cc/en/pmwiki.php?n=Reference/Sizeof */
/* https://www.freertos.org/vTaskGetInfo.html */
/* https://www.esp32.com/viewtopic.php?t=4295 */
/* Serial.println(uxTaskGetStackHighWaterMark(NULL)); in task for left stack size */
xTaskCreatePinnedToCore(
producerTask, /* Function to implement the task */
(j+2)%2 == 0 ? "calcTask0" : "calcTask1", /* Name of the task */
sizeof(c[j]) * 32 * 8, /* Stack size in words: */
/* -> size in words of the computation object: sizeof(c[j]) * 32 */
/* -> multiple by 8 for secure issues (used stack size will increase during runtime) */
/* => total allocated stack size: 1024 */
c[j], /* Task input parameter */
0, /* Priority of the task */
NULL, /* Task handle. */
(j+2)%2); /* Core where the task should run -> toggle between 0,1 if user try */
/* to run multiple threads on a dual core processor */
}
for (int k = 0; k < numOfThreads; k++) {
long partResult;
/*
* regarding to src [3]: "For the last argument, the value is specified in ticks, and we will
* pass the value portMAX_DELAY, meaning that we will wait indefinitely
* in case the queue is fullor we receive an message object."
*
* So this function call is a blocking call and the current (main) thread will wait until he received a new message
* from the queue. In this case, we can add the current part result to the main result:
* -> result += partResult
*/
xQueueReceive(*queue, &partResult, portMAX_DELAY);
Serial.print("[bench] Received (part) result from thread ");
Serial.print(k);
Serial.print(" on core ");
Serial.println((k+2)%2);
result += partResult;
}
long end = millis();
average += end - start;
/*
* =============================================================================
* =================================
*/
}
Serial.print("[bench] Number of threads: ");
Serial.print(numOfThreads);
Serial.print("; total time: ");
Serial.print(average / numOfCycles);
Serial.println(" ms.");
Serial.print("[bench] => Result: ");
Serial.println(result / numOfCycles);
return average / numOfCycles;
}