Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9bca6bd
Add separate host array classes
adayton1 Sep 12, 2025
016a6c3
Clean up
adayton1 Sep 12, 2025
8bb4f56
Fixes and add tests
adayton1 Sep 15, 2025
5ae28c1
Clean up
adayton1 Sep 15, 2025
eedce00
Make host array constructor explicit
adayton1 Sep 16, 2025
4fd51a0
Add generic ArrayPointer and ArrayView classes
adayton1 Sep 16, 2025
9f7f647
Clean up ArrayPointer
adayton1 Sep 17, 2025
27f9e76
Update ArrayPointer
adayton1 Sep 17, 2025
eee0256
Add DualArray implementation
adayton1 Sep 18, 2025
8445b14
Add Context and ContextManager
adayton1 Sep 18, 2025
de9d954
Add ContextManager tests
adayton1 Sep 18, 2025
383796b
Remove accidentally committed changes
adayton1 Sep 18, 2025
3ec3666
More changes
adayton1 Sep 18, 2025
4bdf2f8
Fix ContextManager
adayton1 Sep 18, 2025
c01e502
Add DualArray tests and fixes
adayton1 Sep 18, 2025
8acff16
Add ContextGuard class
adayton1 Sep 18, 2025
fa423b9
Clean up ContextManager
adayton1 Sep 19, 2025
bf60814
Improve tests
adayton1 Sep 19, 2025
f445792
Fix up testing
adayton1 Sep 19, 2025
50dc749
More clean up of tests
adayton1 Sep 19, 2025
fb1940b
Add HostDeviceArrayManager and tests
adayton1 Oct 29, 2025
354af28
Add tests integrating ArrayPointer and HostDeviceArrayManager
adayton1 Oct 29, 2025
39af481
Add new tests to build
adayton1 Oct 29, 2025
cdfbbee
Merge in develop
adayton1 Oct 29, 2025
5b7418c
Update hip host config
adayton1 Oct 29, 2025
3c7b2a2
Build fixes
adayton1 Oct 29, 2025
389c005
Fix for using methods in lambdas
adayton1 Oct 29, 2025
56fd864
Mark more ArrayPointer functions as const
adayton1 Oct 29, 2025
dd57fce
Fix converting constructor
adayton1 Oct 29, 2025
8023309
Add cuda host config
adayton1 Oct 31, 2025
e3f4675
Pull in changes from develop
adayton1 Jan 12, 2026
2535189
Merge branch 'develop' into feature/chai_redesign_1
adayton1 Jan 12, 2026
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
159 changes: 159 additions & 0 deletions src/chai/expt/Array.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#ifndef CHAI_MANAGED_ARRAY_HPP
#define CHAI_MANAGED_ARRAY_HPP

#include "chai/expt/ArrayManager.hpp"
#include <cstddef>

namespace chai {
namespace expt {
template <typename ElementType, typename ArrayType>
class Array {
public:
Array() = default;

explicit Array(const ArrayType& manager)
: m_manager{manager}
{
}

explicit Array(ArrayType&& manager)
: m_manager{std::move(manager)}
{
}

Array(const Array& other) :
m_data{other.m_data},
m_size{other.m_size},
m_manager{other.m_manager}
{
update();
}

void resize(std::size_t newSize) {
m_data = nullptr;
m_size = newSize;
m_manager.resize(newSize);
}

void free() {
m_data = nullptr;
m_size = 0;
m_manager.free();
}

CHAI_HOST_DEVICE std::size_t size() const
{
return m_size;
}

CHAI_HOST_DEVICE void update() const
{
#if !defined(CHAI_DEVICE_COMPILE)
m_data = m_manager.data(!std::is_const_v<ElementType>);
#endif
}

CHAI_HOST_DEVICE void cupdate() const
{
#if !defined(CHAI_DEVICE_COMPILE)
m_data = m_manager.data(false);
#endif
}

/*!
* \brief Get a pointer to the element data in the specified context.
*
* \param context The context in which to retrieve the element data.
*
* \return A pointer to the element data in the specified context.
*/
ElementType* data() const
{
update();
return m_data;
}

/*!
* \brief Get a const pointer to the element data in the specified context.
*
* \param context The context in which to retrieve the const element data.
*
* \return A const pointer to the element data in the specified context.
*/
CHAI_HOST_DEVICE const ElementType* cdata() const {
cupdate();
return m_data;
}

/*!
* \brief Get the ith element in the array.
*
* \param i The index of the element to retrieve.
*
* \pre The copy constructor has been called with the execution space
* set to CPU or GPU (e.g. by the RAJA plugin).
*/
CHAI_HOST_DEVICE ElementType& operator[](std::size_t i) const
{
return m_data[i];
}

/*!
* \brief Get the value of the element at the specified index.
*
* \param i The index of the element to retrieve.
*
* \return The value of the element at the specified index.
*
* \throw std::runtime_exception if unable to retrieve the element.
*/
ElementType get(std::size_t i) const
{
return *(static_cast<ElementType*>(m_manager.get(i*sizeof(ElementType), sizeof(ElementType))));
}

/*!
* \brief Set a value at a specified index in the array.
*
* \param i The index where the value is to be set.
* \param value The value to set at the specified index.
*
* \throw std::runtime_exception if the array manager is not associated with the Array.
*/
void set(std::size_t i, const ElementType& value) {
m_manager.set(i*sizeof(ElementType), sizeof(ElementType), static_cast<void*>(std::addressof(value)));
}

private:
/*!
* The array that is coherent in the current execution space.
*/
ElementType* m_data{nullptr};

/*!
* The number of elements in the array.
*/
std::size_t m_size{0};

/*!
* The array manager controls the coherence of the array.
*/
ArrayType m_manager{};
}; // class Array

/*!
* \brief Constructs an array by creating a new manager object.
*
* \tparam ArrayManager<ElementType> The type of array manager.
* \tparam Args The type of the arguments used to construct the array manager.
*
* \param args The arguments to construct an array manager.
*/
template <typename ElementType, typename ArrayManager, typename... Args>
Array<ElementType> makeArray(Args&&... args) {
return Array<ElementType>(new ArrayManager(std::forward<Args>(args)...));
}
} // namespace expt
} // namespace chai

#endif // CHAI_MANAGED_ARRAY_HPP
179 changes: 179 additions & 0 deletions src/chai/expt/ArrayPointer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#ifndef CHAI_ARRAY_POINTER_HPP
#define CHAI_ARRAY_POINTER_HPP

#include "chai/config.hpp"
#include "chai/ChaiMacros.hpp"
#include <type_traits>

namespace chai::expt
{
template <typename ElementType, template <typename> typename ManagerType>
class ArrayPointer
{
public:
using Manager = ManagerType<std::remove_cv_t<ElementType>>;

ArrayPointer() = default;

CHAI_HOST_DEVICE ArrayPointer(std::nullptr_t)
: ArrayPointer()
{
}

explicit ArrayPointer(Manager* array)
: m_manager{array}
{
update();
}

CHAI_HOST_DEVICE ArrayPointer(const ArrayPointer& other)
: m_data{other.m_data},
m_size{other.m_size},
m_manager{other.m_manager}
{
update();
}

template <typename OtherElementType,
typename = std::enable_if_t<std::is_convertible_v<OtherElementType (*)[], ElementType (*)[]>>>
CHAI_HOST_DEVICE ArrayPointer(const ArrayPointer<OtherElementType, ManagerType>& other)
: m_data{other.m_data},
m_size{other.m_size},
m_manager{other.m_manager}
{
update();
}

CHAI_HOST_DEVICE ArrayPointer& operator=(const ArrayPointer& other)
{
if (&other != this)
{
m_data = other.m_data;
m_size = other.m_size;
m_manager = other.m_manager;

update();
}

return *this;
}

CHAI_HOST_DEVICE ArrayPointer& operator=(std::nullptr_t)
{
m_data = nullptr;
m_size = 0;
m_manager = nullptr;

return *this;
}

void resize(std::size_t newSize)
{
if (m_manager == nullptr)
{
m_manager = new Manager();
}

m_data = nullptr;
m_size = newSize;
m_manager->resize(newSize);

update();
}

void free()
{
m_data = nullptr;
m_size = 0;
delete m_manager;
m_manager = nullptr;
}

CHAI_HOST_DEVICE std::size_t size() const
{
return m_size;
}

CHAI_HOST_DEVICE void update() const
{
#if !defined(CHAI_DEVICE_COMPILE)
if (m_manager)
{
if (ElementType* data = m_manager->data(); data)
{
m_data = data;
}

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

CHAI_HOST_DEVICE void cupdate() const
{
#if !defined(CHAI_DEVICE_COMPILE)
if (m_manager)
{
if (ElementType* data = m_manager->data(); data)
{
m_data = data;
}

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

CHAI_HOST_DEVICE ElementType* data() const
{
update();
return m_data;
}

CHAI_HOST_DEVICE const ElementType* cdata() const
{
cupdate();
return m_data;
}

CHAI_HOST_DEVICE ElementType& operator[](std::size_t i) const
{
return m_data[i];
}

ElementType get(std::size_t i)
{
if (m_manager && i < m_manager->size())
{
return m_manager->get(i);
}
else
{
throw std::out_of_range("Manager index out of bounds");
}
}

void set(std::size_t i, ElementType value)
{
if (m_manager && i < m_manager->size())
{
m_manager->set(i, value);
}
else
{
throw std::out_of_range("Manager index out of bounds");
}
}

private:
mutable ElementType* m_data{nullptr};
mutable std::size_t m_size{0};
Manager* m_manager{nullptr};

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

#endif // CHAI_ARRAY_POINTER_HPP
Loading