-
Notifications
You must be signed in to change notification settings - Fork 0
/
compute_queue.cpp
110 lines (90 loc) · 2.62 KB
/
compute_queue.cpp
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
#include <algorithm>
#include "compute_queue.h"
#include "glstuff.h"
ComputeQueue::ComputeQueue()
{
}
void ComputeQueue::addTimings(ComputeClient* client, unsigned itemsRun, double time)
{
auto it = m_timings.find(client);
if (it == m_timings.end())
{
m_timings.insert(std::make_pair(client, CountAndTime(itemsRun, time)));
}
else
{
it->second.m_count += itemsRun;
it->second.m_time += time;
}
}
double ComputeQueue::getAverageTime(ComputeClient* client)
{
const auto it = m_timings.find(client);
return (it == m_timings.end()) ? -1.0 : (it->second.m_time / it->second.m_count);
}
void ComputeQueue::runAll()
{
for (auto computeClientPtr : m_clients)
{
const double startTime = glfwGetTime();
glFinish(); // For accurate timing
const unsigned itemsRun = computeClientPtr->runAllComputeItems();
glFinish(); // For accurate timing
const double endTime = glfwGetTime();
addTimings(computeClientPtr, itemsRun, endTime - startTime);
}
m_clients.clear();
}
void ComputeQueue::_runSome(ComputeClient* client, int count)
{
bool allRun;
const double startTime = glfwGetTime();
glFinish(); // For accurate timing
const unsigned itemsRun = client->runSomeComputeItems(count, allRun);
glFinish(); // For accurate timing
const double endTime = glfwGetTime();
//addTimings(client, itemsRun, endTime - startTime);
if (!allRun)
m_clients.push_back(client);
printf("Ran %u batches in %lf sec\n", itemsRun, endTime - startTime);
}
/*
MISTAKE: The next 2 functions shouldn't just look at
the first client, they should keep running clients in a loop
until the time is exhausted!!!
(This will only make a difference with >1 clients)
*/
void ComputeQueue::runSome(int count)
{
if (m_clients.empty())
return;
// Find the client to run
ComputeClient* const client = m_clients.front();
m_clients.pop_front();
// Run and add timings
_runSome(client, count);
}
void ComputeQueue::runUntil(double endTime)
{
if (m_clients.empty())
return;
const double startTime = glfwGetTime();
// Find the client to run
ComputeClient* const client = m_clients.front();
m_clients.pop_front();
double averageTime = getAverageTime(client);
if (averageTime < 0.0) // No data present
{
_runSome(client, 1); // This will add some data
if (endTime <= startTime)
return; // In case populating the initial average took long enough
}
// Run a number that should take us up to the desired time,
// but run a minimum of one unit, even if it takes too long.
const double timeToSpend = endTime - startTime;
const unsigned count = (unsigned)floor(
std::max(timeToSpend / averageTime, 1.0)
);
// Run and add timings
_runSome(client, count);
}