| // 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; |
| } |