@@ -44,94 +44,162 @@ namespace resources
4444
4545 class Sycl
4646 {
47- static sycl::queue *get_a_queue (sycl::context &syclContext,
48- int num,
49- bool useContext)
50- {
51- constexpr auto gpuSelector = sycl::gpu_selector_v;
52- static sycl::property_list propertyList =
53- sycl::property_list (sycl::property::queue::in_order ());
54- static sycl::context privateContext;
55- static sycl::context *contextInUse = NULL ;
56- static std::map<sycl::context *, std::array<sycl::queue, 16 >> queueMap;
57-
58-
59- static std::mutex m_mtx;
60- m_mtx.lock ();
61-
62- // User passed a context, use it
63- if (useContext) {
64- contextInUse = &syclContext;
65-
66- if (queueMap.find (contextInUse) == queueMap.end ()) {
67- queueMap[contextInUse] = {
68- sycl::queue (*contextInUse, gpuSelector, propertyList),
69- sycl::queue (*contextInUse, gpuSelector, propertyList),
70- sycl::queue (*contextInUse, gpuSelector, propertyList),
71- sycl::queue (*contextInUse, gpuSelector, propertyList),
72- sycl::queue (*contextInUse, gpuSelector, propertyList),
73- sycl::queue (*contextInUse, gpuSelector, propertyList),
74- sycl::queue (*contextInUse, gpuSelector, propertyList),
75- sycl::queue (*contextInUse, gpuSelector, propertyList),
76- sycl::queue (*contextInUse, gpuSelector, propertyList),
77- sycl::queue (*contextInUse, gpuSelector, propertyList),
78- sycl::queue (*contextInUse, gpuSelector, propertyList),
79- sycl::queue (*contextInUse, gpuSelector, propertyList),
80- sycl::queue (*contextInUse, gpuSelector, propertyList),
81- sycl::queue (*contextInUse, gpuSelector, propertyList),
82- sycl::queue (*contextInUse, gpuSelector, propertyList),
83- sycl::queue (*contextInUse, gpuSelector, propertyList)};
84- }
85- } else { // User did not pass context, use last used or private one
86- if (contextInUse == NULL ) {
87- contextInUse = &privateContext;
88- queueMap[contextInUse] = {
89- sycl::queue (*contextInUse, gpuSelector, propertyList),
90- sycl::queue (*contextInUse, gpuSelector, propertyList),
91- sycl::queue (*contextInUse, gpuSelector, propertyList),
92- sycl::queue (*contextInUse, gpuSelector, propertyList),
93- sycl::queue (*contextInUse, gpuSelector, propertyList),
94- sycl::queue (*contextInUse, gpuSelector, propertyList),
95- sycl::queue (*contextInUse, gpuSelector, propertyList),
96- sycl::queue (*contextInUse, gpuSelector, propertyList),
97- sycl::queue (*contextInUse, gpuSelector, propertyList),
98- sycl::queue (*contextInUse, gpuSelector, propertyList),
99- sycl::queue (*contextInUse, gpuSelector, propertyList),
100- sycl::queue (*contextInUse, gpuSelector, propertyList),
101- sycl::queue (*contextInUse, gpuSelector, propertyList),
102- sycl::queue (*contextInUse, gpuSelector, propertyList),
103- sycl::queue (*contextInUse, gpuSelector, propertyList),
104- sycl::queue (*contextInUse, gpuSelector, propertyList)};
105- }
47+ /*
48+ * \brief Get the camp managed sycl context.
49+ *
50+ * Note that the first call sets up the context with the given argument.
51+ *
52+ * \return Reference to the camp managed sycl context.
53+ */
54+ static sycl::context& get_private_context (const sycl::context* syclContext)
55+ {
56+ static sycl::context s_context (syclContext ? *syclContext : sycl::context ());
57+ return s_context;
58+ }
59+
60+ /*
61+ * \brief Get the per thread camp managed sycl context.
62+ *
63+ * Note that the first call sets up the context with the given argument.
64+ *
65+ * \return Reference to the per thread camp managed sycl context.
66+ */
67+ static sycl::context& get_thread_private_context (sycl::context const & syclContext)
68+ {
69+ thread_local sycl::context t_context (syclContext);
70+ return t_context;
71+ }
72+
73+ /*
74+ * \brief Get the per thread camp managed sycl context.
75+ *
76+ * Note that the first call sets up the context with the given argument.
77+ *
78+ * \return Reference to the per thread camp managed sycl context.
79+ */
80+ static sycl::context const & get_thread_default_context (sycl::context const & syclContext)
81+ {
82+ get_private_context (&syclContext);
83+ return get_thread_private_context (syclContext);
84+ }
85+
86+ public:
87+ /*
88+ * \brief Get the camp managed sycl context.
89+ *
90+ * \return Const reference to the camp managed sycl context.
91+ */
92+ static sycl::context const & get_default_context ()
93+ {
94+ return get_private_context (nullptr );
95+ }
96+
97+ /*
98+ * \brief Get the per thread camp managed sycl context.
99+ *
100+ * \return Const reference to the per thread camp managed sycl context.
101+ */
102+ static sycl::context const & get_thread_default_context ()
103+ {
104+ return get_thread_private_context (get_private_context (nullptr ));
105+ }
106+
107+ /*
108+ * \brief Set the camp managed sycl context.
109+ */
110+ static void set_default_context (sycl::context const & syclContext)
111+ {
112+ get_private_context (&syclContext) = syclContext;
113+ }
114+
115+ /*
116+ * \brief Set the per thread camp managed sycl context.
117+ */
118+ static void set_thread_default_context (sycl::context const & syclContext)
119+ {
120+ get_private_context (&syclContext);
121+ get_thread_private_context (syclContext) = syclContext;
122+ }
123+
124+ private:
125+ static sycl::queue *get_a_queue (const sycl::context* syclContext,
126+ int num)
127+ {
128+ static constexpr int num_queues = 16 ;
129+
130+ static std::mutex s_mtx;
131+
132+ // note that this type must not invalidate iterators when modified
133+ using value_second_type = std::pair<int , std::array<sycl::queue, num_queues>>;
134+ using queueMap_type = std::map<const sycl::context*, value_second_type>;
135+ static queueMap_type queueMap;
136+ static const typename queueMap_type::iterator queueMap_end = queueMap.end ();
137+ thread_local typename queueMap_type::iterator cachedContextIter = queueMap_end;
138+
139+ if (syclContext) {
140+ // implement sticky contexts
141+ set_thread_default_context (*syclContext);
142+ }
143+ syclContext = &get_thread_default_context ();
144+
145+ if (syclContext != cachedContextIter->first ) {
146+ cachedContextIter = queueMap_end;
106147 }
107- m_mtx.unlock ();
108148
109- static int previous = 0 ;
149+ if (cachedContextIter == queueMap_end || num < 0 ) {
150+ std::lock_guard<std::mutex> lock (s_mtx);
151+
152+ if (cachedContextIter == queueMap_end) {
153+ cachedContextIter = queueMap.find (syclContext);
154+ if (cachedContextIter == queueMap_end) {
155+ static constexpr auto gpuSelector = sycl::gpu_selector_v;
156+ static const sycl::property_list propertyList =
157+ sycl::property_list (sycl::property::queue::in_order ());
158+
159+ cachedContextIter = queueMap.emplace (syclContext,
160+ value_second_type (num_queues-1 , {
161+ sycl::queue (*syclContext, gpuSelector, propertyList),
162+ sycl::queue (*syclContext, gpuSelector, propertyList),
163+ sycl::queue (*syclContext, gpuSelector, propertyList),
164+ sycl::queue (*syclContext, gpuSelector, propertyList),
165+ sycl::queue (*syclContext, gpuSelector, propertyList),
166+ sycl::queue (*syclContext, gpuSelector, propertyList),
167+ sycl::queue (*syclContext, gpuSelector, propertyList),
168+ sycl::queue (*syclContext, gpuSelector, propertyList),
169+ sycl::queue (*syclContext, gpuSelector, propertyList),
170+ sycl::queue (*syclContext, gpuSelector, propertyList),
171+ sycl::queue (*syclContext, gpuSelector, propertyList),
172+ sycl::queue (*syclContext, gpuSelector, propertyList),
173+ sycl::queue (*syclContext, gpuSelector, propertyList),
174+ sycl::queue (*syclContext, gpuSelector, propertyList),
175+ sycl::queue (*syclContext, gpuSelector, propertyList),
176+ sycl::queue (*syclContext, gpuSelector, propertyList)})
177+ ).first ;
178+ }
179+ }
110180
111- static std::once_flag m_onceFlag;
112- CAMP_ALLOW_UNUSED_LOCAL (m_onceFlag);
113- if (num < 0 ) {
114- m_mtx.lock ();
115- previous = (previous + 1 ) % 16 ;
116- m_mtx.unlock ();
117- return &queueMap[contextInUse][previous];
181+ if (num < 0 ) {
182+ int & previous = cachedContextIter->second .first ;
183+ previous = (previous + 1 ) % num_queues;
184+ return &cachedContextIter->second .second [previous];
185+ }
118186 }
119187
120- return &queueMap[contextInUse][ num % 16 ];
188+ return &cachedContextIter-> second . second [ num % num_queues ];
121189 }
122190
123191 // Private from-queue constructor
124192 Sycl (sycl::queue& q) : qu(&q) {}
125193
126194 public:
127- Sycl (int group = -1 )
195+ Sycl (int group = -1 , sycl::context const & syclContext = get_thread_default_context())
196+ : qu(get_a_queue(&syclContext, group))
128197 {
129- sycl::context temp;
130- qu = get_a_queue (temp, group, false );
131198 }
132199
133- Sycl (sycl::context &syclContext, int group = -1 )
134- : qu(get_a_queue(syclContext, group, true ))
200+ [[deprecated]]
201+ Sycl (sycl::context const & syclContext, int group = -1 )
202+ : qu(get_a_queue(&syclContext, group))
135203 {
136204 }
137205
@@ -141,13 +209,16 @@ namespace resources
141209 return Sycl (q);
142210 }
143211
144- // Methods
145- Platform get_platform () const { return Platform::sycl; }
212+ // get default resource
146213 static Sycl get_default ()
147214 {
148- static Sycl h;
149- return h;
215+ return Sycl (0 , get_default_context ());
150216 }
217+
218+ // Methods
219+ Platform get_platform () const { return Platform::sycl; }
220+
221+ // Event
151222 SyclEvent get_event () { return SyclEvent (get_queue ()); }
152223 Event get_event_erased () { return Event{SyclEvent (get_queue ())}; }
153224 void wait () { qu->wait (); }
@@ -207,6 +278,7 @@ namespace resources
207278 }
208279 }
209280
281+ // implementation specific
210282 sycl::queue *get_queue () { return qu; }
211283 sycl::queue const *get_queue () const { return qu; }
212284
0 commit comments