blob: f06c73566067c2a15f738a0a382ed1903209e985 [file]
// REQUIRES: any-device
// RUN: %clangxx -fsycl %s -o %t.out
// RUN: %t.out
#include <sycl/sycl.hpp>
#include <iostream>
constexpr int LocalSize = 8;
constexpr int WorkGroups = 4;
constexpr int GlobalSize = WorkGroups * LocalSize;
// Keep the value ranges of different work-groups disjoint, so that reading
// another work-group's data is detected as well.
constexpr int GroupBias = LocalSize + 2;
// The barrier is a synchronization primitive, so run the same scenario several
// times to reduce the chance of a race passing unnoticed.
constexpr int Iterations = 4;
static bool runBarrierCase(sycl::queue &Q, int Iteration) {
int *Data = sycl::malloc_shared<int>(GlobalSize, Q);
int *LocalData = sycl::malloc_shared<int>(GlobalSize, Q);
Q.parallel_for<class barrier_kernel>(
sycl::nd_range<1>{GlobalSize, LocalSize}, [=](sycl::nd_item<1> It) {
const int Lid = It.get_local_id(0);
const int Gid = It.get_group().get_group_id(0);
int *GroupData = LocalData + Gid * LocalSize;
GroupData[Lid] = Gid * GroupBias + Lid + 1;
sycl::group_barrier(It.get_group());
if (Lid == 0) {
int Result = GroupData[0];
for (int I = 1; I < LocalSize; ++I)
Result += GroupData[I];
GroupData[0] = Result;
}
sycl::group_barrier(It.get_group());
Data[It.get_global_id(0)] = GroupData[0];
});
Q.wait();
bool Failure = false;
for (int Gid = 0; Gid < WorkGroups; ++Gid) {
int Expected = 0;
for (int Lid = 0; Lid < LocalSize; ++Lid) {
const int Value = Gid * GroupBias + Lid + 1;
Expected += Value;
}
for (int Lid = 0; Lid < LocalSize; ++Lid) {
const int Index = Gid * LocalSize + Lid;
if (Data[Index] != Expected) {
std::cerr << "Iteration " << Iteration << ": mismatch at group " << Gid
<< " lane " << Lid << ": got " << Data[Index] << ", expected "
<< Expected << std::endl;
Failure = true;
}
}
}
sycl::free(Data, Q);
sycl::free(LocalData, Q);
return !Failure;
}
int main() {
sycl::queue Q;
for (int I = 0; I < Iterations; ++I)
if (!runBarrierCase(Q, I))
return 1;
return 0;
}