From d96b5849ec08e86141852b21f927bd9956536ca4 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Mon, 18 Nov 2024 17:26:49 -0500 Subject: [PATCH] Bring back scopes on Buffer construction This allows us to mark buffers as allocate-only. SyncIn is the default. Ignored in the MANDESS backend. Signed-off-by: Joseph Schuchart --- ttg/ttg/madness/buffer.h | 50 +++++------------------ ttg/ttg/parsec/buffer.h | 86 ++++++++-------------------------------- 2 files changed, 25 insertions(+), 111 deletions(-) diff --git a/ttg/ttg/madness/buffer.h b/ttg/ttg/madness/buffer.h index 25dd0836c..b1accb37e 100644 --- a/ttg/ttg/madness/buffer.h +++ b/ttg/ttg/madness/buffer.h @@ -48,7 +48,7 @@ struct Buffer : private Allocator { Buffer() : Buffer(nullptr, 0) { } - Buffer(std::size_t n) + Buffer(std::size_t n, ttg::scope scope = ttg::scope::SyncIn) : allocator_type() , m_host_data(allocate(n)) , m_count(n) @@ -59,7 +59,7 @@ struct Buffer : private Allocator { * The memory pointed to by ptr must be accessible during * the life-time of the buffer. */ template - Buffer(std::unique_ptr ptr, std::size_t n) + Buffer(std::unique_ptr ptr, std::size_t n, ttg::scope scope = ttg::scope::SyncIn) : allocator_type() , m_sptr(std::move(ptr)) , m_host_data(m_sptr.get()) @@ -70,7 +70,7 @@ struct Buffer : private Allocator { /* Constructing a buffer using application-managed memory. * The memory pointed to by ptr must be accessible during * the life-time of the buffer. */ - Buffer(std::shared_ptr ptr, std::size_t n) + Buffer(std::shared_ptr ptr, std::size_t n, ttg::scope scope = ttg::scope::SyncIn) : allocator_type() , m_sptr(std::move(ptr)) , m_host_data(m_sptr.get()) @@ -230,7 +230,7 @@ struct Buffer : private Allocator { } /* Reallocate the buffer with count elements */ - void reset(std::size_t n) { + void reset(std::size_t n, ttg::scope scope = ttg::scope::SyncIn) { if (m_owned) { deallocate(); @@ -247,47 +247,15 @@ struct Buffer : private Allocator { m_count = n; } - /* Reset the buffer to use the ptr to count elements */ - void reset(T* ptr, std::size_t n = 1) { - /* TODO: can we resize if count is smaller than m_count? */ - if (n == m_count) { - return; - } - - if (m_owned) { - deallocate(); - } - - if (nullptr == ptr) { - m_host_data = nullptr; - m_count = 0; - m_owned = false; - } else { - m_host_data = ptr; - m_count = n; - m_owned = false; - } + /** + * Resets the scope of the buffer. Ignored in MADNESS. + */ + void reset_scope(ttg::scope scope) { + /* nothing to do here */ } /* serialization support */ -#if defined(TTG_SERIALIZATION_SUPPORTS_BOOST) && 0 - template - void serialize(Archive& ar, const unsigned int version) { - if constexpr (ttg::detail::is_output_archive_v) { - std::size_t s = size(); - ar& s; - /* TODO: how to serialize the array? */ - } else { - std::size_t s; - ar & s; - /* initialize internal pointers and then reset */ - reset(s); - /* TODO: how to deserialize the array? */ - } - } -#endif // TTG_SERIALIZATION_SUPPORTS_BOOST - #if defined(TTG_SERIALIZATION_SUPPORTS_MADNESS) template std::enable_if_t || diff --git a/ttg/ttg/parsec/buffer.h b/ttg/ttg/parsec/buffer.h index c3e313044..22b8c51de 100644 --- a/ttg/ttg/parsec/buffer.h +++ b/ttg/ttg/parsec/buffer.h @@ -97,7 +97,8 @@ namespace detail { this->device_private = to_address(m_ptr); } - void construct(std::size_t size, const allocator_type& alloc = allocator_type()) { + void construct(std::size_t size, + const allocator_type& alloc = allocator_type()) { constexpr const bool is_empty_allocator = std::is_same_v>; assert(!is_empty_allocator); m_allocator = alloc; @@ -110,65 +111,6 @@ namespace detail { } }; -#if 0 - /** - * derived from parsec_data_t managing an allocator for host memory - * and creating a host copy through a callback - */ - struct data_type : public parsec_data_t { - private: - [[no_unique_address]] - Allocator host_allocator; - - allocator_type& get_allocator_reference() { return static_cast(*this); } - - element_type* do_allocate(std::size_t n) { - return allocator_traits::allocate(get_allocator_reference(), n); - } - - public: - - explicit data_type(const Allocator& host_alloc = Allocator()) - : host_allocator(host_alloc) - { } - - void* allocate(std::size_t size) { - return do_allocate(size); - } - - void deallocate(void* ptr, std::size_t size) { - allocator_traits::deallocate(get_allocator_reference(), ptr, size); - } - }; - - /* Allocate the host copy for a given data_t */ - static parsec_data_copy_t* data_copy_allocate(parsec_data_t* pdata, int device) { - if (device != 0) return nullptr; // we only allocate for the host - data_type* data = static_cast(pdata); // downcast - data_copy_type* copy = PARSEC_OBJ_NEW(data_copy_type); - copy->device_private = data->allocate(data->nb_elts); - return copy; - } - /** - * Create the PaRSEC object infrastructure for the data copy type - */ - inline void data_construct(data_type* obj) - { - obj->allocate_cb = &data_copy_allocate; - } - - static void data_destruct(data_type* obj) - { - /* cleanup alloctor instance */ - obj->~data_type(); - } - - static constexpr PARSEC_OBJ_CLASS_INSTANCE(data_type, parsec_data_t, - data_copy_construct, - data_copy_destruct); - -#endif // 0 - /** * Create the PaRSEC object infrastructure for the data copy type */ @@ -186,7 +128,7 @@ namespace detail { data_copy_construct, data_copy_destruct); - static parsec_data_t * create_data(std::size_t size, + static parsec_data_t * create_data(std::size_t size, ttg::scope scope, const allocator_type& allocator = allocator_type()) { parsec_data_t *data = PARSEC_OBJ_NEW(parsec_data_t); data->owner_device = 0; @@ -200,12 +142,13 @@ namespace detail { /* adjust data flags */ data->device_copies[0]->flags |= PARSEC_DATA_FLAG_PARSEC_MANAGED; data->device_copies[0]->coherency_state = PARSEC_DATA_COHERENCY_SHARED; - data->device_copies[0]->version = 1; + /* setting version to 0 causes data not to be sent to the device */ + data->device_copies[0]->version = (scope == ttg::scope::SyncIn) ? 1 : 0; return data; } - static parsec_data_t * create_data(PtrT& ptr, std::size_t size) { + static parsec_data_t * create_data(PtrT& ptr, std::size_t size, ttg::scope scope) { parsec_data_t *data = PARSEC_OBJ_NEW(parsec_data_t); data->owner_device = 0; data->nb_elts = size; @@ -218,7 +161,8 @@ namespace detail { /* adjust data flags */ data->device_copies[0]->flags |= PARSEC_DATA_FLAG_PARSEC_MANAGED; data->device_copies[0]->coherency_state = PARSEC_DATA_COHERENCY_SHARED; - data->device_copies[0]->version = 1; + /* setting version to 0 causes data not to be sent to the device */ + data->device_copies[0]->version = (scope == ttg::scope::SyncIn) ? 1 : 0; return data; } @@ -272,8 +216,8 @@ struct Buffer { Buffer() { } - Buffer(std::size_t n) - : m_data(detail::ttg_parsec_data_types::create_data(n*sizeof(element_type))) + Buffer(std::size_t n, ttg::scope scope = ttg::scope::SyncIn) + : m_data(detail::ttg_parsec_data_types::create_data(n*sizeof(element_type), scope)) , m_count(n) { } @@ -282,18 +226,20 @@ struct Buffer { * The shared_ptr will ensure that the memory is not free'd before * the runtime has released all of its references. */ - Buffer(std::shared_ptr ptr, std::size_t n) + Buffer(std::shared_ptr ptr, std::size_t n, + ttg::scope scope = ttg::scope::SyncIn) : m_data(detail::ttg_parsec_data_types, detail::empty_allocator> - ::create_data(ptr, n*sizeof(element_type))) + ::create_data(ptr, n*sizeof(element_type), scope)) , m_count(n) { } template - Buffer(std::unique_ptr ptr, std::size_t n) + Buffer(std::unique_ptr ptr, std::size_t n, + ttg::scope scope = ttg::scope::SyncIn) : m_data(detail::ttg_parsec_data_types, detail::empty_allocator> - ::create_data(ptr, n*sizeof(element_type))) + ::create_data(ptr, n*sizeof(element_type), scope)) , m_count(n) { }