CCCL (CUDA C++ Core Libraries) provides: - CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk) - Thrust: high-level parallel algorithms (transform_reduce, sort, scan) - libcudacxx: CUDA C++ standard library (atomics, barriers, memory) - cudax: experimental features (memory resources, allocators) - Tuning policies: per-SM hardware-specific algorithm parameters Competition optimization vectors mapped to CCCL: - Output TPS (83% weight): warp_reduce, block_reduce, device_topk - Input TPS (14% weight): device_scan, block_load, prefetch - Cache TPS (3% weight): prefix caching strategy patterns - Memory (0.9 util): pooled/cached/buddy allocators Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only) License: Apache-2.0
221 lines
6.9 KiB
Plaintext
221 lines
6.9 KiB
Plaintext
#include <thrust/distance.h>
|
|
#include <thrust/iterator/offset_iterator.h>
|
|
|
|
#include <cuda/std/iterator>
|
|
|
|
#include <unittest/unittest.h>
|
|
|
|
// ensure that we properly support thrust::counting_iterator from cuda::std
|
|
void TestOffsetIteratorTraits()
|
|
{
|
|
using base_it = thrust::host_vector<int>::iterator;
|
|
using it = thrust::offset_iterator<base_it>;
|
|
using traits = cuda::std::iterator_traits<it>;
|
|
using vec_traits = cuda::std::iterator_traits<base_it>;
|
|
|
|
static_assert(cuda::std::is_same_v<traits::difference_type, vec_traits::difference_type>);
|
|
static_assert(cuda::std::is_same_v<traits::value_type, vec_traits::value_type>);
|
|
static_assert(cuda::std::is_same_v<traits::pointer, vec_traits::pointer>);
|
|
static_assert(cuda::std::is_same_v<traits::reference, vec_traits::reference>);
|
|
static_assert(cuda::std::is_same_v<traits::iterator_category, vec_traits::iterator_category>);
|
|
|
|
static_assert(cuda::std::is_same_v<thrust::iterator_traversal_t<it>, thrust::random_access_traversal_tag>);
|
|
|
|
static_assert(cuda::std::__has_random_access_traversal<it>);
|
|
|
|
static_assert(cuda::std::output_iterator<it, int>);
|
|
static_assert(cuda::std::input_iterator<it>);
|
|
static_assert(cuda::std::forward_iterator<it>);
|
|
static_assert(cuda::std::bidirectional_iterator<it>);
|
|
static_assert(cuda::std::random_access_iterator<it>);
|
|
static_assert(!cuda::std::contiguous_iterator<it>);
|
|
}
|
|
DECLARE_UNITTEST(TestOffsetIteratorTraits);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetConstructor()
|
|
{
|
|
thrust::offset_iterator<int*> iter0;
|
|
ASSERT_EQUAL(iter0.base(), static_cast<int*>(nullptr));
|
|
ASSERT_EQUAL(iter0.offset(), 0);
|
|
|
|
Vector v{42, 43};
|
|
thrust::offset_iterator iter1(v.begin());
|
|
ASSERT_EQUAL_QUIET(iter1.base(), v.begin());
|
|
ASSERT_EQUAL(iter1.offset(), 0);
|
|
ASSERT_EQUAL(*iter1, 42);
|
|
|
|
thrust::offset_iterator iter2(v.begin(), 1);
|
|
ASSERT_EQUAL_QUIET(iter2.base(), v.begin());
|
|
ASSERT_EQUAL(iter2.offset(), 1);
|
|
ASSERT_EQUAL(*iter2, 43);
|
|
|
|
ptrdiff_t offset = 1;
|
|
thrust::offset_iterator iter3(v.begin(), &offset);
|
|
ASSERT_EQUAL_QUIET(iter3.base(), v.begin());
|
|
ASSERT_EQUAL(iter3.offset(), &offset);
|
|
ASSERT_EQUAL(*iter3.offset(), 1);
|
|
ASSERT_EQUAL(*iter3, 43);
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetConstructor);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetIteratorCopyConstructorAndAssignment()
|
|
{
|
|
Vector v{42, 43};
|
|
|
|
// value offset
|
|
{
|
|
thrust::offset_iterator iter0(v.begin());
|
|
#if _CCCL_COMPILER(MSVC) // MSVC cannot deduce the template arguments from the copy ctor
|
|
decltype(iter0) iter1(iter0);
|
|
#else // _CCCL_COMPILER(MSVC)
|
|
thrust::offset_iterator iter1(iter0);
|
|
#endif // _CCCL_COMPILER(MSVC)
|
|
ASSERT_EQUAL(iter0 == iter1, true);
|
|
ASSERT_EQUAL(*iter0 == *iter1, true);
|
|
|
|
thrust::offset_iterator iter2(v.begin() + 1);
|
|
ASSERT_EQUAL(iter0 != iter2, true);
|
|
ASSERT_EQUAL(*iter0 != *iter2, true);
|
|
|
|
iter2 = iter0;
|
|
ASSERT_EQUAL(iter0 == iter2, true);
|
|
ASSERT_EQUAL(*iter0 == *iter2, true);
|
|
}
|
|
|
|
// indirect offset
|
|
{
|
|
const typename Vector::iterator::difference_type offset = 0;
|
|
thrust::offset_iterator iter0(v.begin(), &offset);
|
|
|
|
#if _CCCL_COMPILER(MSVC) // MSVC cannot deduce the template arguments from the copy ctor
|
|
decltype(iter0) iter1(iter0);
|
|
#else // _CCCL_COMPILER(MSVC)
|
|
thrust::offset_iterator iter1(iter0);
|
|
#endif // _CCCL_COMPILER(MSVC)
|
|
ASSERT_EQUAL(iter0 == iter1, true);
|
|
ASSERT_EQUAL(*iter0 == *iter1, true);
|
|
|
|
thrust::offset_iterator iter2(v.begin() + 1, &offset);
|
|
ASSERT_EQUAL(iter0 != iter2, true);
|
|
ASSERT_EQUAL(*iter0 != *iter2, true);
|
|
|
|
iter2 = iter0;
|
|
ASSERT_EQUAL(iter0 == iter2, true);
|
|
ASSERT_EQUAL(*iter0 == *iter2, true);
|
|
}
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetIteratorCopyConstructorAndAssignment);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetIteratorIncrement()
|
|
{
|
|
auto test = [](auto iter) {
|
|
ASSERT_EQUAL(*iter, 0);
|
|
iter++;
|
|
ASSERT_EQUAL(*iter, 1);
|
|
iter++;
|
|
iter++;
|
|
ASSERT_EQUAL(*iter, 3);
|
|
iter += 5;
|
|
ASSERT_EQUAL(*iter, 8);
|
|
iter -= 10;
|
|
ASSERT_EQUAL(*iter, -2);
|
|
};
|
|
|
|
const Vector v{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
|
test(thrust::offset_iterator(v.begin() + 1, 1));
|
|
const typename Vector::iterator::difference_type offset = 1;
|
|
test(thrust::offset_iterator(v.begin() + 1, &offset));
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetIteratorIncrement);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetIteratorMutation()
|
|
{
|
|
{
|
|
Vector v{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
|
thrust::offset_iterator it(v.begin() + 1, 1);
|
|
*it = 42;
|
|
++it;
|
|
*it = 43;
|
|
++it.offset();
|
|
*it = 44;
|
|
ASSERT_EQUAL(v, (Vector{-2, -1, 42, 43, 44, 3, 4, 5, 6, 7, 8}));
|
|
}
|
|
{
|
|
Vector v{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
|
typename Vector::iterator::difference_type offset = 1;
|
|
thrust::offset_iterator it(v.begin() + 1, &offset);
|
|
*it = 42;
|
|
++it;
|
|
*it = 43;
|
|
offset = 2;
|
|
*it = 44;
|
|
ASSERT_EQUAL(v, (Vector{-2, -1, 42, 43, 44, 3, 4, 5, 6, 7, 8}));
|
|
}
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetIteratorMutation);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetIteratorComparisonAndDistance()
|
|
{
|
|
auto test = [](auto iter1, auto iter2) {
|
|
ASSERT_EQUAL(iter1 == iter2, true);
|
|
ASSERT_EQUAL(iter1 - iter2, 0);
|
|
ASSERT_EQUAL(::cuda::std::distance(iter1, iter2), 0);
|
|
|
|
iter1++;
|
|
ASSERT_EQUAL(iter1 == iter2, false);
|
|
ASSERT_EQUAL(iter1 - iter2, 1);
|
|
ASSERT_EQUAL(::cuda::std::distance(iter1, iter2), -1);
|
|
|
|
iter2++;
|
|
ASSERT_EQUAL(iter1 == iter2, true);
|
|
ASSERT_EQUAL(iter1 - iter2, 0);
|
|
ASSERT_EQUAL(::cuda::std::distance(iter1, iter2), 0);
|
|
|
|
iter1 += 100;
|
|
iter2 += 100;
|
|
ASSERT_EQUAL(iter1 == iter2, true);
|
|
ASSERT_EQUAL(iter1 - iter2, 0);
|
|
ASSERT_EQUAL(::cuda::std::distance(iter1, iter2), 0);
|
|
|
|
iter1 -= 5;
|
|
ASSERT_EQUAL(iter1 == iter2, false);
|
|
ASSERT_EQUAL(iter1 - iter2, -5);
|
|
ASSERT_EQUAL(::cuda::std::distance(iter1, iter2), 5);
|
|
};
|
|
|
|
Vector v(101);
|
|
test(thrust::offset_iterator(v.begin()), thrust::offset_iterator(v.begin()));
|
|
const typename Vector::iterator::difference_type offset = 0;
|
|
test(thrust::offset_iterator(v.begin(), &offset), thrust::offset_iterator(v.begin(), &offset));
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetIteratorComparisonAndDistance);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetIteratorLateValue()
|
|
{
|
|
typename Vector::difference_type offset;
|
|
Vector v{0, 1, 2, 3, 4, 5, 6, 7, 8};
|
|
thrust::offset_iterator iter(v.begin(), &offset);
|
|
offset = 2; // we provide the offset value **after** constructing the iterator
|
|
ASSERT_EQUAL(*iter, 2);
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetIteratorLateValue);
|
|
|
|
template <typename Vector>
|
|
void TestOffsetIteratorIndirectValueFancyIterator()
|
|
{
|
|
using thrust::placeholders::_1;
|
|
|
|
Vector v{0, 1, 2, 3, 4, 5, 6, 7, 8};
|
|
thrust::device_vector<typename Vector::difference_type> offsets{2};
|
|
auto it = thrust::make_transform_iterator(offsets.begin(), _1 * 3);
|
|
thrust::offset_iterator iter(v.begin(), it);
|
|
ASSERT_EQUAL(*iter, 6);
|
|
}
|
|
DECLARE_VECTOR_UNITTEST(TestOffsetIteratorIndirectValueFancyIterator);
|