Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify check for usm allocated vector iterator #1536

Merged
merged 4 commits into from
Apr 29, 2024
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
54 changes: 12 additions & 42 deletions include/oneapi/dpl/pstl/hetero/dpcpp/sycl_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define _ONEDPL_SYCL_ITERATOR_H

#include <iterator>
#include <type_traits>
#include "../../onedpl_config.h"
#include "sycl_defs.h"

Expand Down Expand Up @@ -149,63 +150,32 @@ struct _ModeConverter<access_mode::write>
static constexpr access_mode __value = access_mode::discard_write;
};

template <typename Iter, typename ValueType = typename std::iterator_traits<Iter>::value_type>
template <typename Iter, typename ValueType = std::decay_t<typename std::iterator_traits<Iter>::value_type>>
using __default_alloc_vec_iter = typename std::vector<ValueType>::iterator;

template <typename Iter, typename ValueType = typename std::iterator_traits<Iter>::value_type>
template <typename Iter, typename ValueType = std::decay_t<typename std::iterator_traits<Iter>::value_type>>
using __usm_shared_alloc_vec_iter =
typename std::vector<ValueType, typename sycl::usm_allocator<ValueType, sycl::usm::alloc::shared>>::iterator;

template <typename Iter, typename ValueType = typename std::iterator_traits<Iter>::value_type>
template <typename Iter, typename ValueType = std::decay_t<typename std::iterator_traits<Iter>::value_type>>
using __usm_host_alloc_vec_iter =
typename std::vector<ValueType, typename sycl::usm_allocator<ValueType, sycl::usm::alloc::host>>::iterator;

// Evaluates to true if the provided type is an iterator with a value_type and if the implementation of a
// std::vector<value_type, Alloc>::iterator can be distinguished between three different allocators, the
// default, usm_shared, and usm_host. If all are distinct, it is very unlikely any non-usm based allocator
// could be confused with a usm allocator.
template <typename Iter, typename Void = void>
struct __vector_iter_distinguishes_by_allocator : std::false_type
{
};
template <typename Iter>
struct __vector_iter_distinguishes_by_allocator<
Iter, std::enable_if_t<!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>> &&
!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_host_alloc_vec_iter<Iter>> &&
!std::is_same_v<__usm_host_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>>>>
: std::true_type
{
};

template <typename Iter, typename Void = void>
struct __is_known_usm_vector_iter_impl : std::false_type
{
};

template <typename Iter>
struct __is_known_usm_vector_iter_impl<
Iter, std::enable_if_t<std::conjunction<
std::disjunction<std::is_same<Iter, oneapi::dpl::__internal::__usm_shared_alloc_vec_iter<Iter>>,
std::is_same<Iter, oneapi::dpl::__internal::__usm_host_alloc_vec_iter<Iter>>>,
oneapi::dpl::__internal::__vector_iter_distinguishes_by_allocator<Iter>>::value>> : std::true_type
{
};

template <typename Iter, typename Void = void>
struct __is_known_usm_vector_iter : std::false_type
{
};
constexpr bool __vector_iter_distinguishes_by_allocator_v =
!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>> &&
!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_host_alloc_vec_iter<Iter>> &&
!std::is_same_v<__usm_host_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>>;

//We must avoid instantiating vector of const, reference, or function elements to avoid ill-formed vector instantiation
template <typename Iter>
struct __is_known_usm_vector_iter<
Iter, std::enable_if_t<std::conjunction<
std::negation<std::disjunction<std::is_const<typename std::iterator_traits<Iter>::value_type>,
std::is_reference<typename std::iterator_traits<Iter>::value_type>,
std::is_function<typename std::iterator_traits<Iter>::value_type>>>,
oneapi::dpl::__internal::__is_known_usm_vector_iter_impl<Iter>>::value>> : std::true_type
{
};
constexpr bool __is_known_usm_vector_iter_v =
oneapi::dpl::__internal::__vector_iter_distinguishes_by_allocator_v<Iter> &&
(std::is_same_v<Iter, oneapi::dpl::__internal::__usm_shared_alloc_vec_iter<Iter>> ||
std::is_same_v<Iter, oneapi::dpl::__internal::__usm_host_alloc_vec_iter<Iter>>);

} // namespace __internal

Expand Down
6 changes: 4 additions & 2 deletions include/oneapi/dpl/pstl/hetero/dpcpp/utils_ranges_sycl.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ struct is_passed_directly<Iter, ::std::enable_if_t<Iter::is_passed_directly::val

//support std::vector::iterator with usm host / shared allocator as passed directly
template <typename Iter>
struct is_passed_directly<Iter, std::enable_if_t<oneapi::dpl::__internal::__is_known_usm_vector_iter<Iter>::value>>
struct is_passed_directly<Iter, std::enable_if_t<oneapi::dpl::__internal::__is_known_usm_vector_iter_v<Iter>>>
: std::true_type
{
};
Expand All @@ -236,7 +236,9 @@ struct is_passed_directly<oneapi::dpl::transform_iterator<Iter, Unary>> : is_pas

template <typename SourceIterator, typename IndexIterator>
struct is_passed_directly<oneapi::dpl::permutation_iterator<SourceIterator, IndexIterator>>
: ::std::conjunction<is_passed_directly<SourceIterator>, is_passed_directly<IndexIterator>>
: ::std::conjunction<
is_passed_directly<SourceIterator>,
is_passed_directly<typename oneapi::dpl::permutation_iterator<SourceIterator, IndexIterator>::IndexMap>>
{
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test_usm_shared_alloc(Policy&& policy, T trash, size_t n, const std::string& typ
__recurse, 0, /*__read =*/true, /*__reset_read=*/true, /*__write=*/true,
/*__check_write=*/true, /*__usable_as_perm_map=*/true,
/*__usable_as_perm_src=*/
TestUtils::__vector_impl_distinguishes_usm_allocator_from_default<decltype(shared_data_vec.begin())>::value,
TestUtils::__vector_impl_distinguishes_usm_allocator_from_default_v<decltype(shared_data_vec.begin())>,
/*__is_reversible=*/true>(policy, shared_data_vec.begin(), shared_data_vec.end(), counting,
copy_out.get_data(), shared_data_vec.begin(), copy_out.get_data(), counting,
trash, std::string("usm_shared_alloc_vector<") + type_text + std::string(">"));
Expand Down Expand Up @@ -77,7 +77,7 @@ test_usm_host_alloc(Policy&& policy, T trash, size_t n, const std::string& type_
wrap_recurse<
__recurse, 0, /*__read =*/true, /*__reset_read=*/true, /*__write=*/true,
/*__check_write=*/true, /*__usable_as_perm_map=*/true, /*__usable_as_perm_src=*/
TestUtils::__vector_impl_distinguishes_usm_allocator_from_default<decltype(host_data_vec.begin())>::value,
TestUtils::__vector_impl_distinguishes_usm_allocator_from_default_v<decltype(host_data_vec.begin())>,
/*__is_reversible=*/true>(policy, host_data_vec.begin(), host_data_vec.end(), counting, copy_out.get_data(),
host_data_vec.begin(), copy_out.get_data(), counting, trash,
std::string("usm_host_alloc_vector<") + type_text + std::string(">"));
Expand Down
23 changes: 8 additions & 15 deletions test/support/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -854,34 +854,27 @@ struct _ZipIteratorAdapter
};

#if TEST_DPCPP_BACKEND_PRESENT
template <typename Iter, typename ValueType = typename std::iterator_traits<Iter>::value_type>
template <typename Iter, typename ValueType = std::decay_t<typename std::iterator_traits<Iter>::value_type>>
using __default_alloc_vec_iter = typename std::vector<ValueType>::iterator;

template <typename Iter, typename ValueType = typename std::iterator_traits<Iter>::value_type>
template <typename Iter, typename ValueType = std::decay_t<typename std::iterator_traits<Iter>::value_type>>
using __usm_shared_alloc_vec_iter =
typename std::vector<ValueType, typename sycl::usm_allocator<ValueType, sycl::usm::alloc::shared>>::iterator;

template <typename Iter, typename ValueType = typename std::iterator_traits<Iter>::value_type>
template <typename Iter, typename ValueType = std::decay_t<typename std::iterator_traits<Iter>::value_type>>
using __usm_host_alloc_vec_iter =
typename std::vector<ValueType, typename sycl::usm_allocator<ValueType, sycl::usm::alloc::host>>::iterator;

// Evaluates to true if the provided type is an iterator with a value_type and if the implementation of a
// std::vector<value_type, Alloc>::iterator can be distinguished between three different allocators, the
// default, usm_shared, and usm_host. If all are distinct, it is very unlikely any non-usm based allocator
// could be confused with a usm allocator.
template <typename Iter, typename Void = void>
struct __vector_impl_distinguishes_usm_allocator_from_default : std::false_type
{
};

template <typename Iter>
struct __vector_impl_distinguishes_usm_allocator_from_default<
Iter, std::enable_if_t<!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>> &&
!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_host_alloc_vec_iter<Iter>> &&
!std::is_same_v<__usm_host_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>>>>
: std::true_type
{
};
constexpr bool __vector_impl_distinguishes_usm_allocator_from_default_v =
!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>> &&
!std::is_same_v<__default_alloc_vec_iter<Iter>, __usm_host_alloc_vec_iter<Iter>> &&
!std::is_same_v<__usm_host_alloc_vec_iter<Iter>, __usm_shared_alloc_vec_iter<Iter>>;

#endif //TEST_DPCPP_BACKEND_PRESENT

////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading