Skip to content

Commit

Permalink
Using ttg::Buffer requires MADNESS serialization
Browse files Browse the repository at this point in the history
We cannot use boost serialization to inspect objects for the
buffers they contain because boost archives cannot be templated properly
and need explicit instantiations for its archives, which is impossible
for the BufferInspectorArchive. We just rely on madness from now on.

Signed-off-by: Joseph Schuchart <joseph.schuchart@stonybrook.edu>
  • Loading branch information
devreal committed Nov 12, 2024
1 parent 8e0c610 commit 8f6e3ef
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 71 deletions.
6 changes: 4 additions & 2 deletions tests/unit/device_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ namespace madness {
};
} // namespace archive
} // namespace madness
#endif // TTG_SERIALIZATION_SUPPORTS_MADNESS

static_assert(madness::is_serializable_v<madness::archive::BufferInspectorArchive<ttg::detail::buffer_apply_dummy_fn>, derived_value_t>);
static_assert(ttg::detail::has_buffer_apply_v<derived_value_t>);
static_assert(ttg::detail::has_buffer_apply_v<nested_value_t>);


TEST_CASE("Device", "coro") {
SECTION("buffer-inspection") {
Expand Down Expand Up @@ -487,3 +487,5 @@ TEST_CASE("Device", "coro") {
}

#endif // TTG_IMPL_DEVICE_SUPPORT

#endif // TTG_SERIALIZATION_SUPPORTS_MADNESS
74 changes: 17 additions & 57 deletions ttg/ttg/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ namespace ttg {
template<typename T, typename Allocator = std::allocator<T>>
using Buffer = TTG_IMPL_NS::Buffer<T, Allocator>;

namespace meta {

template<typename T, typename A>
struct is_buffer<ttg::Buffer<T, A>> : std::true_type
{ };

template<typename T, typename A>
struct is_buffer<const ttg::Buffer<T, A>> : std::true_type
{ };

} // namespace meta

namespace detail {
/**
* Type traits to check whether we can use serialization
Expand All @@ -27,8 +39,6 @@ namespace detail {
template<typename T>
constexpr const bool has_buffer_apply_v = has_buffer_apply<T>::value;

/* dummy function type used to check whether buffer_apply is available */
using buffer_apply_dummy_fn = decltype([]<typename T, typename A>(const ttg::Buffer<T, A>&){});
} // namespace detail

} // namespace ttg
Expand Down Expand Up @@ -116,76 +126,26 @@ namespace ttg::detail {
ar & t;
}

/* dummy function type used to check whether buffer_apply is available */
using buffer_apply_dummy_fn = decltype([]<typename T, typename A>(const ttg::Buffer<T, A>&){});

template<typename T>
struct has_buffer_apply_helper<T, std::enable_if_t<madness::is_serializable_v<madness::archive::BufferInspectorArchive<buffer_apply_dummy_fn>, std::decay_t<T>>>>
: std::true_type
{ };

} // namespace ttg::detail

#elif defined(TTG_SERIALZIATION_SUPPORTS_BOOST)
#else

#include <boost/archive/detail/common_oarchive.hpp>
namespace ttg::detail {

template<typename Fn>
struct BufferInspectorArchive
: public boost::archive::detail::common_oarchive<BufferInspectorArchive<Fn>> {
private:
Fn m_fn;

friend class boost::archive::save_access;

/// Stores (counts) data into the memory buffer.

/// The function only appears (due to \c enable_if) if \c T is
/// serializable.
/// \tparam T Type of the data to be stored (counted).
/// \param[in] t Pointer to the data to be stored (counted).
/// \param[in] n Size of data to be stored (counted).
template <typename T, typename Allocator>
void save(const ttg::Buffer<T, Allocator>* t) const {
/* invoke the function on buffer */
m_fn(t[i]);
}

template <typename T>
void save(const T& t) const {
/* nothing to be done for other types */
}

public:
template<typename _Fn>
BufferInspectorArchive(_Fn&& fn)
: m_fn(fn)
{ }

// archives are expected to support this function
void save_binary(void *address, std::size_t count)
{
/* nothing to do */
}
};

/* deduction guide */
template<typename Fn>
BufferInspectorArchive(Fn&&) -> BufferInspectorArchive<Fn>;

template<typename T, typename Fn>
requires(is_boost_serializable_v<madness::archive::BufferInspectorArchive<Fn>, std::decay<T>>)
void buffer_apply(T&& t, Fn&& fn) {
BufferInspectorArchive ar(std::forward<Fn>(fn));
ar & t;
static_assert(ttg::meta::is_void_v<Fn>, "Types using ttg::Buffer must be MADNESS serializable.");
}

template<typename T>
struct has_buffer_apply_helper<T, std::enable_if_t<is_boost_serializable_v<BufferInspectorArchive<buffer_apply_dummy_fn>, std::decay_t<T>>>>
: std::true_type
{ };

} // namespace ttg::detail

#endif // TTG_SERIALIZATION_SUPPORTS_MADNESS


#endif // TTG_buffer_H
9 changes: 6 additions & 3 deletions ttg/ttg/parsec/parsec_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
namespace ttg_parsec::detail {
template<typename Value, typename Fn>
void foreach_parsec_data(Value&& value, Fn&& fn) {
ttg::detail::buffer_apply(value, [&]<typename B>(B&& b){
fn(detail::get_parsec_data(b));
});
/* protect for non-serializable types, allowed if the TT has no device op */
if constexpr (ttg::detail::has_buffer_apply_v<Value>) {
ttg::detail::buffer_apply(value, [&]<typename B>(B&& b){
fn(detail::get_parsec_data(b));
});
}
}
} // namespace ttg_parsec::detail

Expand Down
9 changes: 0 additions & 9 deletions ttg/ttg/util/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "ttg/util/span.h"
#include "ttg/util/typelist.h"
#include "ttg/buffer.h"
#include "ttg/ptr.h"
#include "ttg/devicescratch.h"

Expand Down Expand Up @@ -313,14 +312,6 @@ namespace ttg {
struct is_buffer : std::false_type
{ };

template<typename T, typename A>
struct is_buffer<ttg::Buffer<T, A>> : std::true_type
{ };

template<typename T, typename A>
struct is_buffer<const ttg::Buffer<T, A>> : std::true_type
{ };

template<typename T>
constexpr bool is_buffer_v = is_buffer<T>::value;

Expand Down

0 comments on commit 8f6e3ef

Please sign in to comment.