Skip to content

Commit 12c069d

Browse files
committed
[SYCL] Add opportunistic_group implementation
Signed-off-by: John Pennycook <[email protected]>
1 parent adbd46c commit 12c069d

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//==--- opportunistic_group.hpp --- SYCL extension for non-uniform groups --==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#pragma once
10+
#include <sycl/ext/oneapi/experimental/non_uniform_groups.hpp>
11+
#include <sycl/ext/oneapi/sub_group_mask.hpp>
12+
13+
namespace sycl {
14+
__SYCL_INLINE_VER_NAMESPACE(_V1) {
15+
namespace ext::oneapi::experimental {
16+
17+
class opportunistic_group;
18+
19+
namespace this_kernel {
20+
inline opportunistic_group get_opportunistic_group();
21+
}
22+
23+
class opportunistic_group {
24+
public:
25+
using id_type = id<1>;
26+
using range_type = range<1>;
27+
using linear_id_type = uint32_t;
28+
static constexpr int dimensions = 1;
29+
static constexpr sycl::memory_scope fence_scope =
30+
sycl::memory_scope::sub_group;
31+
32+
id_type get_group_id() const {
33+
#ifdef __SYCL_DEVICE_ONLY__
34+
return static_cast<id_type>(0);
35+
#else
36+
throw runtime_error("Non-uniform groups are not supported on host device.",
37+
PI_ERROR_INVALID_DEVICE);
38+
#endif
39+
}
40+
41+
id_type get_local_id() const {
42+
#ifdef __SYCL_DEVICE_ONLY__
43+
return detail::CallerPositionInMask(Mask);
44+
#else
45+
throw runtime_error("Non-uniform groups are not supported on host device.",
46+
PI_ERROR_INVALID_DEVICE);
47+
#endif
48+
}
49+
50+
range_type get_group_range() const {
51+
#ifdef __SYCL_DEVICE_ONLY__
52+
return 1;
53+
#else
54+
throw runtime_error("Non-uniform groups are not supported on host device.",
55+
PI_ERROR_INVALID_DEVICE);
56+
#endif
57+
}
58+
59+
range_type get_local_range() const {
60+
#ifdef __SYCL_DEVICE_ONLY__
61+
return Mask.count();
62+
#else
63+
throw runtime_error("Non-uniform groups are not supported on host device.",
64+
PI_ERROR_INVALID_DEVICE);
65+
#endif
66+
}
67+
68+
linear_id_type get_group_linear_id() const {
69+
#ifdef __SYCL_DEVICE_ONLY__
70+
return static_cast<linear_id_type>(get_group_id()[0]);
71+
#else
72+
throw runtime_error("Non-uniform groups are not supported on host device.",
73+
PI_ERROR_INVALID_DEVICE);
74+
#endif
75+
}
76+
77+
linear_id_type get_local_linear_id() const {
78+
#ifdef __SYCL_DEVICE_ONLY__
79+
return static_cast<linear_id_type>(get_local_id()[0]);
80+
#else
81+
throw runtime_error("Non-uniform groups are not supported on host device.",
82+
PI_ERROR_INVALID_DEVICE);
83+
#endif
84+
}
85+
86+
linear_id_type get_group_linear_range() const {
87+
#ifdef __SYCL_DEVICE_ONLY__
88+
return static_cast<linear_id_type>(get_group_range()[0]);
89+
#else
90+
throw runtime_error("Non-uniform groups are not supported on host device.",
91+
PI_ERROR_INVALID_DEVICE);
92+
#endif
93+
}
94+
95+
linear_id_type get_local_linear_range() const {
96+
#ifdef __SYCL_DEVICE_ONLY__
97+
return static_cast<linear_id_type>(get_local_range()[0]);
98+
#else
99+
throw runtime_error("Non-uniform groups are not supported on host device.",
100+
PI_ERROR_INVALID_DEVICE);
101+
#endif
102+
}
103+
104+
bool leader() const {
105+
#ifdef __SYCL_DEVICE_ONLY__
106+
return __spirv_SubgroupLocalInvocationId() == Mask.find_low();
107+
#else
108+
throw runtime_error("Non-uniform groups are not supported on host device.",
109+
PI_ERROR_INVALID_DEVICE);
110+
#endif
111+
}
112+
113+
private:
114+
sub_group_mask Mask;
115+
116+
protected:
117+
opportunistic_group(sub_group_mask m) : Mask(m) {}
118+
119+
friend opportunistic_group this_kernel::get_opportunistic_group();
120+
};
121+
122+
namespace this_kernel {
123+
124+
inline opportunistic_group get_opportunistic_group() {
125+
#ifdef __SYCL_DEVICE_ONLY__
126+
#if defined(__SPIR__)
127+
// TODO: It may be wiser to call the intrinsic than rely on this_group()
128+
sycl::sub_group sg = sycl::ext::oneapi::this_sub_group();
129+
sub_group_mask mask = sycl::ext::oneapi::group_ballot(sg, true);
130+
return opportunistic_group(mask);
131+
#elif defined(__NVPTX__)
132+
// TODO: Construct from __activemask
133+
#endif
134+
#else
135+
throw runtime_error("Non-uniform groups are not supported on host device.",
136+
PI_ERROR_INVALID_DEVICE);
137+
#endif
138+
}
139+
140+
} // namespace this_kernel
141+
142+
template <>
143+
struct is_user_constructed_group<opportunistic_group> : std::true_type {};
144+
145+
} // namespace ext::oneapi::experimental
146+
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
147+
} // namespace sycl

sycl/include/sycl/sycl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
#include <sycl/ext/oneapi/experimental/builtins.hpp>
7272
#include <sycl/ext/oneapi/experimental/cluster_group.hpp>
7373
#include <sycl/ext/oneapi/experimental/cuda/barrier.hpp>
74+
#include <sycl/ext/oneapi/experimental/opportunistic_group.hpp>
7475
#include <sycl/ext/oneapi/experimental/tangle_group.hpp>
7576
#include <sycl/ext/oneapi/filter_selector.hpp>
7677
#include <sycl/ext/oneapi/group_algorithm.hpp>

0 commit comments

Comments
 (0)