Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit 3cf1cc0

Browse files
[SYCL] Add a test for alignment of allocated USM memory (#1042)
* [SYCL] Add a test for alignment of allocated USM memory
1 parent 4c05df0 commit 3cf1cc0

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed

SYCL/USM/alloc_functions.cpp

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t1.out
2+
// RUN: %HOST_RUN_PLACEHOLDER %t1.out
3+
// RUN: %CPU_RUN_PLACEHOLDER %t1.out
4+
// RUN: %GPU_RUN_PLACEHOLDER %t1.out
5+
// RUN: %ACC_RUN_PLACEHOLDER %t1.out
6+
7+
//==------------------------------------------------------------------------==//
8+
//
9+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
10+
// See https://llvm.org/LICENSE.txt for license information.
11+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include <sycl.hpp>
16+
17+
#include <iostream>
18+
#include <tuple>
19+
20+
using namespace sycl;
21+
22+
constexpr size_t Align = 256;
23+
24+
struct alignas(Align) Aligned {
25+
int x;
26+
};
27+
28+
int main() {
29+
device d;
30+
// Note that get_context() from a default-constructed queue would behave
31+
// differently. Such a context would include multiple devices and would have
32+
// to satisfly all their alignment requirement at once, effectively
33+
// strictening them.
34+
context ctx{d};
35+
queue q{ctx, d};
36+
37+
auto check = [&q](size_t Alignment, auto AllocFn, int Line = __builtin_LINE(),
38+
int Case = 0) {
39+
// First allocation might naturally be over-aligned. Do several of them to
40+
// do the verification;
41+
decltype(AllocFn()) Arr[10];
42+
for (auto *&Elem : Arr)
43+
Elem = AllocFn();
44+
for (auto *Ptr : Arr) {
45+
auto v = reinterpret_cast<uintptr_t>(Ptr);
46+
if ((v & (Alignment - 1)) != 0) {
47+
std::cout << "Failed at line " << Line << ", case " << Case
48+
<< std::endl;
49+
assert(false && "Not properly aligned!");
50+
break; // To be used with commented out assert above.
51+
}
52+
}
53+
for (auto *Ptr : Arr)
54+
free(Ptr, q);
55+
};
56+
57+
// The strictest (largest) fundamental alignment of any type is the alignment
58+
// of max_align_t. This is, however, smaller than the minimal alignment
59+
// returned by the underlyging runtime as of now.
60+
constexpr size_t FAlign = alignof(std::max_align_t);
61+
62+
auto CheckAll = [&](size_t Expected, auto Funcs,
63+
int Line = __builtin_LINE()) {
64+
std::apply(
65+
[&](auto... Fs) {
66+
int Case = 0;
67+
(void)std::initializer_list<int>{
68+
(check(Expected, Fs, Line, Case++), 0)...};
69+
},
70+
Funcs);
71+
};
72+
73+
auto MDevice = [&](auto... args) {
74+
return malloc_device(sizeof(std::max_align_t), args...);
75+
};
76+
CheckAll(FAlign,
77+
std::tuple{[&]() { return MDevice(q); },
78+
[&]() { return MDevice(d, ctx); },
79+
[&]() { return MDevice(q, property_list{}); },
80+
[&]() { return MDevice(d, ctx, property_list{}); }});
81+
82+
auto MHost = [&](auto... args) {
83+
return malloc_host(sizeof(std::max_align_t), args...);
84+
};
85+
CheckAll(FAlign,
86+
std::tuple{[&]() { return MHost(q); }, [&]() { return MHost(ctx); },
87+
[&]() { return MHost(q, property_list{}); },
88+
[&]() { return MHost(ctx, property_list{}); }});
89+
90+
auto MShared = [&](auto... args) {
91+
return malloc_shared(sizeof(std::max_align_t), args...);
92+
};
93+
CheckAll(FAlign,
94+
std::tuple{[&]() { return MShared(q); },
95+
[&]() { return MShared(d, ctx); },
96+
[&]() { return MShared(q, property_list{}); },
97+
[&]() { return MShared(d, ctx, property_list{}); }});
98+
99+
auto ADevice = [&](size_t Align, auto... args) {
100+
return aligned_alloc_device(Align, sizeof(std::max_align_t), args...);
101+
};
102+
CheckAll(FAlign,
103+
std::tuple{
104+
[&]() { return ADevice(FAlign / 2, q); },
105+
[&]() { return ADevice(FAlign / 2, d, ctx); },
106+
[&]() { return ADevice(FAlign / 2, q, property_list{}); },
107+
[&]() { return ADevice(FAlign / 2, d, ctx, property_list{}); }});
108+
CheckAll(
109+
Align,
110+
std::tuple{[&]() { return ADevice(Align, q); },
111+
[&]() { return ADevice(Align, d, ctx); },
112+
[&]() { return ADevice(Align, q, property_list{}); },
113+
[&]() { return ADevice(Align, d, ctx, property_list{}); }});
114+
115+
auto AHost = [&](size_t Align, auto... args) {
116+
return aligned_alloc_host(Align, sizeof(std::max_align_t), args...);
117+
};
118+
CheckAll(
119+
FAlign,
120+
std::tuple{[&]() { return AHost(FAlign / 2, q); },
121+
[&]() { return AHost(FAlign / 2, ctx); },
122+
[&]() { return AHost(FAlign / 2, q, property_list{}); },
123+
[&]() { return AHost(FAlign / 2, ctx, property_list{}); }});
124+
CheckAll(Align,
125+
std::tuple{[&]() { return AHost(Align, q); },
126+
[&]() { return AHost(Align, ctx); },
127+
[&]() { return AHost(Align, q, property_list{}); },
128+
[&]() { return AHost(Align, ctx, property_list{}); }});
129+
130+
auto AShared = [&](size_t Align, auto... args) {
131+
return aligned_alloc_shared(Align, sizeof(std::max_align_t), args...);
132+
};
133+
CheckAll(FAlign,
134+
std::tuple{
135+
[&]() { return AShared(FAlign / 2, q); },
136+
[&]() { return AShared(FAlign / 2, d, ctx); },
137+
[&]() { return AShared(FAlign / 2, q, property_list{}); },
138+
[&]() { return AShared(FAlign / 2, d, ctx, property_list{}); }});
139+
CheckAll(
140+
Align,
141+
std::tuple{[&]() { return AShared(Align, q); },
142+
[&]() { return AShared(Align, d, ctx); },
143+
[&]() { return AShared(Align, q, property_list{}); },
144+
[&]() { return AShared(Align, d, ctx, property_list{}); }});
145+
146+
auto TDevice = [&](auto... args) {
147+
return malloc_device<Aligned>(1, args...);
148+
};
149+
CheckAll(Align, std::tuple{[&]() { return TDevice(q); },
150+
[&]() { return TDevice(d, ctx); }});
151+
152+
auto THost = [&](auto... args) { return malloc_host<Aligned>(1, args...); };
153+
CheckAll(Align, std::tuple{[&]() { return THost(q); },
154+
[&]() { return THost(ctx); }});
155+
156+
auto TShared = [&](auto... args) {
157+
return malloc_shared<Aligned>(1, args...);
158+
};
159+
CheckAll(Align, std::tuple{[&]() { return TShared(q); },
160+
[&]() { return TShared(d, ctx); }});
161+
162+
auto ATDevice = [&](size_t Align, auto... args) {
163+
return aligned_alloc_device<Aligned>(Align, 1, args...);
164+
};
165+
CheckAll(Align, std::tuple{[&]() { return ATDevice(Align / 2, q); },
166+
[&]() { return ATDevice(Align / 2, d, ctx); }});
167+
CheckAll(Align * 2,
168+
std::tuple{[&]() { return ATDevice(Align * 2, q); },
169+
[&]() { return ATDevice(Align * 2, d, ctx); }});
170+
171+
auto ATHost = [&](size_t Align, auto... args) {
172+
return aligned_alloc_host<Aligned>(Align, 1, args...);
173+
};
174+
CheckAll(Align, std::tuple{[&]() { return ATHost(Align / 2, q); },
175+
[&]() { return ATHost(Align / 2, ctx); }});
176+
CheckAll(Align * 2, std::tuple{[&]() { return ATHost(Align * 2, q); },
177+
[&]() { return ATHost(Align * 2, ctx); }});
178+
179+
auto ATShared = [&](size_t Align, auto... args) {
180+
return aligned_alloc_shared<Aligned>(Align, 1, args...);
181+
};
182+
CheckAll(Align, std::tuple{[&]() { return ATShared(Align / 2, q); },
183+
[&]() { return ATShared(Align / 2, d, ctx); }});
184+
CheckAll(Align * 2,
185+
std::tuple{[&]() { return ATShared(Align * 2, q); },
186+
[&]() { return ATShared(Align * 2, d, ctx); }});
187+
188+
auto Malloc = [&](auto... args) {
189+
return malloc(sizeof(std::max_align_t), args...);
190+
};
191+
CheckAll(
192+
FAlign,
193+
std::tuple{
194+
[&]() { return Malloc(q, usm::alloc::host); },
195+
[&]() { return Malloc(d, ctx, usm::alloc::host); },
196+
[&]() { return Malloc(q, usm::alloc::host, property_list{}); },
197+
[&]() { return Malloc(d, ctx, usm::alloc::host, property_list{}); }});
198+
199+
auto TMalloc = [&](auto... args) { return malloc<Aligned>(1, args...); };
200+
CheckAll(Align,
201+
std::tuple{[&]() { return TMalloc(q, usm::alloc::host); },
202+
[&]() { return TMalloc(d, ctx, usm::alloc::host); }});
203+
204+
auto AMalloc = [&](size_t Align, auto... args) {
205+
return aligned_alloc(Align, sizeof(std::max_align_t), args...);
206+
};
207+
CheckAll(FAlign,
208+
std::tuple{
209+
[&]() { return AMalloc(FAlign / 2, q, usm::alloc::host); },
210+
[&]() { return AMalloc(FAlign / 2, d, ctx, usm::alloc::host); },
211+
[&]() {
212+
return AMalloc(FAlign / 2, q, usm::alloc::host,
213+
property_list{});
214+
},
215+
[&]() {
216+
return AMalloc(FAlign / 2, d, ctx, usm::alloc::host,
217+
property_list{});
218+
}});
219+
CheckAll(
220+
Align,
221+
std::tuple{[&]() { return AMalloc(Align, q, usm::alloc::host); },
222+
[&]() { return AMalloc(Align, d, ctx, usm::alloc::host); },
223+
[&]() {
224+
return AMalloc(Align, q, usm::alloc::host, property_list{});
225+
},
226+
[&]() {
227+
return AMalloc(Align, d, ctx, usm::alloc::host,
228+
property_list{});
229+
}});
230+
231+
auto ATMalloc = [&](size_t Align, auto... args) {
232+
return aligned_alloc<Aligned>(Align, 1, args...);
233+
};
234+
CheckAll(
235+
Align,
236+
std::tuple{
237+
[&]() { return ATMalloc(Align / 2, q, usm::alloc::host); },
238+
[&]() { return ATMalloc(Align / 2, d, ctx, usm::alloc::host); }});
239+
CheckAll(
240+
Align * 2,
241+
std::tuple{
242+
[&]() { return ATMalloc(Align * 2, q, usm::alloc::host); },
243+
[&]() { return ATMalloc(Align * 2, d, ctx, usm::alloc::host); }});
244+
245+
return 0;
246+
}

0 commit comments

Comments
 (0)