Skip to content
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
45 changes: 44 additions & 1 deletion docs/sphinx/expt/design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,50 @@ counted since clean up cannot be triggered from the device.
a[i] -= 1; // Use CHAI data structures in the DEVICE context...
});

----------------
ManagedArrayView
----------------

This class provides a uniform interface for viewing different types of memory
across multiple backends. It has shallow-copy semantics, which allows it to be
passed by value to a CUDA or HIP kernel. When copy constructed, it queries the
array manager to update the cached size and pointer from the array manager.
Unlike ``ManagedArrayPointer``, this class is non-owning: it cannot allocate,
resize, or free the underlying data, and the referenced manager must outlive
the view.

.. code-block:: cpp

#include "chai/expt/ContextRAJAPlugin.hpp"
#include "chai/expt/ManagedArrayView.hpp"
#include "chai/expt/UnifiedArrayManager.hpp"
#include "RAJA/RAJA.hpp"

static ::RAJA::util::PluginRegistry::add<chai::expt::ContextRAJAPlugin> P(
"CHAIContextPlugin",
"Plugin that integrates CHAI context management with RAJA.");

// It's recommended to use an alias so that it is easy to swap out the array manager.
template <typename T>
using UnifiedArrayManager = ::chai::expt::UnifiedArrayManager<T>;

template <typename T>
using ManagedArrayView = ::chai::expt::ManagedArrayView<T, UnifiedArrayManager<T>>;

const std::size_t N = 1000000;
UnifiedArrayManager<int> manager{N};
ManagedArrayView<int> a{manager};

::RAJA::forall<::RAJA::seq_exec>(::RAJA::TypedRangeSegment<int>(0, N), [=] (int i) {
a[i] = i; // Use CHAI data structures in the HOST context...
});

constexpr int BLOCK_SIZE = 256;

::RAJA::forall<::RAJA::cuda_exec_async<BLOCK_SIZE>>(::RAJA::TypedRangeSegment<int>(0, N), [=] __device__ (int i) {
a[i] -= 1; // Use CHAI data structures in the DEVICE context...
});

----------------
HostArrayManager
----------------
Expand Down Expand Up @@ -268,4 +312,3 @@ of each element on the host (numeric types are initialized to zero).
const int* p = a.data(false);
// Read through p...
}

1 change: 1 addition & 0 deletions src/chai/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ if(CHAI_ENABLE_EXPERIMENTAL)
expt/HostSharedPointer.hpp
expt/ManagedArrayPointer.hpp
expt/ManagedArraySharedPointer.hpp
expt/ManagedArrayView.hpp
expt/UnifiedArrayManager.hpp
ManagedSharedPtr.hpp
SharedPtrCounter.hpp
Expand Down
187 changes: 187 additions & 0 deletions src/chai/expt/ManagedArrayView.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lawrence Livermore National Security, LLC and other CHAI
// contributors. See the CHAI LICENSE and COPYRIGHT files for details.
//
// SPDX-License-Identifier: BSD-3-Clause
//////////////////////////////////////////////////////////////////////////////

#ifndef CHAI_EXPT_MANAGED_ARRAY_VIEW_HPP
#define CHAI_EXPT_MANAGED_ARRAY_VIEW_HPP

#include "chai/config.hpp"
#include "chai/ChaiMacros.hpp"

#include <cstddef>
#include <type_traits>
namespace chai::expt
{
/*!
* \brief This class provides a uniform interface for viewing different types
* of managed array memory across multiple backends.
*
* \details This class has shallow-copy semantics, which allows it to be
* passed by value to a CUDA or HIP kernel. When copy constructed,
* it queries the array manager to update the cached size and pointer
* from the array manager. This acts as a non-owning view and cannot
* allocate, free, or resize the underlying data.
*
* \tparam ElementType The type of elements contained in this array.
* \tparam ManagerType Manages the underlying memory.
*/
template <typename ElementType, typename ManagerType>
class ManagedArrayView
{
public:
/*!
* \brief Constructs a default ManagedArrayView.
*
* \details Creates a null pointer with size zero and no associated manager.
*/
ManagedArrayView() = default;

/*!
* \brief Constructs a ManagedArrayView from an existing manager.
*
* \param manager An object that owns/manages the underlying array.
*
* \note The manager is not copied or owned. The caller must ensure the
* manager outlives the view.
*/
explicit ManagedArrayView(ManagerType& manager)
: m_data{manager.data()},
m_size{manager.size()},
m_manager{&manager}
{
}

/*!
* \brief Copy-constructs a ManagedArrayView from another ManagedArrayView.
*
* \param other The ManagedArrayView to copy.
*
* \details Copies the cached pointer, size, and manager pointer. The
* cached pointer/size are synchronized by calling update().
*/
CHAI_HOST_DEVICE ManagedArrayView(const ManagedArrayView& other)
: m_data{other.m_data},
m_size{other.m_size},
m_manager{other.m_manager}
{
update();
}

/*!
* \brief Converting copy-constructor from a non-const ManagedArrayView to a const ManagedArrayView.
*
* \tparam OtherElementType The source element type; must be non-const, and this
* ManagedArrayView's ElementType must be const-qualified version of it.
*
* \param other The source ManagedArrayView to copy from.
*/
template <typename OtherElementType,
typename = std::enable_if_t<!std::is_const_v<OtherElementType> &&
std::is_same_v<ElementType, std::add_const_t<OtherElementType>>>>
CHAI_HOST_DEVICE ManagedArrayView(const ManagedArrayView<OtherElementType, ManagerType>& other)
: m_data{other.m_data},
m_size{other.m_size},
m_manager{other.m_manager}
{
}

/*!
* \brief Copy-assigns from another ManagedArrayView.
*
* \param other The ManagedArrayView to copy from.
*
* \return Reference to this ManagedArrayView.
*/
ManagedArrayView& operator=(const ManagedArrayView& other) = default;

/*!
* \brief Returns the number of elements in the underlying managed array.
*
* \return The number of elements.
*/
CHAI_HOST_DEVICE std::size_t size() const
{
#if !defined(CHAI_DEVICE_COMPILE)
if (m_manager)
{
m_size = m_manager->size();
}
#endif
return m_size;
}

/*!
* \brief Returns the cached pointer to the managed array's data.
*
* \return Pointer to the first element of the underlying managed array, or nullptr.
*/
CHAI_HOST_DEVICE ElementType* data() const
{
#if !defined(CHAI_DEVICE_COMPILE)
if (m_manager)
{
if (ElementType* data = static_cast<ElementType*>(m_manager->data()); data)
{
m_data = data;
}
}
#endif
return m_data;
}

/*!
* \brief Synchronizes the cached pointer and size from the manager.
*/
CHAI_HOST_DEVICE void update() const
{
#if !defined(CHAI_DEVICE_COMPILE)
if (m_manager)
{
if (ElementType* data = static_cast<ElementType*>(m_manager->data()); data)
{
m_data = data;
}

m_size = m_manager->size();
}
#endif
}

/*!
* \brief Unchecked element access.
*
* \param i Element index.
*
* \return Reference to element i in the cached data pointer.
*/
CHAI_HOST_DEVICE ElementType& operator[](std::size_t i) const
{
return m_data[i];
}

private:
/*!
* \brief Cached pointer to the managed array.
*/
mutable ElementType* m_data{nullptr};

/*!
* \brief Cached number of elements in the managed array.
*/
mutable std::size_t m_size{0};

/*!
* \brief Pointer to the manager that owns/manages the underlying array.
*/
ManagerType* m_manager{nullptr};

/// Needed for the converting constructor
template <typename OtherElementType, typename OtherManagerType>
friend class ManagedArrayView;
}; // class ManagedArrayView
} // namespace chai::expt

#endif // CHAI_EXPT_MANAGED_ARRAY_VIEW_HPP
22 changes: 22 additions & 0 deletions tests/expt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ blt_add_test(
NAME ManagedArrayPointerTests
COMMAND ManagedArrayPointerTests)

blt_add_executable(
NAME ManagedArrayViewTests
SOURCES ManagedArrayViewTests.cpp
HEADERS ${chai_expt_test_headers}
INCLUDES ${PROJECT_BINARY_DIR}/include
DEPENDS_ON ${chai_expt_test_depends})

blt_add_test(
NAME ManagedArrayViewTests
COMMAND ManagedArrayViewTests)

blt_add_executable(
NAME HostArrayPointerTests
SOURCES HostArrayPointerTests.cpp
Expand All @@ -81,6 +92,17 @@ blt_add_test(
NAME HostArrayPointerTests
COMMAND HostArrayPointerTests)

blt_add_executable(
NAME HostArrayViewTests
SOURCES HostArrayViewTests.cpp
HEADERS ${chai_expt_test_headers}
INCLUDES ${PROJECT_BINARY_DIR}/include
DEPENDS_ON ${chai_expt_test_depends})

blt_add_test(
NAME HostArrayViewTests
COMMAND HostArrayViewTests)

blt_add_executable(
NAME HostArraySharedPointerTests
SOURCES HostArraySharedPointerTests.cpp
Expand Down
Loading