Skip to content

Commit

Permalink
Bring back scopes on Buffer construction
Browse files Browse the repository at this point in the history
This allows us to mark buffers as allocate-only. SyncIn is the default.
Ignored in the MANDESS backend.

Signed-off-by: Joseph Schuchart <[email protected]>
  • Loading branch information
devreal committed Nov 18, 2024
1 parent a5f35a6 commit d96b584
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 111 deletions.
50 changes: 9 additions & 41 deletions ttg/ttg/madness/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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<typename Deleter>
Buffer(std::unique_ptr<element_type[], Deleter> ptr, std::size_t n)
Buffer(std::unique_ptr<element_type[], Deleter> ptr, std::size_t n, ttg::scope scope = ttg::scope::SyncIn)
: allocator_type()
, m_sptr(std::move(ptr))
, m_host_data(m_sptr.get())
Expand All @@ -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<element_type[]> ptr, std::size_t n)
Buffer(std::shared_ptr<element_type[]> ptr, std::size_t n, ttg::scope scope = ttg::scope::SyncIn)
: allocator_type()
, m_sptr(std::move(ptr))
, m_host_data(m_sptr.get())
Expand Down Expand Up @@ -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();
Expand All @@ -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 <typename Archive>
void serialize(Archive& ar, const unsigned int version) {
if constexpr (ttg::detail::is_output_archive_v<Archive>) {
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 <typename Archive>
std::enable_if_t<std::is_base_of_v<madness::archive::BufferInputArchive, Archive> ||
Expand Down
86 changes: 16 additions & 70 deletions ttg/ttg/parsec/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Allocator, empty_allocator<value_type>>;
assert(!is_empty_allocator);
m_allocator = alloc;
Expand All @@ -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<allocator_type&>(*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<data_type*>(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
*/
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -272,8 +216,8 @@ struct Buffer {
Buffer()
{ }

Buffer(std::size_t n)
: m_data(detail::ttg_parsec_data_types<T*, Allocator>::create_data(n*sizeof(element_type)))
Buffer(std::size_t n, ttg::scope scope = ttg::scope::SyncIn)
: m_data(detail::ttg_parsec_data_types<T*, Allocator>::create_data(n*sizeof(element_type), scope))
, m_count(n)
{ }

Expand All @@ -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<element_type[]> ptr, std::size_t n)
Buffer(std::shared_ptr<element_type[]> ptr, std::size_t n,
ttg::scope scope = ttg::scope::SyncIn)
: m_data(detail::ttg_parsec_data_types<std::shared_ptr<element_type[]>,
detail::empty_allocator<element_type>>
::create_data(ptr, n*sizeof(element_type)))
::create_data(ptr, n*sizeof(element_type), scope))
, m_count(n)
{ }

template<typename Deleter>
Buffer(std::unique_ptr<element_type[], Deleter> ptr, std::size_t n)
Buffer(std::unique_ptr<element_type[], Deleter> ptr, std::size_t n,
ttg::scope scope = ttg::scope::SyncIn)
: m_data(detail::ttg_parsec_data_types<std::unique_ptr<element_type[], Deleter>,
detail::empty_allocator<element_type>>
::create_data(ptr, n*sizeof(element_type)))
::create_data(ptr, n*sizeof(element_type), scope))
, m_count(n)
{ }

Expand Down

0 comments on commit d96b584

Please sign in to comment.