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

Rework float atomic tests for min/max #109

Merged
merged 1 commit into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions SYCL/AtomicRef/max-native.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -DSYCL_USE_NATIVE_FP_ATOMICS \
// RUN: -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %HOST_RUN_PLACEHOLDER %t.out
// RUN: %GPU_RUN_PLACEHOLDER %t.out
// RUN: %CPU_RUN_PLACEHOLDER %t.out
// TODO: Remove items from UNSUPPORTED once corresponding backends support
// "native" implementation
// UNSUPPORTED: gpu, cpu, cuda

#include <CL/sycl.hpp>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
#include <vector>
using namespace sycl;
using namespace sycl::ONEAPI;

template <typename T> void max_test(queue q, size_t N) {
T initial = std::numeric_limits<T>::lowest();
T val = initial;
std::vector<T> output(N);
std::fill(output.begin(), output.end(), std::numeric_limits<T>::max());
{
buffer<T> val_buf(&val, 1);
buffer<T> output_buf(output.data(), output.size());

q.submit([&](handler &cgh) {
auto val = val_buf.template get_access<access::mode::read_write>(cgh);
auto out =
output_buf.template get_access<access::mode::discard_write>(cgh);
cgh.parallel_for(range<1>(N), [=](item<1> it) {
int gid = it.get_id(0);
auto atm = atomic_ref<T, ONEAPI::memory_order::relaxed,
ONEAPI::memory_scope::device,
access::address_space::global_space>(val[0]);

// +1 accounts for lowest() returning 0 for unsigned types
out[gid] = atm.fetch_max(T(gid) + 1);
});
});
}

// Final value should be equal to N
assert(val == N);

// Only one work-item should have received the initial value
assert(std::count(output.begin(), output.end(), initial) == 1);

// fetch_max returns original value
// Intermediate values should all be >= initial value
for (int i = 0; i < N; ++i) {
assert(output[i] >= initial);
}
}

int main() {
queue q;
std::string version = q.get_device().get_info<info::device::version>();

constexpr int N = 32;
max_test<int>(q, N);
max_test<unsigned int>(q, N);
max_test<long>(q, N);
max_test<unsigned long>(q, N);
max_test<long long>(q, N);
max_test<unsigned long long>(q, N);
max_test<float>(q, N);
max_test<double>(q, N);

std::cout << "Test passed." << std::endl;
}
70 changes: 70 additions & 0 deletions SYCL/AtomicRef/min-native.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -DSYCL_USE_NATIVE_FP_ATOMICS \
// RUN: -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %HOST_RUN_PLACEHOLDER %t.out
// RUN: %GPU_RUN_PLACEHOLDER %t.out
// RUN: %CPU_RUN_PLACEHOLDER %t.out
// TODO: Remove items from UNSUPPORTED once corresponding backends support
// "native" implementation
// UNSUPPORTED: gpu, cpu, cuda

#include <CL/sycl.hpp>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
#include <vector>
using namespace sycl;
using namespace sycl::ONEAPI;

template <typename T> void min_test(queue q, size_t N) {
T initial = std::numeric_limits<T>::max();
T val = initial;
std::vector<T> output(N);
std::fill(output.begin(), output.end(), 0);
{
buffer<T> val_buf(&val, 1);
buffer<T> output_buf(output.data(), output.size());

q.submit([&](handler &cgh) {
auto val = val_buf.template get_access<access::mode::read_write>(cgh);
auto out =
output_buf.template get_access<access::mode::discard_write>(cgh);
cgh.parallel_for(range<1>(N), [=](item<1> it) {
int gid = it.get_id(0);
auto atm = atomic_ref<T, ONEAPI::memory_order::relaxed,
ONEAPI::memory_scope::device,
access::address_space::global_space>(val[0]);
out[gid] = atm.fetch_min(T(gid));
});
});
}

// Final value should be equal to 0
assert(val == 0);

// Only one work-item should have received the initial value
assert(std::count(output.begin(), output.end(), initial) == 1);

// fetch_min returns original value
// Intermediate values should all be <= initial value
for (int i = 0; i < N; ++i) {
assert(output[i] <= initial);
}
}

int main() {
queue q;
std::string version = q.get_device().get_info<info::device::version>();

constexpr int N = 32;
min_test<int>(q, N);
min_test<unsigned int>(q, N);
min_test<long>(q, N);
min_test<unsigned long>(q, N);
min_test<long long>(q, N);
min_test<unsigned long long>(q, N);
min_test<float>(q, N);
min_test<double>(q, N);

std::cout << "Test passed." << std::endl;
}