1881 lines
64 KiB
C++
1881 lines
64 KiB
C++
//@HEADER
|
|
// ************************************************************************
|
|
//
|
|
// Kokkos v. 4.0
|
|
// Copyright (2022) National Technology & Engineering
|
|
// Solutions of Sandia, LLC (NTESS).
|
|
//
|
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
|
// the U.S. Government retains certain rights in this software.
|
|
//
|
|
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://kokkos.org/LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//@HEADER
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <Kokkos_Core.hpp>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <Kokkos_DynRankView.hpp>
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
namespace Test {
|
|
|
|
template <class T, class... P>
|
|
size_t allocation_count(const Kokkos::DynRankView<T, P...>& view) {
|
|
const size_t card = view.size();
|
|
const size_t alloc = view.span();
|
|
|
|
return card <= alloc ? alloc : 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
template <typename T, class DeviceType>
|
|
struct TestViewOperator {
|
|
using execution_space = DeviceType;
|
|
|
|
static const unsigned N = 100;
|
|
static const unsigned D = 3;
|
|
|
|
using view_type = Kokkos::DynRankView<T, execution_space>;
|
|
|
|
const view_type v1;
|
|
const view_type v2;
|
|
|
|
TestViewOperator() : v1("v1", N, D), v2("v2", N, D) {}
|
|
|
|
static void testit() { Kokkos::parallel_for(N, TestViewOperator()); }
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const unsigned i) const {
|
|
const unsigned X = 0;
|
|
const unsigned Y = 1;
|
|
const unsigned Z = 2;
|
|
|
|
v2(i, X) = v1(i, X);
|
|
v2(i, Y) = v1(i, Y);
|
|
v2(i, Z) = v1(i, Z);
|
|
}
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
template <class DataType, class DeviceType, unsigned Rank>
|
|
struct TestViewOperator_LeftAndRight;
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 7> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2,
|
|
unsigned N3, unsigned N4, unsigned N5,
|
|
unsigned N6)
|
|
: left("left", N0, N1, N2, N3, N4, N5, N6),
|
|
right("right", N0, N1, N2, N3, N4, N5, N6),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3,
|
|
unsigned N4, unsigned N5, unsigned N6) {
|
|
TestViewOperator_LeftAndRight driver(N0, N1, N2, N3, N4, N5, N6);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
long offset;
|
|
|
|
offset = -1;
|
|
for (unsigned i6 = 0; i6 < unsigned(left.extent(6)); ++i6)
|
|
for (unsigned i5 = 0; i5 < unsigned(left.extent(5)); ++i5)
|
|
for (unsigned i4 = 0; i4 < unsigned(left.extent(4)); ++i4)
|
|
for (unsigned i3 = 0; i3 < unsigned(left.extent(3)); ++i3)
|
|
for (unsigned i2 = 0; i2 < unsigned(left.extent(2)); ++i2)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
const long j = &left(i0, i1, i2, i3, i4, i5, i6) -
|
|
&left(0, 0, 0, 0, 0, 0, 0);
|
|
if (j < offset || left_alloc <= j) {
|
|
update |= 1;
|
|
}
|
|
offset = j;
|
|
}
|
|
|
|
offset = -1;
|
|
for (unsigned i0 = 0; i0 < unsigned(right.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(right.extent(1)); ++i1)
|
|
for (unsigned i2 = 0; i2 < unsigned(right.extent(2)); ++i2)
|
|
for (unsigned i3 = 0; i3 < unsigned(right.extent(3)); ++i3)
|
|
for (unsigned i4 = 0; i4 < unsigned(right.extent(4)); ++i4)
|
|
for (unsigned i5 = 0; i5 < unsigned(right.extent(5)); ++i5)
|
|
for (unsigned i6 = 0; i6 < unsigned(right.extent(6)); ++i6) {
|
|
const long j = &right(i0, i1, i2, i3, i4, i5, i6) -
|
|
&right(0, 0, 0, 0, 0, 0, 0);
|
|
if (j < offset || right_alloc <= j) {
|
|
update |= 2;
|
|
}
|
|
offset = j;
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 6> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2,
|
|
unsigned N3, unsigned N4, unsigned N5)
|
|
: left("left", N0, N1, N2, N3, N4, N5),
|
|
right("right", N0, N1, N2, N3, N4, N5),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3,
|
|
unsigned N4, unsigned N5) {
|
|
TestViewOperator_LeftAndRight driver(N0, N1, N2, N3, N4, N5);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
long offset;
|
|
|
|
offset = -1;
|
|
for (unsigned i5 = 0; i5 < unsigned(left.extent(5)); ++i5)
|
|
for (unsigned i4 = 0; i4 < unsigned(left.extent(4)); ++i4)
|
|
for (unsigned i3 = 0; i3 < unsigned(left.extent(3)); ++i3)
|
|
for (unsigned i2 = 0; i2 < unsigned(left.extent(2)); ++i2)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
const long j =
|
|
&left(i0, i1, i2, i3, i4, i5) - &left(0, 0, 0, 0, 0, 0);
|
|
if (j < offset || left_alloc <= j) {
|
|
update |= 1;
|
|
}
|
|
offset = j;
|
|
}
|
|
|
|
offset = -1;
|
|
for (unsigned i0 = 0; i0 < unsigned(right.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(right.extent(1)); ++i1)
|
|
for (unsigned i2 = 0; i2 < unsigned(right.extent(2)); ++i2)
|
|
for (unsigned i3 = 0; i3 < unsigned(right.extent(3)); ++i3)
|
|
for (unsigned i4 = 0; i4 < unsigned(right.extent(4)); ++i4)
|
|
for (unsigned i5 = 0; i5 < unsigned(right.extent(5)); ++i5) {
|
|
const long j =
|
|
&right(i0, i1, i2, i3, i4, i5) - &right(0, 0, 0, 0, 0, 0);
|
|
if (j < offset || right_alloc <= j) {
|
|
update |= 2;
|
|
}
|
|
offset = j;
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 5> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
using stride_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutStride, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
stride_view left_stride;
|
|
stride_view right_stride;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2,
|
|
unsigned N3, unsigned N4)
|
|
: left("left", N0, N1, N2, N3, N4),
|
|
right("right", N0, N1, N2, N3, N4),
|
|
left_stride(left),
|
|
right_stride(right),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3,
|
|
unsigned N4) {
|
|
TestViewOperator_LeftAndRight driver(N0, N1, N2, N3, N4);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
long offset;
|
|
|
|
offset = -1;
|
|
for (unsigned i4 = 0; i4 < unsigned(left.extent(4)); ++i4)
|
|
for (unsigned i3 = 0; i3 < unsigned(left.extent(3)); ++i3)
|
|
for (unsigned i2 = 0; i2 < unsigned(left.extent(2)); ++i2)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
const long j = &left(i0, i1, i2, i3, i4) - &left(0, 0, 0, 0, 0);
|
|
if (j < offset || left_alloc <= j) {
|
|
update |= 1;
|
|
}
|
|
offset = j;
|
|
|
|
if (&left(i0, i1, i2, i3, i4) !=
|
|
&left_stride(i0, i1, i2, i3, i4)) {
|
|
update |= 4;
|
|
}
|
|
}
|
|
|
|
offset = -1;
|
|
for (unsigned i0 = 0; i0 < unsigned(right.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(right.extent(1)); ++i1)
|
|
for (unsigned i2 = 0; i2 < unsigned(right.extent(2)); ++i2)
|
|
for (unsigned i3 = 0; i3 < unsigned(right.extent(3)); ++i3)
|
|
for (unsigned i4 = 0; i4 < unsigned(right.extent(4)); ++i4) {
|
|
const long j = &right(i0, i1, i2, i3, i4) - &right(0, 0, 0, 0, 0);
|
|
if (j < offset || right_alloc <= j) {
|
|
update |= 2;
|
|
}
|
|
offset = j;
|
|
|
|
if (&right(i0, i1, i2, i3, i4) !=
|
|
&right_stride(i0, i1, i2, i3, i4)) {
|
|
update |= 8;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 4> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2,
|
|
unsigned N3)
|
|
: left("left", N0, N1, N2, N3),
|
|
right("right", N0, N1, N2, N3),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3) {
|
|
TestViewOperator_LeftAndRight driver(N0, N1, N2, N3);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
long offset;
|
|
|
|
offset = -1;
|
|
for (unsigned i3 = 0; i3 < unsigned(left.extent(3)); ++i3)
|
|
for (unsigned i2 = 0; i2 < unsigned(left.extent(2)); ++i2)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
const long j = &left(i0, i1, i2, i3) - &left(0, 0, 0, 0);
|
|
if (j < offset || left_alloc <= j) {
|
|
update |= 1;
|
|
}
|
|
offset = j;
|
|
}
|
|
|
|
offset = -1;
|
|
for (unsigned i0 = 0; i0 < unsigned(right.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(right.extent(1)); ++i1)
|
|
for (unsigned i2 = 0; i2 < unsigned(right.extent(2)); ++i2)
|
|
for (unsigned i3 = 0; i3 < unsigned(right.extent(3)); ++i3) {
|
|
const long j = &right(i0, i1, i2, i3) - &right(0, 0, 0, 0);
|
|
if (j < offset || right_alloc <= j) {
|
|
update |= 2;
|
|
}
|
|
offset = j;
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 3> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
using stride_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutStride, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
stride_view left_stride;
|
|
stride_view right_stride;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2)
|
|
: left(std::string("left"), N0, N1, N2),
|
|
right(std::string("right"), N0, N1, N2),
|
|
left_stride(left),
|
|
right_stride(right),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0, unsigned N1, unsigned N2) {
|
|
TestViewOperator_LeftAndRight driver(N0, N1, N2);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
long offset;
|
|
|
|
offset = -1;
|
|
for (unsigned i2 = 0; i2 < unsigned(left.extent(2)); ++i2)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
const long j = &left(i0, i1, i2) - &left(0, 0, 0);
|
|
if (j < offset || left_alloc <= j) {
|
|
update |= 1;
|
|
}
|
|
offset = j;
|
|
|
|
if (&left(i0, i1, i2) != &left_stride(i0, i1, i2)) {
|
|
update |= 4;
|
|
}
|
|
}
|
|
|
|
offset = -1;
|
|
for (unsigned i0 = 0; i0 < unsigned(right.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(right.extent(1)); ++i1)
|
|
for (unsigned i2 = 0; i2 < unsigned(right.extent(2)); ++i2) {
|
|
const long j = &right(i0, i1, i2) - &right(0, 0, 0);
|
|
if (j < offset || right_alloc <= j) {
|
|
update |= 2;
|
|
}
|
|
offset = j;
|
|
|
|
if (&right(i0, i1, i2) != &right_stride(i0, i1, i2)) {
|
|
update |= 8;
|
|
}
|
|
}
|
|
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i2 = 0; i2 < unsigned(left.extent(2)); ++i2) {
|
|
if (&left(i0, i1, i2) != &left(i0, i1, i2, 0, 0, 0, 0)) {
|
|
update |= 3;
|
|
}
|
|
if (&right(i0, i1, i2) != &right(i0, i1, i2, 0, 0, 0, 0)) {
|
|
update |= 3;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 2> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0, unsigned N1)
|
|
: left("left", N0, N1),
|
|
right("right", N0, N1),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0, unsigned N1) {
|
|
TestViewOperator_LeftAndRight driver(N0, N1);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
long offset;
|
|
|
|
offset = -1;
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1)
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
const long j = &left(i0, i1) - &left(0, 0);
|
|
if (j < offset || left_alloc <= j) {
|
|
update |= 1;
|
|
}
|
|
offset = j;
|
|
}
|
|
|
|
offset = -1;
|
|
for (unsigned i0 = 0; i0 < unsigned(right.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(right.extent(1)); ++i1) {
|
|
const long j = &right(i0, i1) - &right(0, 0);
|
|
if (j < offset || right_alloc <= j) {
|
|
update |= 2;
|
|
}
|
|
offset = j;
|
|
}
|
|
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0)
|
|
for (unsigned i1 = 0; i1 < unsigned(left.extent(1)); ++i1) {
|
|
if (&left(i0, i1) != &left(i0, i1, 0, 0, 0, 0, 0)) {
|
|
update |= 3;
|
|
}
|
|
if (&right(i0, i1) != &right(i0, i1, 0, 0, 0, 0, 0)) {
|
|
update |= 3;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class DataType, class DeviceType>
|
|
struct TestViewOperator_LeftAndRight<DataType, DeviceType, 1> {
|
|
using execution_space = DeviceType;
|
|
using memory_space = typename execution_space::memory_space;
|
|
using size_type = typename execution_space::size_type;
|
|
|
|
using value_type = int;
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void join(value_type& update, const value_type& input) {
|
|
update |= input;
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
static void init(value_type& update) { update = 0; }
|
|
|
|
using left_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutLeft, execution_space>;
|
|
|
|
using right_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutRight, execution_space>;
|
|
|
|
using stride_view =
|
|
Kokkos::DynRankView<DataType, Kokkos::LayoutStride, execution_space>;
|
|
|
|
left_view left;
|
|
right_view right;
|
|
stride_view left_stride;
|
|
stride_view right_stride;
|
|
long left_alloc;
|
|
long right_alloc;
|
|
|
|
TestViewOperator_LeftAndRight(unsigned N0)
|
|
: left("left", N0),
|
|
right("right", N0),
|
|
left_stride(left),
|
|
right_stride(right),
|
|
left_alloc(allocation_count(left)),
|
|
right_alloc(allocation_count(right)) {}
|
|
|
|
static void testit(unsigned N0) {
|
|
TestViewOperator_LeftAndRight driver(N0);
|
|
|
|
int error_flag = 0;
|
|
|
|
Kokkos::parallel_reduce(1, driver, error_flag);
|
|
|
|
ASSERT_EQ(error_flag, 0);
|
|
}
|
|
|
|
KOKKOS_INLINE_FUNCTION
|
|
void operator()(const size_type, value_type& update) const {
|
|
for (unsigned i0 = 0; i0 < unsigned(left.extent(0)); ++i0) {
|
|
if (&left(i0) != &left(i0, 0, 0, 0, 0, 0, 0)) {
|
|
update |= 3;
|
|
}
|
|
if (&right(i0) != &right(i0, 0, 0, 0, 0, 0, 0)) {
|
|
update |= 3;
|
|
}
|
|
if (&left(i0) != &left_stride(i0)) {
|
|
update |= 4;
|
|
}
|
|
if (&right(i0) != &right_stride(i0)) {
|
|
update |= 8;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
template <typename T, class DeviceType>
|
|
class TestDynViewAPI {
|
|
public:
|
|
using device = DeviceType;
|
|
|
|
enum { N0 = 1000, N1 = 3, N2 = 5, N3 = 7 };
|
|
|
|
using dView0 = Kokkos::DynRankView<T, device>;
|
|
using const_dView0 = Kokkos::DynRankView<const T, device>;
|
|
|
|
using dView0_unmanaged =
|
|
Kokkos::DynRankView<T, device, Kokkos::MemoryUnmanaged>;
|
|
using host_drv_space = typename dView0::host_mirror_space;
|
|
|
|
using View0 = Kokkos::View<T, device>;
|
|
using View1 = Kokkos::View<T*, device>;
|
|
using View2 = Kokkos::View<T**, device>;
|
|
using View3 = Kokkos::View<T***, device>;
|
|
using View4 = Kokkos::View<T****, device>;
|
|
using View5 = Kokkos::View<T*****, device>;
|
|
using View6 = Kokkos::View<T******, device>;
|
|
using View7 = Kokkos::View<T*******, device>;
|
|
|
|
using host_view_space = typename View0::host_mirror_space;
|
|
|
|
static void run_tests() {
|
|
run_test_resize_realloc<false>();
|
|
run_test_resize_realloc<true>();
|
|
run_test_mirror();
|
|
run_test_mirror_and_copy();
|
|
run_test_scalar();
|
|
run_test();
|
|
run_test_allocated();
|
|
run_test_const();
|
|
run_test_subview();
|
|
run_test_subview_strided();
|
|
run_test_vector();
|
|
run_test_as_view_of_rank_n();
|
|
run_test_layout();
|
|
}
|
|
|
|
static void run_operator_test_rank12345() {
|
|
TestViewOperator<T, device>::testit();
|
|
TestViewOperator_LeftAndRight<int, device, 5>::testit(2, 3, 4, 2, 3);
|
|
TestViewOperator_LeftAndRight<int, device, 4>::testit(2, 3, 4, 2);
|
|
TestViewOperator_LeftAndRight<int, device, 3>::testit(2, 3, 4);
|
|
TestViewOperator_LeftAndRight<int, device, 2>::testit(2, 3);
|
|
TestViewOperator_LeftAndRight<int, device, 1>::testit(2);
|
|
}
|
|
|
|
static void run_operator_test_rank67() {
|
|
TestViewOperator_LeftAndRight<int, device, 7>::testit(2, 3, 4, 2, 3, 4, 2);
|
|
TestViewOperator_LeftAndRight<int, device, 6>::testit(2, 3, 4, 2, 3, 4);
|
|
}
|
|
|
|
template <bool Initialize>
|
|
static void run_test_resize_realloc() {
|
|
dView0 drv0("drv0", 10, 20, 30);
|
|
ASSERT_EQ(drv0.rank(), 3u);
|
|
|
|
if (Initialize)
|
|
Kokkos::resize(Kokkos::WithoutInitializing, drv0, 5, 10);
|
|
else
|
|
Kokkos::resize(drv0, 5, 10);
|
|
ASSERT_EQ(drv0.rank(), 2u);
|
|
ASSERT_EQ(drv0.extent(0), 5u);
|
|
ASSERT_EQ(drv0.extent(1), 10u);
|
|
ASSERT_EQ(drv0.extent(2), 1u);
|
|
|
|
if (Initialize)
|
|
Kokkos::realloc(Kokkos::WithoutInitializing, drv0, 10, 20);
|
|
else
|
|
Kokkos::realloc(drv0, 10, 20);
|
|
ASSERT_EQ(drv0.rank(), 2u);
|
|
ASSERT_EQ(drv0.extent(0), 10u);
|
|
ASSERT_EQ(drv0.extent(1), 20u);
|
|
ASSERT_EQ(drv0.extent(2), 1u);
|
|
}
|
|
|
|
static void run_test_mirror() {
|
|
using view_type = Kokkos::DynRankView<int, host_drv_space>;
|
|
using mirror_type = typename view_type::HostMirror;
|
|
view_type a("a");
|
|
mirror_type am = Kokkos::create_mirror_view(a);
|
|
mirror_type ax = Kokkos::create_mirror(a);
|
|
ASSERT_EQ(&a(), &am());
|
|
ASSERT_EQ(a.rank(), am.rank());
|
|
ASSERT_EQ(ax.rank(), am.rank());
|
|
|
|
{
|
|
Kokkos::DynRankView<double, Kokkos::LayoutLeft, Kokkos::HostSpace> a_h(
|
|
"A", 1000);
|
|
auto a_h2 = Kokkos::create_mirror(Kokkos::HostSpace(), a_h);
|
|
auto a_d = Kokkos::create_mirror(typename device::memory_space(), a_h);
|
|
|
|
int equal_ptr_h_h2 = (a_h.data() == a_h2.data()) ? 1 : 0;
|
|
int equal_ptr_h_d = (a_h.data() == a_d.data()) ? 1 : 0;
|
|
int equal_ptr_h2_d = (a_h2.data() == a_d.data()) ? 1 : 0;
|
|
|
|
ASSERT_EQ(equal_ptr_h_h2, 0);
|
|
ASSERT_EQ(equal_ptr_h_d, 0);
|
|
ASSERT_EQ(equal_ptr_h2_d, 0);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
}
|
|
{
|
|
Kokkos::DynRankView<double, Kokkos::LayoutRight, Kokkos::HostSpace> a_h(
|
|
"A", 1000);
|
|
auto a_h2 = Kokkos::create_mirror(Kokkos::HostSpace(), a_h);
|
|
auto a_d = Kokkos::create_mirror(typename device::memory_space(), a_h);
|
|
|
|
int equal_ptr_h_h2 = (a_h.data() == a_h2.data()) ? 1 : 0;
|
|
int equal_ptr_h_d = (a_h.data() == a_d.data()) ? 1 : 0;
|
|
int equal_ptr_h2_d = (a_h2.data() == a_d.data()) ? 1 : 0;
|
|
|
|
ASSERT_EQ(equal_ptr_h_h2, 0);
|
|
ASSERT_EQ(equal_ptr_h_d, 0);
|
|
ASSERT_EQ(equal_ptr_h2_d, 0);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
}
|
|
|
|
{
|
|
Kokkos::DynRankView<double, Kokkos::LayoutLeft, Kokkos::HostSpace> a_h(
|
|
"A", 1000);
|
|
auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(), a_h);
|
|
auto a_d =
|
|
Kokkos::create_mirror_view(typename device::memory_space(), a_h);
|
|
|
|
int equal_ptr_h_h2 = a_h.data() == a_h2.data() ? 1 : 0;
|
|
int equal_ptr_h_d = a_h.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h2_d = a_h2.data() == a_d.data() ? 1 : 0;
|
|
|
|
int is_same_memspace =
|
|
std::is_same_v<Kokkos::HostSpace, typename device::memory_space> ? 1
|
|
: 0;
|
|
ASSERT_EQ(equal_ptr_h_h2, 1);
|
|
ASSERT_EQ(equal_ptr_h_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h2_d, is_same_memspace);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
}
|
|
{
|
|
Kokkos::DynRankView<double, Kokkos::LayoutRight, Kokkos::HostSpace> a_h(
|
|
"A", 1000);
|
|
auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(), a_h);
|
|
auto a_d =
|
|
Kokkos::create_mirror_view(typename device::memory_space(), a_h);
|
|
|
|
int equal_ptr_h_h2 = a_h.data() == a_h2.data() ? 1 : 0;
|
|
int equal_ptr_h_d = a_h.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h2_d = a_h2.data() == a_d.data() ? 1 : 0;
|
|
|
|
int is_same_memspace =
|
|
std::is_same_v<Kokkos::HostSpace, typename device::memory_space> ? 1
|
|
: 0;
|
|
ASSERT_EQ(equal_ptr_h_h2, 1);
|
|
ASSERT_EQ(equal_ptr_h_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h2_d, is_same_memspace);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
}
|
|
{
|
|
using view_stride_type =
|
|
Kokkos::DynRankView<int, Kokkos::LayoutStride, Kokkos::HostSpace>;
|
|
unsigned order[] = {6, 5, 4, 3, 2, 1, 0},
|
|
dimen[] = {N0, N1, N2, 2, 2, 2, 2}; // LayoutRight equivalent
|
|
view_stride_type a_h(
|
|
"a", Kokkos::LayoutStride::order_dimensions(7, order, dimen));
|
|
auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(), a_h);
|
|
auto a_d =
|
|
Kokkos::create_mirror_view(typename device::memory_space(), a_h);
|
|
|
|
int equal_ptr_h_h2 = a_h.data() == a_h2.data() ? 1 : 0;
|
|
int equal_ptr_h_d = a_h.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h2_d = a_h2.data() == a_d.data() ? 1 : 0;
|
|
|
|
int is_same_memspace =
|
|
std::is_same_v<Kokkos::HostSpace, typename device::memory_space> ? 1
|
|
: 0;
|
|
ASSERT_EQ(equal_ptr_h_h2, 1);
|
|
ASSERT_EQ(equal_ptr_h_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h2_d, is_same_memspace);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
}
|
|
}
|
|
|
|
static void run_test_mirror_and_copy() {
|
|
// LayoutLeft
|
|
{
|
|
Kokkos::DynRankView<double, Kokkos::LayoutLeft, Kokkos::HostSpace> a_org(
|
|
"A", 10);
|
|
a_org(5) = 42.0;
|
|
Kokkos::DynRankView<double, Kokkos::LayoutLeft, Kokkos::HostSpace> a_h =
|
|
a_org;
|
|
auto a_h2 = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), a_h);
|
|
auto a_d = Kokkos::create_mirror_view_and_copy(DeviceType(), a_h);
|
|
auto a_h3 = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), a_d);
|
|
|
|
int equal_ptr_h_h2 = a_h.data() == a_h2.data() ? 1 : 0;
|
|
int equal_ptr_h_d = a_h.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h2_d = a_h2.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h3_d = a_h3.data() == a_d.data() ? 1 : 0;
|
|
|
|
int is_same_memspace =
|
|
std::is_same_v<Kokkos::HostSpace, typename DeviceType::memory_space>
|
|
? 1
|
|
: 0;
|
|
ASSERT_EQ(equal_ptr_h_h2, 1);
|
|
ASSERT_EQ(equal_ptr_h_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h2_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h3_d, is_same_memspace);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h3.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_h3.extent(0));
|
|
ASSERT_EQ(a_h.rank(), a_org.rank());
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_h3.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
ASSERT_EQ(a_org(5), a_h3(5));
|
|
}
|
|
// LayoutRight
|
|
{
|
|
Kokkos::DynRankView<double, Kokkos::LayoutRight, Kokkos::HostSpace> a_org(
|
|
"A", 10);
|
|
a_org(5) = 42.0;
|
|
Kokkos::DynRankView<double, Kokkos::LayoutRight, Kokkos::HostSpace> a_h =
|
|
a_org;
|
|
auto a_h2 = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), a_h);
|
|
auto a_d = Kokkos::create_mirror_view_and_copy(DeviceType(), a_h);
|
|
auto a_h3 = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), a_d);
|
|
|
|
int equal_ptr_h_h2 = a_h.data() == a_h2.data() ? 1 : 0;
|
|
int equal_ptr_h_d = a_h.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h2_d = a_h2.data() == a_d.data() ? 1 : 0;
|
|
int equal_ptr_h3_d = a_h3.data() == a_d.data() ? 1 : 0;
|
|
|
|
int is_same_memspace =
|
|
std::is_same_v<Kokkos::HostSpace, typename DeviceType::memory_space>
|
|
? 1
|
|
: 0;
|
|
ASSERT_EQ(equal_ptr_h_h2, 1);
|
|
ASSERT_EQ(equal_ptr_h_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h2_d, is_same_memspace);
|
|
ASSERT_EQ(equal_ptr_h3_d, is_same_memspace);
|
|
|
|
ASSERT_EQ(a_h.extent(0), a_h3.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_h2.extent(0));
|
|
ASSERT_EQ(a_h.extent(0), a_d.extent(0));
|
|
ASSERT_EQ(a_h.rank(), a_org.rank());
|
|
ASSERT_EQ(a_h.rank(), a_h2.rank());
|
|
ASSERT_EQ(a_h.rank(), a_h3.rank());
|
|
ASSERT_EQ(a_h.rank(), a_d.rank());
|
|
ASSERT_EQ(a_org(5), a_h3(5));
|
|
}
|
|
}
|
|
|
|
static void run_test_as_view_of_rank_n() {
|
|
Kokkos::View<int, Kokkos::HostSpace> error_flag_host("error_flag");
|
|
error_flag_host() = 0;
|
|
auto error_flag =
|
|
Kokkos::create_mirror_view_and_copy(DeviceType(), error_flag_host);
|
|
|
|
dView0 d("d");
|
|
|
|
// Rank 0
|
|
Kokkos::resize(d);
|
|
|
|
auto policy0 = Kokkos::RangePolicy<DeviceType>(DeviceType(), 0, 1);
|
|
|
|
View0 v0 = Kokkos::Impl::as_view_of_rank_n<0>(d);
|
|
// Assign values after calling as_view_of_rank_n() function under
|
|
// test to ensure aliasing
|
|
Kokkos::parallel_for(
|
|
policy0, KOKKOS_LAMBDA(int) { d() = 13; });
|
|
ASSERT_EQ(v0.size(), d.size());
|
|
ASSERT_EQ(v0.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy0, KOKKOS_LAMBDA(int) {
|
|
if (d() != v0()) error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 1
|
|
Kokkos::resize(d, 1);
|
|
|
|
auto policy1 =
|
|
Kokkos::RangePolicy<DeviceType>(DeviceType(), 0, d.extent(0));
|
|
|
|
View1 v1 = Kokkos::Impl::as_view_of_rank_n<1>(d);
|
|
Kokkos::parallel_for(
|
|
policy1, KOKKOS_LAMBDA(int i0) { d(i0) = i0; });
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v1.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v1.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy1, KOKKOS_LAMBDA(int i0) {
|
|
if (d(i0) != v1(i0)) error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 2
|
|
Kokkos::resize(d, 1, 2);
|
|
|
|
auto policy2 = Kokkos::MDRangePolicy<DeviceType, Kokkos::Rank<2>>(
|
|
{0, 0}, {d.extent(0), d.extent(1)});
|
|
|
|
View2 v2 = Kokkos::Impl::as_view_of_rank_n<2>(d);
|
|
Kokkos::parallel_for(
|
|
policy2, KOKKOS_LAMBDA(int i0, int i1) { d(i0, i1) = i0 + 10 * i1; });
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v2.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v2.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy2, KOKKOS_LAMBDA(int i0, int i1) {
|
|
if (d(i0, i1) != v2(i0, i1)) error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 3
|
|
Kokkos::resize(d, 1, 2, 3);
|
|
|
|
auto policy3 = Kokkos::MDRangePolicy<DeviceType, Kokkos::Rank<3>>(
|
|
{0, 0, 0}, {d.extent(0), d.extent(1), d.extent(2)});
|
|
|
|
View3 v3 = Kokkos::Impl::as_view_of_rank_n<3>(d);
|
|
Kokkos::parallel_for(
|
|
policy3, KOKKOS_LAMBDA(int i0, int i1, int i2) {
|
|
d(i0, i1, i2) = i0 + 10 * i1 + 100 * i2;
|
|
});
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v3.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v3.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy3, KOKKOS_LAMBDA(int i0, int i1, int i2) {
|
|
if (d(i0, i1, i2) != v3(i0, i1, i2)) error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 4
|
|
Kokkos::resize(d, 1, 2, 3, 4);
|
|
|
|
auto policy4 = Kokkos::MDRangePolicy<DeviceType, Kokkos::Rank<4>>(
|
|
{0, 0, 0, 0}, {d.extent(0), d.extent(1), d.extent(2), d.extent(3)});
|
|
|
|
View4 v4 = Kokkos::Impl::as_view_of_rank_n<4>(d);
|
|
Kokkos::parallel_for(
|
|
policy4, KOKKOS_LAMBDA(int i0, int i1, int i2, int i3) {
|
|
d(i0, i1, i2, i3) = i0 + 10 * i1 + 100 * i2 + 1000 * i3;
|
|
});
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v4.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v4.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy4, KOKKOS_LAMBDA(int i0, int i1, int i2, int i3) {
|
|
if (d(i0, i1, i2, i3) != v4(i0, i1, i2, i3)) error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 5
|
|
Kokkos::resize(d, 1, 2, 3, 4, 5);
|
|
|
|
auto policy5 = Kokkos::MDRangePolicy<DeviceType, Kokkos::Rank<5>>(
|
|
{0, 0, 0, 0, 0},
|
|
{d.extent(0), d.extent(1), d.extent(2), d.extent(3), d.extent(4)});
|
|
|
|
View5 v5 = Kokkos::Impl::as_view_of_rank_n<5>(d);
|
|
Kokkos::parallel_for(
|
|
policy5, KOKKOS_LAMBDA(int i0, int i1, int i2, int i3, int i4) {
|
|
d(i0, i1, i2, i3, i4) =
|
|
i0 + 10 * i1 + 100 * i2 + 1000 * i3 + 10000 * i4;
|
|
});
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v5.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v5.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy5, KOKKOS_LAMBDA(int i0, int i1, int i2, int i3, int i4) {
|
|
if (d(i0, i1, i2, i3, i4) != v5(i0, i1, i2, i3, i4)) error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 6
|
|
Kokkos::resize(d, 1, 2, 3, 4, 5, 6);
|
|
|
|
auto policy6 = Kokkos::MDRangePolicy<DeviceType, Kokkos::Rank<6>>(
|
|
{0, 0, 0, 0, 0, 0}, {d.extent(0), d.extent(1), d.extent(2), d.extent(3),
|
|
d.extent(4), d.extent(5)});
|
|
|
|
View6 v6 = Kokkos::Impl::as_view_of_rank_n<6>(d);
|
|
Kokkos::parallel_for(
|
|
policy6, KOKKOS_LAMBDA(int i0, int i1, int i2, int i3, int i4, int i5) {
|
|
d(i0, i1, i2, i3, i4, i5) =
|
|
i0 + 10 * i1 + 100 * i2 + 1000 * i3 + 10000 * i4 + 100000 * i5;
|
|
});
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v6.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v6.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy6, KOKKOS_LAMBDA(int i0, int i1, int i2, int i3, int i4, int i5) {
|
|
if (d(i0, i1, i2, i3, i4, i5) != v6(i0, i1, i2, i3, i4, i5))
|
|
error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
|
|
// Rank 7
|
|
Kokkos::resize(d, 1, 2, 3, 4, 5, 6, 7);
|
|
|
|
// MDRangePolicy only accepts Rank < 7
|
|
#if 0
|
|
auto policy7 = Kokkos::MDRangePolicy<DeviceType, Kokkos::Rank<7>>(
|
|
{0, 0, 0, 0, 0, 0, 0},
|
|
{d.extent(0), d.extent(1), d.extent(2), d.extent(3), d.extent(4),
|
|
d.extent(5), d.extent(6)});
|
|
|
|
View7 v7 = Kokkos::Impl::as_view_of_rank_n<7>(d);
|
|
Kokkos::parallel_for(
|
|
policy7,
|
|
KOKKOS_LAMBDA(int i0, int i1, int i2, int i3, int i4, int i5, int i6) {
|
|
d(i0, i1, i2, i3, i4, i5, i6) = i0 + 10 * i1 + 100 * i2 + 1000 * i3 +
|
|
10000 * i4 + 100000 * i5 +
|
|
1000000 * i6;
|
|
});
|
|
for (unsigned int rank = 0; rank < d.rank(); ++rank)
|
|
ASSERT_EQ(v7.extent(rank), d.extent(rank));
|
|
ASSERT_EQ(v7.data(), d.data());
|
|
Kokkos::parallel_for(
|
|
policy7,
|
|
KOKKOS_LAMBDA(int i0, int i1, int i2, int i3, int i4, int i5, int i6) {
|
|
if (d(i0, i1, i2, i3, i4, i5, i6) != v7(i0, i1, i2, i3, i4, i5, i6))
|
|
error_flag() = 1;
|
|
});
|
|
Kokkos::deep_copy(error_flag_host, error_flag);
|
|
ASSERT_EQ(error_flag_host(), 0);
|
|
#endif // MDRangePolict Rank < 7
|
|
}
|
|
|
|
static void run_test_scalar() {
|
|
using hView0 = typename dView0::HostMirror; // HostMirror of DynRankView is
|
|
// a DynRankView
|
|
|
|
dView0 dx, dy;
|
|
hView0 hx, hy;
|
|
|
|
dx = dView0("dx");
|
|
dy = dView0("dy");
|
|
|
|
hx = Kokkos::create_mirror(dx);
|
|
hy = Kokkos::create_mirror(dy);
|
|
|
|
hx() = 1;
|
|
|
|
Kokkos::deep_copy(dx, hx);
|
|
Kokkos::deep_copy(dy, dx);
|
|
Kokkos::deep_copy(hy, dy);
|
|
|
|
ASSERT_EQ(hx(), hy());
|
|
ASSERT_EQ(dx.rank(), hx.rank());
|
|
ASSERT_EQ(dy.rank(), hy.rank());
|
|
|
|
// View - DynRankView Interoperability tests
|
|
// deep_copy DynRankView to View
|
|
View0 vx("vx");
|
|
Kokkos::deep_copy(vx, dx);
|
|
ASSERT_EQ(rank(dx), rank(vx));
|
|
|
|
View0 vy("vy");
|
|
Kokkos::deep_copy(vy, dy);
|
|
ASSERT_EQ(rank(dy), rank(vy));
|
|
|
|
// deep_copy View to DynRankView
|
|
dView0 dxx("dxx");
|
|
Kokkos::deep_copy(dxx, vx);
|
|
ASSERT_EQ(rank(dxx), rank(vx));
|
|
|
|
View7 vcast = dx.ConstDownCast();
|
|
ASSERT_EQ(dx.extent(0), vcast.extent(0));
|
|
ASSERT_EQ(dx.extent(1), vcast.extent(1));
|
|
ASSERT_EQ(dx.extent(2), vcast.extent(2));
|
|
ASSERT_EQ(dx.extent(3), vcast.extent(3));
|
|
ASSERT_EQ(dx.extent(4), vcast.extent(4));
|
|
|
|
View7 vcast1(dy.ConstDownCast());
|
|
ASSERT_EQ(dy.extent(0), vcast1.extent(0));
|
|
ASSERT_EQ(dy.extent(1), vcast1.extent(1));
|
|
ASSERT_EQ(dy.extent(2), vcast1.extent(2));
|
|
ASSERT_EQ(dy.extent(3), vcast1.extent(3));
|
|
ASSERT_EQ(dy.extent(4), vcast1.extent(4));
|
|
|
|
// View - DynRankView Interoperability tests
|
|
// copy View to DynRankView
|
|
dView0 dfromvx(vx);
|
|
auto hmx = Kokkos::create_mirror_view(dfromvx);
|
|
Kokkos::deep_copy(hmx, dfromvx);
|
|
auto hvx = Kokkos::create_mirror_view(vx);
|
|
Kokkos::deep_copy(hvx, vx);
|
|
ASSERT_EQ(rank(hvx), rank(hmx));
|
|
ASSERT_EQ(hvx.extent(0), hmx.extent(0));
|
|
ASSERT_EQ(hvx.extent(1), hmx.extent(1));
|
|
|
|
// copy-assign View to DynRankView
|
|
dView0 dfromvy = vy;
|
|
auto hmy = Kokkos::create_mirror_view(dfromvy);
|
|
Kokkos::deep_copy(hmy, dfromvy);
|
|
auto hvy = Kokkos::create_mirror_view(vy);
|
|
Kokkos::deep_copy(hvy, vy);
|
|
ASSERT_EQ(rank(hvy), rank(hmy));
|
|
ASSERT_EQ(hvy.extent(0), hmy.extent(0));
|
|
ASSERT_EQ(hvy.extent(1), hmy.extent(1));
|
|
|
|
View7 vtest1("vtest1", 2, 2, 2, 2, 2, 2, 2);
|
|
dView0 dfromv1(vtest1);
|
|
ASSERT_EQ(dfromv1.rank(), vtest1.rank);
|
|
ASSERT_EQ(dfromv1.extent(0), vtest1.extent(0));
|
|
ASSERT_EQ(dfromv1.extent(1), vtest1.extent(1));
|
|
ASSERT_EQ(dfromv1.use_count(), vtest1.use_count());
|
|
|
|
dView0 dfromv2(vcast);
|
|
ASSERT_EQ(dfromv2.rank(), vcast.rank);
|
|
ASSERT_EQ(dfromv2.extent(0), vcast.extent(0));
|
|
ASSERT_EQ(dfromv2.extent(1), vcast.extent(1));
|
|
ASSERT_EQ(dfromv2.use_count(), vcast.use_count());
|
|
|
|
dView0 dfromv3 = vcast1;
|
|
ASSERT_EQ(dfromv3.rank(), vcast1.rank);
|
|
ASSERT_EQ(dfromv3.extent(0), vcast1.extent(0));
|
|
ASSERT_EQ(dfromv3.extent(1), vcast1.extent(1));
|
|
ASSERT_EQ(dfromv3.use_count(), vcast1.use_count());
|
|
}
|
|
|
|
static void run_test() {
|
|
// mfh 14 Feb 2014: This test doesn't actually create instances of
|
|
// these types. In order to avoid "unused type alias"
|
|
// warnings, we declare empty instances of these types, with the
|
|
// usual "(void)" marker to avoid compiler warnings for unused
|
|
// variables.
|
|
|
|
using hView0 = typename dView0::HostMirror;
|
|
|
|
{
|
|
hView0 thing;
|
|
(void)thing;
|
|
}
|
|
|
|
dView0 d_uninitialized(
|
|
Kokkos::view_alloc(Kokkos::WithoutInitializing, "uninit"), 10, 20);
|
|
ASSERT_NE(d_uninitialized.data(), nullptr);
|
|
ASSERT_EQ(d_uninitialized.rank(), 2u);
|
|
ASSERT_EQ(d_uninitialized.extent(0), 10u);
|
|
ASSERT_EQ(d_uninitialized.extent(1), 20u);
|
|
ASSERT_EQ(d_uninitialized.extent(2), 1u);
|
|
|
|
dView0 dx, dy, dz;
|
|
hView0 hx, hy, hz;
|
|
|
|
ASSERT_TRUE(Kokkos::is_dyn_rank_view<dView0>::value);
|
|
ASSERT_FALSE(Kokkos::is_dyn_rank_view<Kokkos::View<double>>::value);
|
|
|
|
ASSERT_EQ(dx.data(), nullptr); // Okay with UVM
|
|
ASSERT_EQ(dy.data(), nullptr); // Okay with UVM
|
|
ASSERT_EQ(dz.data(), nullptr); // Okay with UVM
|
|
ASSERT_EQ(hx.data(), nullptr);
|
|
ASSERT_EQ(hy.data(), nullptr);
|
|
ASSERT_EQ(hz.data(), nullptr);
|
|
ASSERT_EQ(dx.extent(0), 0u); // Okay with UVM
|
|
ASSERT_EQ(dy.extent(0), 0u); // Okay with UVM
|
|
ASSERT_EQ(dz.extent(0), 0u); // Okay with UVM
|
|
ASSERT_EQ(hx.extent(0), 0u);
|
|
ASSERT_EQ(hy.extent(0), 0u);
|
|
ASSERT_EQ(hz.extent(0), 0u);
|
|
ASSERT_EQ(dx.rank(), 0u); // Okay with UVM
|
|
ASSERT_EQ(hx.rank(), 0u);
|
|
|
|
dx = dView0("dx", N1, N2, N3);
|
|
dy = dView0("dy", N1, N2, N3);
|
|
|
|
hx = hView0("hx", N1, N2, N3);
|
|
hy = hView0("hy", N1, N2, N3);
|
|
|
|
ASSERT_EQ(dx.extent(0), unsigned(N1)); // Okay with UVM
|
|
ASSERT_EQ(dy.extent(0), unsigned(N1)); // Okay with UVM
|
|
ASSERT_EQ(hx.extent(0), unsigned(N1));
|
|
ASSERT_EQ(hy.extent(0), unsigned(N1));
|
|
ASSERT_EQ(dx.rank(), 3u); // Okay with UVM
|
|
ASSERT_EQ(hx.rank(), 3u);
|
|
|
|
dx = dView0("dx", N0, N1, N2, N3);
|
|
dy = dView0("dy", N0, N1, N2, N3);
|
|
hx = hView0("hx", N0, N1, N2, N3);
|
|
hy = hView0("hy", N0, N1, N2, N3);
|
|
|
|
ASSERT_EQ(dx.extent(0), unsigned(N0));
|
|
ASSERT_EQ(dy.extent(0), unsigned(N0));
|
|
ASSERT_EQ(hx.extent(0), unsigned(N0));
|
|
ASSERT_EQ(hy.extent(0), unsigned(N0));
|
|
ASSERT_EQ(dx.rank(), 4u);
|
|
ASSERT_EQ(dy.rank(), 4u);
|
|
ASSERT_EQ(hx.rank(), 4u);
|
|
ASSERT_EQ(hy.rank(), 4u);
|
|
|
|
ASSERT_EQ(dx.use_count(), 1);
|
|
|
|
dView0_unmanaged unmanaged_dx = dx;
|
|
ASSERT_EQ(dx.use_count(), 1);
|
|
|
|
dView0_unmanaged unmanaged_from_ptr_dx = dView0_unmanaged(
|
|
dx.data(), dx.extent(0), dx.extent(1), dx.extent(2), dx.extent(3));
|
|
|
|
{
|
|
// Destruction of this view should be harmless
|
|
const_dView0 unmanaged_from_ptr_const_dx(
|
|
dx.data(), dx.extent(0), dx.extent(1), dx.extent(2), dx.extent(3));
|
|
}
|
|
|
|
const_dView0 const_dx = dx;
|
|
ASSERT_EQ(dx.use_count(), 2);
|
|
|
|
{
|
|
const_dView0 const_dx2;
|
|
const_dx2 = const_dx;
|
|
ASSERT_EQ(dx.use_count(), 3);
|
|
|
|
const_dx2 = dy;
|
|
ASSERT_EQ(dx.use_count(), 2);
|
|
|
|
const_dView0 const_dx3(dx);
|
|
ASSERT_EQ(dx.use_count(), 3);
|
|
|
|
dView0_unmanaged dx4_unmanaged(dx);
|
|
ASSERT_EQ(dx.use_count(), 3);
|
|
}
|
|
|
|
ASSERT_EQ(dx.use_count(), 2);
|
|
|
|
ASSERT_NE(dx.data(), nullptr);
|
|
ASSERT_NE(const_dx.data(), nullptr);
|
|
ASSERT_NE(unmanaged_dx.data(), nullptr);
|
|
ASSERT_NE(unmanaged_from_ptr_dx.data(), nullptr);
|
|
ASSERT_NE(dy.data(), nullptr);
|
|
ASSERT_NE(dx, dy);
|
|
|
|
ASSERT_EQ(dx.extent(0), unsigned(N0));
|
|
ASSERT_EQ(dx.extent(1), unsigned(N1));
|
|
ASSERT_EQ(dx.extent(2), unsigned(N2));
|
|
ASSERT_EQ(dx.extent(3), unsigned(N3));
|
|
|
|
ASSERT_EQ(dy.extent(0), unsigned(N0));
|
|
ASSERT_EQ(dy.extent(1), unsigned(N1));
|
|
ASSERT_EQ(dy.extent(2), unsigned(N2));
|
|
ASSERT_EQ(dy.extent(3), unsigned(N3));
|
|
|
|
ASSERT_EQ(unmanaged_from_ptr_dx.span(),
|
|
unsigned(N0) * unsigned(N1) * unsigned(N2) * unsigned(N3));
|
|
|
|
hx = Kokkos::create_mirror(dx);
|
|
hy = Kokkos::create_mirror(dy);
|
|
|
|
ASSERT_EQ(hx.rank(), dx.rank());
|
|
ASSERT_EQ(hy.rank(), dy.rank());
|
|
|
|
ASSERT_EQ(hx.extent(0), unsigned(N0));
|
|
ASSERT_EQ(hx.extent(1), unsigned(N1));
|
|
ASSERT_EQ(hx.extent(2), unsigned(N2));
|
|
ASSERT_EQ(hx.extent(3), unsigned(N3));
|
|
|
|
ASSERT_EQ(hy.extent(0), unsigned(N0));
|
|
ASSERT_EQ(hy.extent(1), unsigned(N1));
|
|
ASSERT_EQ(hy.extent(2), unsigned(N2));
|
|
ASSERT_EQ(hy.extent(3), unsigned(N3));
|
|
|
|
// T v1 = hx() ; // Generates compile error as intended
|
|
// T v2 = hx(0,0) ; // Generates compile error as intended
|
|
// hx(0,0) = v2 ; // Generates compile error as intended
|
|
|
|
#if 0 /* Asynchronous deep copies not implemented for dynamic rank view */
|
|
// Testing with asynchronous deep copy with respect to device
|
|
{
|
|
size_t count = 0 ;
|
|
for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
|
|
for ( size_t i1 = 0 ; i1 < hx.extent(1) ; ++i1 ) {
|
|
for ( size_t i2 = 0 ; i2 < hx.extent(2) ; ++i2 ) {
|
|
for ( size_t i3 = 0 ; i3 < hx.extent(3) ; ++i3 ) {
|
|
hx(ip,i1,i2,i3) = ++count ;
|
|
}}}}
|
|
|
|
|
|
Kokkos::deep_copy(typename hView0::execution_space(), dx , hx );
|
|
Kokkos::deep_copy(typename hView0::execution_space(), dy , dx );
|
|
Kokkos::deep_copy(typename hView0::execution_space(), hy , dy );
|
|
|
|
for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
|
|
for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
|
|
for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
|
|
for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
|
|
{ ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
|
|
}}}}
|
|
|
|
Kokkos::deep_copy(typename hView0::execution_space(), dx , T(0) );
|
|
Kokkos::deep_copy(typename hView0::execution_space(), hx , dx );
|
|
|
|
for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
|
|
for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
|
|
for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
|
|
for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
|
|
{ ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
|
|
}}}}
|
|
}
|
|
|
|
// Testing with asynchronous deep copy with respect to host
|
|
{
|
|
size_t count = 0 ;
|
|
for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
|
|
for ( size_t i1 = 0 ; i1 < hx.extent(1) ; ++i1 ) {
|
|
for ( size_t i2 = 0 ; i2 < hx.extent(2) ; ++i2 ) {
|
|
for ( size_t i3 = 0 ; i3 < hx.extent(3) ; ++i3 ) {
|
|
hx(ip,i1,i2,i3) = ++count ;
|
|
}}}}
|
|
|
|
Kokkos::deep_copy(typename dView0::execution_space(), dx , hx );
|
|
Kokkos::deep_copy(typename dView0::execution_space(), dy , dx );
|
|
Kokkos::deep_copy(typename dView0::execution_space(), hy , dy );
|
|
|
|
for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
|
|
for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
|
|
for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
|
|
for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
|
|
{ ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
|
|
}}}}
|
|
|
|
Kokkos::deep_copy(typename dView0::execution_space(), dx , T(0) );
|
|
Kokkos::deep_copy(typename dView0::execution_space(), hx , dx );
|
|
|
|
for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
|
|
for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
|
|
for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
|
|
for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
|
|
{ ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
|
|
}}}}
|
|
}
|
|
#endif
|
|
|
|
// Testing with synchronous deep copy
|
|
{
|
|
size_t count = 0;
|
|
for (size_t ip = 0; ip < N0; ++ip) {
|
|
for (size_t i1 = 0; i1 < hx.extent(1); ++i1) {
|
|
for (size_t i2 = 0; i2 < hx.extent(2); ++i2) {
|
|
for (size_t i3 = 0; i3 < hx.extent(3); ++i3) {
|
|
hx(ip, i1, i2, i3) = ++count;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Kokkos::deep_copy(dx, hx);
|
|
Kokkos::deep_copy(dy, dx);
|
|
Kokkos::deep_copy(hy, dy);
|
|
Kokkos::fence();
|
|
|
|
for (size_t ip = 0; ip < N0; ++ip) {
|
|
for (size_t i1 = 0; i1 < N1; ++i1) {
|
|
for (size_t i2 = 0; i2 < N2; ++i2) {
|
|
for (size_t i3 = 0; i3 < N3; ++i3) {
|
|
{
|
|
ASSERT_EQ(hx(ip, i1, i2, i3), hy(ip, i1, i2, i3));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Kokkos::deep_copy(dx, T(0));
|
|
Kokkos::deep_copy(hx, dx);
|
|
Kokkos::fence();
|
|
|
|
for (size_t ip = 0; ip < N0; ++ip) {
|
|
for (size_t i1 = 0; i1 < N1; ++i1) {
|
|
for (size_t i2 = 0; i2 < N2; ++i2) {
|
|
for (size_t i3 = 0; i3 < N3; ++i3) {
|
|
{
|
|
ASSERT_EQ(hx(ip, i1, i2, i3), T(0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// ASSERT_EQ( hx(0,0,0,0,0,0,0,0) , T(0) ); //Test rank8 op behaves
|
|
// properly - if implemented
|
|
}
|
|
|
|
dz = dx;
|
|
ASSERT_EQ(dx, dz);
|
|
ASSERT_NE(dy, dz);
|
|
dz = dy;
|
|
ASSERT_EQ(dy, dz);
|
|
ASSERT_NE(dx, dz);
|
|
|
|
dx = dView0();
|
|
ASSERT_EQ(dx.data(), nullptr);
|
|
ASSERT_NE(dy.data(), nullptr);
|
|
ASSERT_NE(dz.data(), nullptr);
|
|
dy = dView0();
|
|
ASSERT_EQ(dx.data(), nullptr);
|
|
ASSERT_EQ(dy.data(), nullptr);
|
|
ASSERT_NE(dz.data(), nullptr);
|
|
dz = dView0();
|
|
ASSERT_EQ(dx.data(), nullptr);
|
|
ASSERT_EQ(dy.data(), nullptr);
|
|
ASSERT_EQ(dz.data(), nullptr);
|
|
|
|
// View - DynRankView Interoperability tests
|
|
// deep_copy from view to dynrankview
|
|
constexpr size_t testdim = 4;
|
|
dView0 dxx("dxx", testdim);
|
|
View1 vxx("vxx", testdim);
|
|
auto hvxx = Kokkos::create_mirror_view(vxx);
|
|
for (size_t i = 0; i < testdim; ++i) {
|
|
hvxx(i) = i;
|
|
}
|
|
Kokkos::deep_copy(vxx, hvxx);
|
|
Kokkos::deep_copy(dxx, vxx);
|
|
auto hdxx = Kokkos::create_mirror_view(dxx);
|
|
Kokkos::deep_copy(hdxx, dxx);
|
|
for (size_t i = 0; i < testdim; ++i) {
|
|
ASSERT_EQ(hvxx(i), hdxx(i));
|
|
}
|
|
|
|
ASSERT_EQ(rank(hdxx), rank(hvxx));
|
|
ASSERT_EQ(hdxx.extent(0), testdim);
|
|
ASSERT_EQ(hdxx.extent(0), hvxx.extent(0));
|
|
|
|
// deep_copy from dynrankview to view
|
|
View1 vdxx("vdxx", testdim);
|
|
auto hvdxx = Kokkos::create_mirror_view(vdxx);
|
|
Kokkos::deep_copy(hvdxx, hdxx);
|
|
ASSERT_EQ(rank(hdxx), rank(hvdxx));
|
|
ASSERT_EQ(hvdxx.extent(0), testdim);
|
|
ASSERT_EQ(hdxx.extent(0), hvdxx.extent(0));
|
|
for (size_t i = 0; i < testdim; ++i) {
|
|
ASSERT_EQ(hvxx(i), hvdxx(i));
|
|
}
|
|
}
|
|
|
|
using DataType = T;
|
|
|
|
static void check_auto_conversion_to_const(
|
|
const Kokkos::DynRankView<const DataType, device>& arg_const,
|
|
const Kokkos::DynRankView<DataType, device>& arg) {
|
|
ASSERT_EQ(arg_const, arg);
|
|
}
|
|
|
|
static void run_test_allocated() {
|
|
using device_type = Kokkos::DynRankView<DataType, device>;
|
|
|
|
const int N1 = 100;
|
|
const int N2 = 10;
|
|
|
|
device_type d1;
|
|
ASSERT_FALSE(d1.is_allocated());
|
|
|
|
d1 = device_type("d1", N1, N2);
|
|
device_type d2(d1);
|
|
device_type d3("d3", N1);
|
|
ASSERT_TRUE(d1.is_allocated());
|
|
ASSERT_TRUE(d2.is_allocated());
|
|
ASSERT_TRUE(d3.is_allocated());
|
|
}
|
|
|
|
static void run_test_const() {
|
|
using typeX = Kokkos::DynRankView<DataType, device>;
|
|
using const_typeX = Kokkos::DynRankView<const DataType, device>;
|
|
using const_typeR =
|
|
Kokkos::DynRankView<const DataType, device, Kokkos::MemoryRandomAccess>;
|
|
typeX x("X", 2);
|
|
const_typeX xc = x;
|
|
const_typeR xr = x;
|
|
|
|
ASSERT_EQ(xc, x);
|
|
ASSERT_EQ(x, xc);
|
|
|
|
// For CUDA the constant random access View does not return
|
|
// an lvalue reference due to retrieving through texture cache
|
|
// therefore not allowed to query the underlying pointer.
|
|
#if defined(KOKKOS_ENABLE_CUDA)
|
|
if (!std::is_same_v<typename device::execution_space, Kokkos::Cuda>)
|
|
#endif
|
|
{
|
|
ASSERT_EQ(x.data(), xr.data());
|
|
}
|
|
|
|
// typeX xf = xc ; // setting non-const from const must not compile
|
|
|
|
check_auto_conversion_to_const(x, x);
|
|
}
|
|
|
|
static void run_test_subview() {
|
|
using cdView = Kokkos::DynRankView<const T, device>;
|
|
using dView = Kokkos::DynRankView<T, device>;
|
|
// LayoutStride required for all returned DynRankView subdynrankview's
|
|
using sdView = Kokkos::DynRankView<T, Kokkos::LayoutStride, device>;
|
|
|
|
dView0 d0("d0");
|
|
cdView s0 = d0;
|
|
|
|
// N0 = 1000,N1 = 3,N2 = 5,N3 = 7
|
|
unsigned order[] = {6, 5, 4, 3, 2, 1, 0},
|
|
dimen[] = {N0, N1, N2, 2, 2, 2, 2}; // LayoutRight equivalent
|
|
sdView d7("d7", Kokkos::LayoutStride::order_dimensions(7, order, dimen));
|
|
ASSERT_EQ(d7.rank(), 7u);
|
|
|
|
sdView ds0 = Kokkos::subdynrankview(d7, 1, 1, 1, 1, 1, 1, 1);
|
|
ASSERT_EQ(ds0.rank(), 0u);
|
|
|
|
// Basic test - ALL
|
|
sdView dsALL = Kokkos::subdynrankview(
|
|
d7, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
|
|
ASSERT_EQ(dsALL.rank(), 7u);
|
|
|
|
// Send a value to final rank returning rank 6 subview
|
|
sdView dsm1 =
|
|
Kokkos::subdynrankview(d7, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), 1);
|
|
ASSERT_EQ(dsm1.rank(), 6u);
|
|
|
|
// Send a std::pair as argument to a rank
|
|
sdView dssp = Kokkos::subdynrankview(
|
|
d7, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(), std::pair<unsigned, unsigned>(1, 2));
|
|
ASSERT_EQ(dssp.rank(), 7u);
|
|
|
|
// Send a kokkos::pair as argument to a rank; take default layout as input
|
|
dView0 dd0("dd0", N0, N1, N2, 2, 2, 2, 2); // default layout
|
|
ASSERT_EQ(dd0.rank(), 7u);
|
|
sdView dtkp = Kokkos::subdynrankview(
|
|
dd0, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(), Kokkos::pair<unsigned, unsigned>(0, 1));
|
|
ASSERT_EQ(dtkp.rank(), 7u);
|
|
|
|
// Return rank 7 subview, taking a pair as one argument, layout stride input
|
|
sdView ds7 = Kokkos::subdynrankview(
|
|
d7, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(), Kokkos::pair<unsigned, unsigned>(0, 1));
|
|
ASSERT_EQ(ds7.rank(), 7u);
|
|
|
|
// Default Layout DynRankView
|
|
dView dv6("dv6", N0, N1, N2, N3, 2, 2);
|
|
ASSERT_EQ(dv6.rank(), 6u);
|
|
|
|
// DynRankView with LayoutRight
|
|
using drView = Kokkos::DynRankView<T, Kokkos::LayoutRight, device>;
|
|
drView dr5("dr5", N0, N1, N2, 2, 2);
|
|
ASSERT_EQ(dr5.rank(), 5u);
|
|
|
|
// LayoutStride but arranged as LayoutRight
|
|
// NOTE: unused arg_layout dimensions must be set toKOKKOS_INVALID_INDEX so
|
|
// that
|
|
// rank deduction can properly take place
|
|
unsigned order5[] = {4, 3, 2, 1, 0}, dimen5[] = {N0, N1, N2, 2, 2};
|
|
Kokkos::LayoutStride ls =
|
|
Kokkos::LayoutStride::order_dimensions(5, order5, dimen5);
|
|
ls.dimension[5] = KOKKOS_INVALID_INDEX;
|
|
ls.dimension[6] = KOKKOS_INVALID_INDEX;
|
|
ls.dimension[7] = KOKKOS_INVALID_INDEX;
|
|
sdView d5("d5", ls);
|
|
ASSERT_EQ(d5.rank(), 5u);
|
|
|
|
// LayoutStride arranged as LayoutRight - commented out as example that
|
|
// fails unit test
|
|
// unsigned order5[] = { 4,3,2,1,0 }, dimen5[] = { N0, N1, N2, 2, 2 };
|
|
// sdView d5( "d5" , Kokkos::LayoutStride::order_dimensions(5, order5,
|
|
// dimen5) );
|
|
//
|
|
// Fails the following unit test:
|
|
// ASSERT_EQ( d5.rank() , dr5.rank() );
|
|
//
|
|
// Explanation: In construction of the Kokkos::LayoutStride below, since
|
|
// the
|
|
// remaining dimensions are not specified, they will default to values of
|
|
// 0 rather thanKOKKOS_INVALID_INDEX.
|
|
// When passed to the DynRankView constructor the default dimensions (of 0)
|
|
// will be counted toward the dynamic rank and returning an incorrect
|
|
// value (i.e. rank 7 rather than 5).
|
|
|
|
// Check LayoutRight dr5 and LayoutStride d5 dimensions agree (as they
|
|
// should)
|
|
ASSERT_EQ(d5.extent(0), dr5.extent(0));
|
|
ASSERT_EQ(d5.extent(1), dr5.extent(1));
|
|
ASSERT_EQ(d5.extent(2), dr5.extent(2));
|
|
ASSERT_EQ(d5.extent(3), dr5.extent(3));
|
|
ASSERT_EQ(d5.extent(4), dr5.extent(4));
|
|
ASSERT_EQ(d5.extent(5), dr5.extent(5));
|
|
ASSERT_EQ(d5.rank(), dr5.rank());
|
|
|
|
// Rank 5 subview of rank 5 dynamic rank view, layout stride input
|
|
sdView ds5 = Kokkos::subdynrankview(d5, Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::pair<unsigned, unsigned>(0, 1));
|
|
ASSERT_EQ(ds5.rank(), 5u);
|
|
|
|
// Pass in extra ALL arguments beyond the rank of the DynRank View.
|
|
// This behavior is allowed - ignore the extra ALL arguments when
|
|
// the src.rank() < number of arguments, but be careful!
|
|
sdView ds5plus = Kokkos::subdynrankview(
|
|
d5, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::pair<unsigned, unsigned>(0, 1), Kokkos::ALL());
|
|
|
|
ASSERT_EQ(ds5.rank(), ds5plus.rank());
|
|
ASSERT_EQ(ds5.extent(0), ds5plus.extent(0));
|
|
ASSERT_EQ(ds5.extent(4), ds5plus.extent(4));
|
|
ASSERT_EQ(ds5.extent(5), ds5plus.extent(5));
|
|
|
|
#if (!defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_CUDA_UVM)) && \
|
|
!defined(KOKKOS_ENABLE_HIP) && !defined(KOKKOS_ENABLE_SYCL)
|
|
ASSERT_EQ(&ds5(1, 1, 1, 1, 0) - &ds5plus(1, 1, 1, 1, 0), 0);
|
|
ASSERT_EQ(&ds5(1, 1, 1, 1, 0, 0) - &ds5plus(1, 1, 1, 1, 0, 0),
|
|
0); // passing argument to rank beyond the view's rank is allowed
|
|
// iff it is a 0.
|
|
#endif
|
|
|
|
// Similar test to rank 5 above, but create rank 4 subview
|
|
// Check that the rank contracts (ds4 and ds4plus) and that subdynrankview
|
|
// can accept extra args (ds4plus)
|
|
sdView ds4 = Kokkos::subdynrankview(d5, Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), Kokkos::ALL(), 0);
|
|
sdView ds4plus =
|
|
Kokkos::subdynrankview(d5, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL(),
|
|
Kokkos::ALL(), 0, Kokkos::ALL());
|
|
|
|
ASSERT_EQ(ds4.rank(), ds4plus.rank());
|
|
ASSERT_EQ(ds4.rank(), 4u);
|
|
ASSERT_EQ(ds4.extent(0), ds4plus.extent(0));
|
|
ASSERT_EQ(ds4.extent(4), ds4plus.extent(4));
|
|
ASSERT_EQ(ds4.extent(5), ds4plus.extent(5));
|
|
}
|
|
|
|
static void run_test_subview_strided() {
|
|
using drview_left =
|
|
Kokkos::DynRankView<int, Kokkos::LayoutLeft, host_drv_space>;
|
|
using drview_right =
|
|
Kokkos::DynRankView<int, Kokkos::LayoutRight, host_drv_space>;
|
|
using drview_stride =
|
|
Kokkos::DynRankView<int, Kokkos::LayoutStride, host_drv_space>;
|
|
|
|
drview_left xl2("xl2", 100, 200);
|
|
drview_right xr2("xr2", 100, 200);
|
|
drview_stride yl1 = Kokkos::subdynrankview(xl2, 0, Kokkos::ALL());
|
|
drview_stride yl2 = Kokkos::subdynrankview(xl2, 1, Kokkos::ALL());
|
|
drview_stride ys1 = Kokkos::subdynrankview(xr2, 0, Kokkos::ALL());
|
|
drview_stride ys2 = Kokkos::subdynrankview(xr2, 1, Kokkos::ALL());
|
|
drview_stride yr1 = Kokkos::subdynrankview(xr2, 0, Kokkos::ALL());
|
|
drview_stride yr2 = Kokkos::subdynrankview(xr2, 1, Kokkos::ALL());
|
|
|
|
ASSERT_EQ(yl1.extent(0), xl2.extent(1));
|
|
ASSERT_EQ(yl2.extent(0), xl2.extent(1));
|
|
|
|
ASSERT_EQ(yr1.extent(0), xr2.extent(1));
|
|
ASSERT_EQ(yr2.extent(0), xr2.extent(1));
|
|
|
|
ASSERT_EQ(&yl1(0) - &xl2(0, 0), 0);
|
|
ASSERT_EQ(&yl2(0) - &xl2(1, 0), 0);
|
|
ASSERT_EQ(&yr1(0) - &xr2(0, 0), 0);
|
|
ASSERT_EQ(&yr2(0) - &xr2(1, 0), 0);
|
|
|
|
drview_left xl4("xl4", 10, 20, 30, 40);
|
|
drview_right xr4("xr4", 10, 20, 30, 40);
|
|
|
|
// Replace subdynrankview with subview - test
|
|
drview_stride yl4 =
|
|
Kokkos::subview(xl4, 1, Kokkos::ALL(), 2, Kokkos::ALL());
|
|
drview_stride yr4 =
|
|
Kokkos::subview(xr4, 1, Kokkos::ALL(), 2, Kokkos::ALL());
|
|
|
|
ASSERT_EQ(yl4.extent(0), xl4.extent(1));
|
|
ASSERT_EQ(yl4.extent(1), xl4.extent(3));
|
|
ASSERT_EQ(yr4.extent(0), xr4.extent(1));
|
|
ASSERT_EQ(yr4.extent(1), xr4.extent(3));
|
|
ASSERT_EQ(yl4.rank(), 2u);
|
|
ASSERT_EQ(yr4.rank(), 2u);
|
|
|
|
ASSERT_EQ(&yl4(4, 4) - &xl4(1, 4, 2, 4), 0);
|
|
ASSERT_EQ(&yr4(4, 4) - &xr4(1, 4, 2, 4), 0);
|
|
}
|
|
|
|
static void run_test_vector() {
|
|
static const unsigned Length = 1000, Count = 8;
|
|
|
|
using multivector_type =
|
|
typename Kokkos::DynRankView<T, Kokkos::LayoutLeft, host_drv_space>;
|
|
|
|
using multivector_right_type =
|
|
typename Kokkos::DynRankView<T, Kokkos::LayoutRight, host_drv_space>;
|
|
|
|
multivector_type mv = multivector_type("mv", Length, Count);
|
|
multivector_right_type mv_right =
|
|
multivector_right_type("mv", Length, Count);
|
|
|
|
using svector_type =
|
|
typename Kokkos::DynRankView<T, Kokkos::LayoutStride, host_drv_space>;
|
|
using smultivector_type =
|
|
typename Kokkos::DynRankView<T, Kokkos::LayoutStride, host_drv_space>;
|
|
using const_svector_right_type =
|
|
typename Kokkos::DynRankView<const T, Kokkos::LayoutStride,
|
|
host_drv_space>;
|
|
using const_svector_type =
|
|
typename Kokkos::DynRankView<const T, Kokkos::LayoutStride,
|
|
host_drv_space>;
|
|
using const_smultivector_type =
|
|
typename Kokkos::DynRankView<const T, Kokkos::LayoutStride,
|
|
host_drv_space>;
|
|
|
|
svector_type v1 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 0);
|
|
svector_type v2 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 1);
|
|
svector_type v3 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 2);
|
|
|
|
svector_type rv1 = Kokkos::subdynrankview(mv_right, 0, Kokkos::ALL());
|
|
svector_type rv2 = Kokkos::subdynrankview(mv_right, 1, Kokkos::ALL());
|
|
svector_type rv3 = Kokkos::subdynrankview(mv_right, 2, Kokkos::ALL());
|
|
|
|
smultivector_type mv1 = Kokkos::subdynrankview(mv, std::make_pair(1, 998),
|
|
std::make_pair(2, 5));
|
|
|
|
smultivector_type mvr1 = Kokkos::subdynrankview(
|
|
mv_right, std::make_pair(1, 998), std::make_pair(2, 5));
|
|
|
|
const_svector_type cv1 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 0);
|
|
const_svector_type cv2 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 1);
|
|
const_svector_type cv3 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 2);
|
|
|
|
svector_type vr1 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 0);
|
|
svector_type vr2 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 1);
|
|
svector_type vr3 = Kokkos::subdynrankview(mv, Kokkos::ALL(), 2);
|
|
|
|
const_svector_right_type cvr1 =
|
|
Kokkos::subdynrankview(mv, Kokkos::ALL(), 0);
|
|
const_svector_right_type cvr2 =
|
|
Kokkos::subdynrankview(mv, Kokkos::ALL(), 1);
|
|
const_svector_right_type cvr3 =
|
|
Kokkos::subdynrankview(mv, Kokkos::ALL(), 2);
|
|
|
|
ASSERT_EQ(&v1[0], &v1(0));
|
|
ASSERT_EQ(&v1[0], &mv(0, 0));
|
|
ASSERT_EQ(&v2[0], &mv(0, 1));
|
|
ASSERT_EQ(&v3[0], &mv(0, 2));
|
|
|
|
ASSERT_EQ(&cv1[0], &mv(0, 0));
|
|
ASSERT_EQ(&cv2[0], &mv(0, 1));
|
|
ASSERT_EQ(&cv3[0], &mv(0, 2));
|
|
|
|
ASSERT_EQ(&vr1[0], &mv(0, 0));
|
|
ASSERT_EQ(&vr2[0], &mv(0, 1));
|
|
ASSERT_EQ(&vr3[0], &mv(0, 2));
|
|
|
|
ASSERT_EQ(&cvr1[0], &mv(0, 0));
|
|
ASSERT_EQ(&cvr2[0], &mv(0, 1));
|
|
ASSERT_EQ(&cvr3[0], &mv(0, 2));
|
|
|
|
ASSERT_EQ(&mv1(0, 0), &mv(1, 2));
|
|
ASSERT_EQ(&mv1(1, 1), &mv(2, 3));
|
|
ASSERT_EQ(&mv1(3, 2), &mv(4, 4));
|
|
ASSERT_EQ(&mvr1(0, 0), &mv_right(1, 2));
|
|
ASSERT_EQ(&mvr1(1, 1), &mv_right(2, 3));
|
|
ASSERT_EQ(&mvr1(3, 2), &mv_right(4, 4));
|
|
|
|
const_svector_type c_cv1(v1);
|
|
typename svector_type::const_type c_cv2(v2);
|
|
typename const_svector_type::const_type c_ccv2(v2);
|
|
|
|
const_smultivector_type cmv(mv);
|
|
typename smultivector_type::const_type cmvX(cmv);
|
|
typename const_smultivector_type::const_type ccmvX(cmv);
|
|
}
|
|
|
|
static void run_test_layout() {
|
|
Kokkos::DynRankView<double> d("source", 1, 2, 3, 4);
|
|
Kokkos::DynRankView<double> e("dest");
|
|
|
|
auto props = Kokkos::view_alloc(Kokkos::WithoutInitializing, d.label());
|
|
e = Kokkos::DynRankView<double>(props, d.layout());
|
|
|
|
ASSERT_EQ(d.rank(), 4u);
|
|
ASSERT_EQ(e.rank(), 4u);
|
|
ASSERT_EQ(e.label(), "source");
|
|
|
|
auto ulayout = e.layout();
|
|
ASSERT_EQ(ulayout.dimension[0], 1u);
|
|
ASSERT_EQ(ulayout.dimension[1], 2u);
|
|
ASSERT_EQ(ulayout.dimension[2], 3u);
|
|
ASSERT_EQ(ulayout.dimension[3], 4u);
|
|
ASSERT_EQ(ulayout.dimension[4], KOKKOS_INVALID_INDEX);
|
|
ASSERT_EQ(ulayout.dimension[5], KOKKOS_INVALID_INDEX);
|
|
ASSERT_EQ(ulayout.dimension[6], KOKKOS_INVALID_INDEX);
|
|
ASSERT_EQ(ulayout.dimension[7], KOKKOS_INVALID_INDEX);
|
|
}
|
|
};
|
|
|
|
} // namespace Test
|
|
|
|
/*--------------------------------------------------------------------------*/
|