Skip to content

Commit

Permalink
Template {Copy,Move}ToDevice over Device instead of Queue
Browse files Browse the repository at this point in the history
  • Loading branch information
makortel committed Dec 18, 2024
1 parent ad1db16 commit 9814921
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 47 deletions.
4 changes: 2 additions & 2 deletions HeterogeneousCore/AlpakaCore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,14 @@ Also note that the `fillDescription()` function must have the same content for a
While the EventSetup can be used to handle copying data to all devices
of an Alpaka backend, for data used only by one EDProducer a simpler
way would be to use one of
* `cms::alpakatools::MoveToDeviceCache<TQueue, THostObject>` (recommended)
* `cms::alpakatools::MoveToDeviceCache<TDevice, THostObject>` (recommended)
* `#include "HeterogeneousCore/AlpakaCore/interface/MoveToDeviceCache.h"`
* Moves the `THostObject` to all devices using `cms::alpakatools::CopyToDevice<THostObject>` synchronously. On host backends the argument `THostObject` is moved around, but not copied.
* The `THostObject` must not be copyable
* This is to avoid easy mistakes with objects that follow copy semantics of `std::shared_ptr` (that includes Alpaka buffers), that would allow the source memory buffer to be used via another copy during the asynchronous data copy to the device.
* The constructor argument `THostObject` object may not be used, unless it is initialized again e.g. by assigning another `THostObject` into it.
* The corresponding device-side object can be obtained with `get()` member function using either alpaka Device or Queue object. It can be used immediately after the constructor returns.
* `cms::alpakatools::CopyToDeviceCache<TQueue, THostObject>` (use only if **must** use copyable `THostObject`)
* `cms::alpakatools::CopyToDeviceCache<TDevice, THostObject>` (use only if **must** use copyable `THostObject`)
* `#include "HeterogeneousCore/AlpakaCore/interface/CopyToDeviceCache.h"`
* Copies the `THostObject` to all devices using `cms::alpakatools::CopyToDevice<THostObject>` synchronously. Also host backends do a copy.
* The constructor argument `THostObject` object can be used for other purposes immediately after the constructor returns
Expand Down
37 changes: 15 additions & 22 deletions HeterogeneousCore/AlpakaCore/interface/CopyToDeviceCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ namespace cms::alpakatools {
// std::conditional_t and if constexpr) because the
// CopyToDevice<THostObject>::copyAsync() is ill-defined e.g. for
// PortableCollection on host device
template <typename TDev, typename TQueue, typename THostObject>
template <typename TDevice, typename THostObject>
class CopyToDeviceCacheImpl {
public:
using Device = TDev;
using Queue = TQueue;
using Device = TDevice;
using Queue = alpaka::Queue<Device, alpaka::NonBlocking>;
using HostObject = THostObject;
using Copy = CopyToDevice<HostObject>;
using DeviceObject = decltype(Copy::copyAsync(std::declval<Queue&>(), std::declval<HostObject const&>()));
Expand Down Expand Up @@ -47,8 +47,8 @@ namespace cms::alpakatools {
};

// For host device, copy the host object directly instead
template <typename TQueue, typename THostObject>
class CopyToDeviceCacheImpl<alpaka_common::DevHost, TQueue, THostObject> {
template <typename THostObject>
class CopyToDeviceCacheImpl<alpaka_common::DevHost, THostObject> {
public:
using HostObject = THostObject;
using DeviceObject = HostObject;
Expand All @@ -63,9 +63,9 @@ namespace cms::alpakatools {
} // namespace detail

/**
* This class template implements a cache for data that is copied
* This class template implements a cache for data that is moved
* from the host (of type THostObject) to all the devices
* corresponding the TQueue queue type.
* corresponding to the TDevice device type.
*
* The host-side object to be copied is given as an argument to the
* class constructor. The constructor uses the
Expand All @@ -77,31 +77,24 @@ namespace cms::alpakatools {
* type is the return type of CopyToDevice<THostObject>::copyAsync())
* can be obtained with get() member function, that has either the
* queue or device argument.
*
* TODO: In principle it would be better to template over Device,
* but then we'd need a way to have a "default queue" type for each
* Device in order to infer the return type of
* CopyToDevice::copyAsync(). Alternatively, the template over
* TQueue could be removed by moving the class definition to
* ALPAKA_ACCELERATOR_NAMESPACE.
*/
template <typename TQueue, typename THostObject>
template <typename TDevice, typename THostObject>
requires alpaka::isDevice<TDevice>
class CopyToDeviceCache {
using Queue = TQueue;
using Device = alpaka::Dev<Queue>;
using Device = TDevice;
using HostObject = THostObject;
using Impl = detail::CopyToDeviceCacheImpl<Device, Queue, HostObject>;
using Impl = detail::CopyToDeviceCacheImpl<Device, HostObject>;
using DeviceObject = typename Impl::DeviceObject;

public:
CopyToDeviceCache(THostObject const& srcData) : data_(srcData) {}

// TODO: I could make this function to return the contained object
// in case of alpaka buffer, PortableObject, or PortableCollection
// (in PortableCollection case it would be the View)
DeviceObject const& get(Device const& dev) const { return data_.get(alpaka::getNativeHandle(dev)); }

DeviceObject const& get(Queue const& queue) const { return get(alpaka::getDev(queue)); }
template <typename TQueue>
DeviceObject const& get(TQueue const& queue) const {
return get(alpaka::getDev(queue));
}

private:
Impl data_;
Expand Down
35 changes: 14 additions & 21 deletions HeterogeneousCore/AlpakaCore/interface/MoveToDeviceCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ namespace cms::alpakatools {
// std::conditional_t and if constexpr) because the
// CopyToDevice<THostObject>::copyAsync() is ill-defined e.g. for
// PortableCollection on host device
template <typename TDev, typename TQueue, typename THostObject>
template <typename TDevice, typename THostObject>
class MoveToDeviceCacheImpl {
public:
using HostObject = THostObject;
using Impl = CopyToDeviceCacheImpl<TDev, TQueue, THostObject>;
using Impl = CopyToDeviceCacheImpl<TDevice, THostObject>;
using DeviceObject = typename Impl::DeviceObject;

MoveToDeviceCacheImpl(HostObject&& srcObject) : impl_(srcObject) {}
Expand All @@ -33,8 +33,8 @@ namespace cms::alpakatools {
};

// For host device, move the host object instead
template <typename TQueue, typename THostObject>
class MoveToDeviceCacheImpl<alpaka_common::DevHost, TQueue, THostObject> {
template <typename THostObject>
class MoveToDeviceCacheImpl<alpaka_common::DevHost, THostObject> {
public:
using HostObject = THostObject;
using DeviceObject = HostObject;
Expand All @@ -51,14 +51,14 @@ namespace cms::alpakatools {
/**
* This class template implements a cache for data that is moved
* from the host (of type THostObject) to all the devices
* corresponding the TQueue queue type.
* corresponding to the TDevice device type.
*
* The host-side object to be moved is given as an argument to the
* class constructor. The constructor uses the
* CopyToDevice<THostObject> class template to copy the data to the
* devices, and waits for the data copies to finish, i.e. the
* constructor is synchronous wrt. the data copies. The "move" is
* achieved by requiring the constructor argument to the rvalue
* achieved by requiring the constructor argument to be an rvalue
* reference.
*
* Note that the host object type is required to be non-copyable.
Expand All @@ -71,34 +71,27 @@ namespace cms::alpakatools {
* type is the return type of CopyToDevice<THostObject>::copyAsync())
* can be obtained with get() member function, that has either the
* queue or device argument.
*
* TODO: In principle it would be better to template over Device,
* but then we'd need a way to have a "default queue" type for each
* Device in order to infer the return type of
* CopyToDevice::copyAsync(). Alternatively, the template over
* TQueue could be removed by moving the class definition to
* ALPAKA_ACCELERATOR_NAMESPACE.
*/
template <typename TQueue, typename THostObject>
template <typename TDevice, typename THostObject>
requires alpaka::isDevice<TDevice>
class MoveToDeviceCache {
public:
using Queue = TQueue;
using Device = alpaka::Dev<Queue>;
using Device = TDevice;
using HostObject = THostObject;
using Impl = detail::MoveToDeviceCacheImpl<Device, Queue, HostObject>;
using Impl = detail::MoveToDeviceCacheImpl<Device, HostObject>;
using DeviceObject = typename Impl::DeviceObject;

static_assert(not(std::is_copy_constructible_v<HostObject> or std::is_copy_assignable_v<HostObject>),
"The data object to be moved to device must not be copyable.");

MoveToDeviceCache(HostObject&& srcData) : data_(std::move(srcData)) {}

// TODO: I could make this function to return the contained object
// in case of alpaka buffer, PortableObject, or PortableCollection
// (in PortableCollection case it would be the View)
DeviceObject const& get(Device const& dev) const { return data_.get(alpaka::getNativeHandle(dev)); }

DeviceObject const& get(Queue const& queue) const { return get(alpaka::getDev(queue)); }
template <typename TQueue>
DeviceObject const& get(TQueue const& queue) const {
return get(alpaka::getDev(queue));
}

private:
Impl data_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
// implementation of the algorithm
TestAlgo algo_;

cms::alpakatools::CopyToDeviceCache<Queue, cms::alpakatools::host_buffer<TestAlgo::UpdateInfo>> deviceCache_;
cms::alpakatools::CopyToDeviceCache<Device, cms::alpakatools::host_buffer<TestAlgo::UpdateInfo>> deviceCache_;
};

} // namespace ALPAKA_ACCELERATOR_NAMESPACE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
// implementation of the algorithm
TestAlgo algo_;

cms::alpakatools::MoveToDeviceCache<Queue, PortableHostObject<TestAlgo::UpdateInfo>> deviceCache_;
cms::alpakatools::MoveToDeviceCache<Device, PortableHostObject<TestAlgo::UpdateInfo>> deviceCache_;
};

} // namespace ALPAKA_ACCELERATOR_NAMESPACE
Expand Down

0 comments on commit 9814921

Please sign in to comment.