forked from triSYCL/triSYCL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
queue.hpp
137 lines (98 loc) · 3.36 KB
/
queue.hpp
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
#ifndef TRISYCL_SYCL_QUEUE_DETAIL_QUEUE_HPP
#define TRISYCL_SYCL_QUEUE_DETAIL_QUEUE_HPP
/** \file Some implementation details of queue.
Ronan at Keryell point FR
This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
*/
#include <atomic>
#include <condition_variable>
#include <mutex>
#ifdef TRISYCL_OPENCL
#include <boost/compute.hpp>
#endif
#include "CL/sycl/context.hpp"
#include "CL/sycl/device.hpp"
#include "CL/sycl/detail/debug.hpp"
namespace cl {
namespace sycl {
namespace detail {
/** Some implementation details about the SYCL queue
*/
struct queue : detail::debug<detail::queue> {
/// Track the number of kernels still running to wait for their completion
std::atomic<size_t> running_kernels;
/// To signal when all the kernels have completed
std::condition_variable finished;
/// To protect the access to the condition variable
std::mutex finished_mutex;
/// Initialize the queue with 0 running kernel
queue() {
running_kernels = 0;
}
/// Wait for all kernel completion
void wait_for_kernel_execution() {
TRISYCL_DUMP_T("Queue waiting for kernel completion");
std::unique_lock<std::mutex> ul { finished_mutex };
finished.wait(ul, [&] {
// When there is no kernel running in this queue, we are ready to go
return running_kernels == 0;
});
}
/// Signal that a new kernel started on this queue
void kernel_start() {
TRISYCL_DUMP_T("A kernel has been added to the queue");
// One more kernel
++running_kernels;
}
/// Signal that a new kernel finished on this queue
void kernel_end() {
TRISYCL_DUMP_T("A kernel of the queue ended");
if (--running_kernels == 0) {
/* It was the last kernel running, so signal the queue just in
case it was working for it for completion
In some cases several threads might want to wait for the
same queue, because of this \c notify_one is not be enough
and a \c notify_all is needed
*/
finished.notify_all();
}
}
#ifdef TRISYCL_OPENCL
/** Return the underlying OpenCL command queue after doing a retain
This memory object is expected to be released by the developer.
Retain a reference to the returned cl_command_queue object.
Caller should release it when finished.
If the queue is a SYCL host queue then an exception is thrown.
*/
virtual cl_command_queue get() const = 0;
/// Return the underlying Boost.Compute command queue
virtual boost::compute::command_queue &get_boost_compute() = 0;
#endif
/** Return the SYCL queue's context
Report errors using SYCL exception classes.
*/
virtual cl::sycl::context get_context() const = 0;
/** Return the SYCL device the queue is associated with
Report errors using SYCL exception classes.
*/
virtual cl::sycl::device get_device() const = 0;
/// Return whether the queue is executing on a SYCL host device
virtual bool is_host() const = 0;
/// Wait for all kernel completion before the queue destruction
/// \todo Update according spec since queue destruction is non blocking
virtual ~queue() {
wait_for_kernel_execution();
}
};
}
}
}
/*
# Some Emacs stuff:
### Local Variables:
### ispell-local-dictionary: "american"
### eval: (flyspell-prog-mode)
### End:
*/
#endif // TRISYCL_SYCL_QUEUE_DETAIL_QUEUE_HPP