Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
Implement resource wrappers for <memory_resource>
Browse files Browse the repository at this point in the history
This includes
* `cuda::mr::resource_ref`
* `cuda::mr::async_resource_ref`
  • Loading branch information
miscco committed Sep 12, 2022
1 parent 332dd6d commit 4bbdd28
Show file tree
Hide file tree
Showing 9 changed files with 1,308 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11

// cuda::mr::async_resource_ref construction
#include <cuda/memory_resource>

#include <cuda/std/cstdint>

template <class T>
struct property_with_value {
using value_type = T;
};

template <class T>
struct property_without_value {};

template <class... Properties>
struct async_resource {
inline __host__ __device__ void* allocate_async(std::size_t, std::size_t,
cuda::stream_ref) {
return &_val;
}

inline __host__ __device__ void
deallocate_async(void* ptr, std::size_t, std::size_t, cuda::stream_ref) {
// ensure that we did get the right inputs forwarded
_val = *static_cast<int*>(ptr);
}

inline __host__ __device__ bool operator==(const async_resource& other) const {
return _val == other._val;
}
inline __host__ __device__ bool operator!=(const async_resource& other) const {
return _val != other._val;
}

int _val = 0;

_LIBCUDACXX_TEMPLATE(class Property)
(requires !cuda::mr::property_with_value<Property> &&
_CUDA_VSTD::_One_of<Property, Properties...>) //
inline __host__ __device__
friend void get_property(const async_resource&, Property) noexcept {}

_LIBCUDACXX_TEMPLATE(class Property)
(requires cuda::mr::property_with_value<Property>&&
_CUDA_VSTD::_One_of<Property, Properties...>) //
inline __host__ __device__ //
friend typename Property::value_type
get_property(const async_resource& res, Property) noexcept {
return res._val;
}
};

namespace constructible {
using ref =
cuda::mr::async_resource_ref<property_with_value<int>,
property_with_value<double>,
property_without_value<std::size_t> >;

using matching_properties = async_resource<property_with_value<double>,
property_without_value<std::size_t>,
property_with_value<int> >;

using missing_stateful_property =
async_resource<property_with_value<int>,
property_without_value<std::size_t> >;
using missing_stateless_property =
async_resource<property_with_value<int>, property_with_value<double> >;

using cuda::std::is_constructible;
static_assert(is_constructible<ref, matching_properties&>::value, "");
static_assert(!is_constructible<ref, missing_stateful_property&>::value, "");
static_assert(!is_constructible<ref, missing_stateless_property&>::value, "");

static_assert(is_constructible<ref, ref&>::value, "");

// Ensure we require a mutable valid reference and do not bind against rvalues
static_assert(!is_constructible<ref, matching_properties>::value, "");
static_assert(!is_constructible<ref, const matching_properties&>::value, "");

static_assert(cuda::std::is_copy_constructible<ref>::value, "");
static_assert(cuda::std::is_move_constructible<ref>::value, "");
} // namespace constructible

namespace assignable {
using ref =
cuda::mr::async_resource_ref<property_with_value<int>,
property_with_value<double>,
property_without_value<std::size_t> >;

using res =
async_resource<property_with_value<int>, property_with_value<double>,
property_without_value<std::size_t> >;

using other_res =
async_resource<property_without_value<int>, property_with_value<int>,
property_with_value<double>,
property_without_value<std::size_t> >;

using cuda::std::is_assignable;
static_assert(cuda::std::is_assignable<ref, res&>::value, "");
static_assert(cuda::std::is_assignable<ref, other_res&>::value, "");

static_assert(cuda::std::is_copy_assignable<ref>::value, "");
static_assert(cuda::std::is_move_assignable<ref>::value, "");
} // namespace assignable

int main(int, char**) { return 0; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11

// cuda::mr::async_resource_ref equality
#include <cuda/memory_resource>
#include <cuda/stream_ref>

#include <cuda/std/cassert>
#include <cuda/std/cstdint>

template <class T>
struct property_with_value {
using value_type = T;
};

template <class T>
struct property_without_value {};

template <class... Properties>
struct async_resource {
inline __host__ __device__ void* allocate_async(std::size_t, std::size_t,
cuda::stream_ref) {
return &_val;
}

inline __host__ __device__ void
deallocate_async(void* ptr, std::size_t, std::size_t, cuda::stream_ref) {
// ensure that we did get the right inputs forwarded
_val = *static_cast<int*>(ptr);
}

inline __host__ __device__ bool operator==(const async_resource& other) const {
return _val == other._val;
}
inline __host__ __device__ bool operator!=(const async_resource& other) const {
return _val != other._val;
}

int _val = 0;

_LIBCUDACXX_TEMPLATE(class Property)
(requires !cuda::mr::property_with_value<Property> &&
_CUDA_VSTD::_One_of<Property, Properties...>) //
inline __host__ __device__
friend void get_property(const async_resource&, Property) noexcept {}

_LIBCUDACXX_TEMPLATE(class Property)
(requires cuda::mr::property_with_value<Property>&&
_CUDA_VSTD::_One_of<Property, Properties...>) //
inline __host__ __device__ //
friend typename Property::value_type
get_property(const async_resource& res, Property) noexcept {
return res._val;
}
};

using ref =
cuda::mr::async_resource_ref<property_with_value<int>,
property_with_value<double>,
property_without_value<std::size_t> >;
using different_properties =
cuda::mr::async_resource_ref<property_with_value<short>,
property_with_value<int>,
property_without_value<std::size_t> >;

using res =
async_resource<property_with_value<int>, property_with_value<double>,
property_without_value<std::size_t> >;

__host__ __device__ void test_equality() {
res input{42};
res with_equal_value{42};
res with_different_value{1337};

// Requires matching properties
assert(ref{input} == different_properties{with_equal_value});
assert(ref{input} != different_properties{with_different_value});
}

int main(int, char**) {
test_equality();
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11

// cuda::mr::async_resource_ref equality
#include <cuda/memory_resource>
#include <cuda/stream_ref>

#include <cuda/std/cassert>
#include <cuda/std/cstdint>

template <class T>
struct property_with_value {
using value_type = T;
};

template <class T>
struct property_without_value {};

template <class... Properties>
struct async_resource {
inline __host__ __device__ void* allocate_async(std::size_t, std::size_t,
cuda::stream_ref) {
return &_val;
}

inline __host__ __device__ void
deallocate_async(void* ptr, std::size_t, std::size_t, cuda::stream_ref) {
// ensure that we did get the right inputs forwarded
_val = *static_cast<int*>(ptr);
}

inline __host__ __device__ bool operator==(const async_resource& other) const {
return _val == other._val;
}
inline __host__ __device__ bool operator!=(const async_resource& other) const {
return _val != other._val;
}

int _val = 0;

_LIBCUDACXX_TEMPLATE(class Property)
(requires !cuda::mr::property_with_value<Property> &&
_CUDA_VSTD::_One_of<Property, Properties...>) //
inline __host__ __device__
friend void get_property(const async_resource&, Property) noexcept {}

_LIBCUDACXX_TEMPLATE(class Property)
(requires cuda::mr::property_with_value<Property>&&
_CUDA_VSTD::_One_of<Property, Properties...>) //
inline __host__ __device__ //
friend typename Property::value_type
get_property(const async_resource& res, Property) noexcept {
return res._val;
}
};

using ref =
cuda::mr::async_resource_ref<property_with_value<int>,
property_with_value<double>,
property_without_value<std::size_t> >;

using pertubed_properties =
cuda::mr::async_resource_ref<property_with_value<double>,
property_with_value<int>,
property_without_value<std::size_t> >;

using res =
async_resource<property_with_value<int>, property_with_value<double>,
property_without_value<std::size_t> >;
using other_res =
async_resource<property_with_value<double>, property_with_value<int>,
property_without_value<std::size_t> >;

__host__ __device__ void test_equality() {
res input{42};
res with_equal_value{42};
res with_different_value{1337};

assert(input == with_equal_value);
assert(input != with_different_value);

assert(ref{input} == ref{with_equal_value});
assert(ref{input} != ref{with_different_value});

// Should ignore pertubed properties
assert(ref{input} == pertubed_properties{with_equal_value});
assert(ref{input} != pertubed_properties{with_different_value});

// Should reject different resources
other_res other_with_matching_value{42};
other_res other_with_different_value{1337};
assert(ref{input} != ref{other_with_matching_value});
assert(ref{input} != ref{other_with_different_value});

assert(ref{input} != pertubed_properties{other_with_matching_value});
assert(ref{input} != pertubed_properties{other_with_matching_value});
}

int main(int, char**) {
test_equality();
return 0;
}
Loading

0 comments on commit 4bbdd28

Please sign in to comment.