diff --git a/DataFormats/Portable/interface/PortableCollection.h b/DataFormats/Portable/interface/PortableCollection.h new file mode 100644 index 0000000000000..b257010cde702 --- /dev/null +++ b/DataFormats/Portable/interface/PortableCollection.h @@ -0,0 +1,54 @@ +#ifndef DataFormats_Portable_interface_PortableCollection_h +#define DataFormats_Portable_interface_PortableCollection_h + +#include <optional> + +#include <alpaka/alpaka.hpp> + +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/host.h" + +// generic SoA-based product +template <typename T, typename TDev> +class PortableCollection { +public: + using Buffer = alpaka::Buf<TDev, std::byte, alpaka::DimInt<1u>, uint32_t>; + + PortableCollection() : buffer_{}, layout_{} {} + + PortableCollection(int32_t elements, TDev const &device) + : buffer_{alpaka::allocBuf<std::byte, uint32_t>( + device, alpaka::Vec<alpaka::DimInt<1u>, uint32_t>{T::compute_size(elements)})}, + layout_{elements, buffer_->data()} { + // Alpaka set to a default alignment of 128 bytes defining ALPAKA_DEFAULT_HOST_MEMORY_ALIGNMENT=128 + assert(reinterpret_cast<uintptr_t>(buffer_->data()) % T::alignment == 0); + alpaka::pin(*buffer_); + } + + ~PortableCollection() {} + + // non-copyable + PortableCollection(PortableCollection const &) = delete; + PortableCollection &operator=(PortableCollection const &) = delete; + + // movable + PortableCollection(PortableCollection &&other) = default; + PortableCollection &operator=(PortableCollection &&other) = default; + + T &operator*() { return layout_; } + + T const &operator*() const { return layout_; } + + T *operator->() { return &layout_; } + + T const *operator->() const { return &layout_; } + + Buffer &buffer() { return *buffer_; } + + Buffer const &buffer() const { return *buffer_; } + +private: + std::optional<Buffer> buffer_; //! + T layout_; +}; + +#endif // DataFormats_Portable_interface_PortableCollection_h diff --git a/DataFormats/Portable/interface/PortableHostCollection.h b/DataFormats/Portable/interface/PortableHostCollection.h new file mode 100644 index 0000000000000..70878ab5eee0f --- /dev/null +++ b/DataFormats/Portable/interface/PortableHostCollection.h @@ -0,0 +1,66 @@ +#ifndef DataFormats_Portable_interface_PortableHostCollection_h +#define DataFormats_Portable_interface_PortableHostCollection_h + +#include <optional> + +#include <alpaka/alpaka.hpp> + +#include "DataFormats/Portable/interface/PortableCollection.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +// generic SoA-based product in pinned host memory +template <typename T> +class PortableCollection<T, alpaka_common::DevHost> { +public: + using Buffer = alpaka::Buf<alpaka_common::DevHost, std::byte, alpaka::DimInt<1u>, uint32_t>; + + PortableCollection() : buffer_{}, layout_{} {} + + PortableCollection(int32_t elements, alpaka_common::DevHost const &host) + : buffer_{alpaka::allocBuf<std::byte, uint32_t>( + host, alpaka::Vec<alpaka::DimInt<1u>, uint32_t>{T::compute_size(elements)})}, + layout_{elements, buffer_->data()} { + // Alpaka set to a default alignment of 128 bytes defining ALPAKA_DEFAULT_HOST_MEMORY_ALIGNMENT=128 + assert(reinterpret_cast<uintptr_t>(buffer_->data()) % T::alignment == 0); + } + + template <typename TDev> + PortableCollection(int32_t elements, alpaka_common::DevHost const &host, TDev const &device) + : buffer_{alpaka::allocMappedBuf<std::byte, uint32_t>( + host, device, alpaka::Vec<alpaka::DimInt<1u>, uint32_t>{T::compute_size(elements)})}, + layout_{elements, buffer_->data()} { + // Alpaka set to a default alignment of 128 bytes defining ALPAKA_DEFAULT_HOST_MEMORY_ALIGNMENT=128 + assert(reinterpret_cast<uintptr_t>(buffer_->data()) % T::alignment == 0); + } + + ~PortableCollection() {} + + // non-copyable + PortableCollection(PortableCollection const &) = delete; + PortableCollection &operator=(PortableCollection const &) = delete; + + // movable + PortableCollection(PortableCollection &&other) = default; + PortableCollection &operator=(PortableCollection &&other) = default; + + T &operator*() { return layout_; } + + T const &operator*() const { return layout_; } + + T *operator->() { return &layout_; } + + T const *operator->() const { return &layout_; } + + Buffer &buffer() { return *buffer_; } + + Buffer const &buffer() const { return *buffer_; } + +private: + std::optional<Buffer> buffer_; //! + T layout_; +}; + +template <typename T> +using PortableHostCollection = PortableCollection<T, alpaka_common::DevHost>; + +#endif // DataFormats_Portable_interface_PortableHostCollection_h diff --git a/DataFormats/Portable/interface/alpaka/PortableDeviceCollection.h b/DataFormats/Portable/interface/alpaka/PortableDeviceCollection.h new file mode 100644 index 0000000000000..d09b743ca85c9 --- /dev/null +++ b/DataFormats/Portable/interface/alpaka/PortableDeviceCollection.h @@ -0,0 +1,15 @@ +#ifndef DataFormats_Portable_interface_alpaka_PortableDeviceCollection_h +#define DataFormats_Portable_interface_alpaka_PortableDeviceCollection_h + +#include "DataFormats/Portable/interface/PortableCollection.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + // generic SoA-based product in device memory + template <typename T> + using PortableDeviceCollection = PortableCollection<T, Device>; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#endif // DataFormats_Portable_interface_alpaka_PortableDeviceCollection_h diff --git a/DataFormats/XyzId/BuildFile.xml b/DataFormats/XyzId/BuildFile.xml new file mode 100644 index 0000000000000..142e026c4af60 --- /dev/null +++ b/DataFormats/XyzId/BuildFile.xml @@ -0,0 +1,11 @@ +<use name="alpaka"/> +<use name="rootcore"/> +<use name="DataFormats/Common"/> +<use name="DataFormats/Portable" source_only="1"/> +<use name="FWCore/Utilities" source_only="1"/> +<use name="HeterogeneousCore/AlpakaInterface" source_only="1"/> +<flags LCG_DICT_HEADER="classes.h"/> +<flags LCG_DICT_XML="classes_def.xml"/> +<export> + <lib name="1"/> +</export> diff --git a/DataFormats/XyzId/README.md b/DataFormats/XyzId/README.md new file mode 100644 index 0000000000000..688d49342bb2c --- /dev/null +++ b/DataFormats/XyzId/README.md @@ -0,0 +1,9 @@ +## Define the alpaka-based SoA data formats + +Notes: + - do not define a dictionary for `XyzIdHostCollection`, because it is the + same class as `alpaka_serial_sync::XyzIdDeviceCollection`; + - define the dictionary for `alpaka_cuda_async::XyzIdDeviceCollection` as + _transient_ only; + - the dictionary for `alpaka_cuda_async::XyzIdDeviceCollection` should be + defined in a separate library, to factor out the CUDA dependency. diff --git a/DataFormats/XyzId/interface/XyzIdHostCollection.h b/DataFormats/XyzId/interface/XyzIdHostCollection.h new file mode 100644 index 0000000000000..01a99dab85319 --- /dev/null +++ b/DataFormats/XyzId/interface/XyzIdHostCollection.h @@ -0,0 +1,10 @@ +#ifndef DataFormats_XyzId_interface_XyzIdHostCollection_h +#define DataFormats_XyzId_interface_XyzIdHostCollection_h + +#include "DataFormats/Portable/interface/PortableHostCollection.h" +#include "DataFormats/XyzId/interface/XyzIdSoA.h" + +// SoA with x, y, z, id fields in pinned host memory +using XyzIdHostCollection = PortableHostCollection<XyzIdSoA>; + +#endif // DataFormats_XyzId_interface_XyzIdHostCollection_h diff --git a/DataFormats/XyzId/interface/XyzIdSoA.h b/DataFormats/XyzId/interface/XyzIdSoA.h new file mode 100644 index 0000000000000..922f5658fed27 --- /dev/null +++ b/DataFormats/XyzId/interface/XyzIdSoA.h @@ -0,0 +1,162 @@ +#ifndef DataFormats_XyzId_interface_XyzIdSoA_h +#define DataFormats_XyzId_interface_XyzIdSoA_h + +#include <cassert> +#include <cstddef> +#include <cstdint> + +#ifdef DEBUG_SOA_CTOR_DTOR +#include <iostream> +#endif + +#include "FWCore/Utilities/interface/typedefs.h" + +// SoA layout with x, y, z, id fields +class XyzIdSoA { +public: + static constexpr size_t alignment = 128; // align all fields to 128 bytes + + // constructor + XyzIdSoA() : size_(0), buffer_(nullptr), x_(nullptr), y_(nullptr), z_(nullptr), id_(nullptr) { +#ifdef DEBUG_SOA_CTOR_DTOR + std::cout << "XyzIdSoA default constructor" << std::endl; +#endif + } + + XyzIdSoA(int32_t size, void *buffer) + : size_(size), + buffer_(buffer), + x_(reinterpret_cast<double *>(reinterpret_cast<intptr_t>(buffer_))), + y_(reinterpret_cast<double *>(reinterpret_cast<intptr_t>(x_) + pad(size * sizeof(double)))), + z_(reinterpret_cast<double *>(reinterpret_cast<intptr_t>(y_) + pad(size * sizeof(double)))), + id_(reinterpret_cast<int32_t *>(reinterpret_cast<intptr_t>(z_) + pad(size * sizeof(double)))) { + assert(size == 0 or (size > 0 and buffer != nullptr)); +#ifdef DEBUG_SOA_CTOR_DTOR + std::cout << "XyzIdSoA constructor with " << size_ << " elements at 0x" << buffer_ << std::endl; +#endif + } + +#ifdef DEBUG_SOA_CTOR_DTOR + ~XyzIdSoA() { + if (buffer_) { + std::cout << "XyzIdSoA destructor with " << size_ << " elements at 0x" << buffer_ << std::endl; + } else { + std::cout << "XyzIdSoA destructor wihout data" << std::endl; + } + } +#else + ~XyzIdSoA() = default; +#endif + + // non-copyable + XyzIdSoA(XyzIdSoA const &) = delete; + XyzIdSoA &operator=(XyzIdSoA const &) = delete; + + // movable +#ifdef DEBUG_SOA_CTOR_DTOR + XyzIdSoA(XyzIdSoA &&other) + : size_(other.size_), buffer_(other.buffer_), x_(other.x_), y_(other.y_), z_(other.z_), id_(other.id_) { + std::cout << "XyzIdSoA move constructor with " << size_ << " elements at 0x" << buffer_ << std::endl; + other.buffer_ = nullptr; + } + + XyzIdSoA &operator=(XyzIdSoA &&other) { + size_ = other.size_; + buffer_ = other.buffer_; + x_ = other.x_; + y_ = other.y_; + z_ = other.z_; + id_ = other.id_; + std::cout << "XyzIdSoA move assignment with " << size_ << " elements at 0x" << buffer_ << std::endl; + other.buffer_ = nullptr; + return *this; + } +#else + XyzIdSoA(XyzIdSoA &&other) = default; + XyzIdSoA &operator=(XyzIdSoA &&other) = default; +#endif + + // global accessors + int32_t size() const { return size_; } + + uint32_t extent() const { return compute_size(size_); } + + void *data() { return buffer_; } + void const *data() const { return buffer_; } + + // element-wise accessors are not implemented for simplicity + + // field-wise accessors + double const &x(int32_t i) const { + assert(i >= 0); + assert(i < size_); + return x_[i]; + } + + double &x(int32_t i) { + assert(i >= 0); + assert(i < size_); + return x_[i]; + } + + double const &y(int32_t i) const { + assert(i >= 0); + assert(i < size_); + return y_[i]; + } + + double &y(int32_t i) { + assert(i >= 0); + assert(i < size_); + return y_[i]; + } + + double const &z(int32_t i) const { + assert(i >= 0); + assert(i < size_); + return z_[i]; + } + + double &z(int32_t i) { + assert(i >= 0); + assert(i < size_); + return z_[i]; + } + + int32_t const &id(int32_t i) const { + assert(i >= 0); + assert(i < size_); + return id_[i]; + } + + int32_t &id(int32_t i) { + assert(i >= 0); + assert(i < size_); + return id_[i]; + } + + // pad a size (in bytes) to the next multiple of the alignment + static constexpr uint32_t pad(size_t size) { return ((size + alignment - 1) / alignment * alignment); } + + // takes the size in elements, returns the size in bytes + static constexpr uint32_t compute_size(int32_t elements) { + assert(elements >= 0); + return pad(elements * sizeof(double)) + // x + pad(elements * sizeof(double)) + // y + pad(elements * sizeof(double)) + // z + elements * sizeof(int32_t); // id - no need to pad the last field + } + +private: + // non-owned memory + cms_int32_t size_; // must be the same as ROOT's Int_t + void *buffer_; //! + + // layout + double *x_; //[size_] + double *y_; //[size_] + double *z_; //[size_] + int32_t *id_; //[size_] +}; + +#endif // DataFormats_XyzId_interface_XyzIdSoA_h diff --git a/DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h b/DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h new file mode 100644 index 0000000000000..f563ca1fd65ce --- /dev/null +++ b/DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h @@ -0,0 +1,15 @@ +#ifndef DataFormats_XyzId_interface_alpaka_XyzIdDeviceCollection_h +#define DataFormats_XyzId_interface_alpaka_XyzIdDeviceCollection_h + +#include "DataFormats/Portable/interface/alpaka/PortableDeviceCollection.h" +#include "DataFormats/XyzId/interface/XyzIdSoA.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + // SoA with x, y, z, id fields in device global memory + using XyzIdDeviceCollection = PortableDeviceCollection<XyzIdSoA>; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#endif // DataFormats_XyzId_interface_alpaka_XyzIdDeviceCollection_h diff --git a/DataFormats/XyzId/src/alpaka/classes_cuda.h b/DataFormats/XyzId/src/alpaka/classes_cuda.h new file mode 100644 index 0000000000000..46686e2a72cfc --- /dev/null +++ b/DataFormats/XyzId/src/alpaka/classes_cuda.h @@ -0,0 +1,6 @@ +#define ALPAKA_ACC_GPU_CUDA_ENABLED +#define ALPAKA_HOST_ONLY + +#include "DataFormats/Common/interface/Wrapper.h" +#include "DataFormats/XyzId/interface/XyzIdSoA.h" +#include "DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h" diff --git a/DataFormats/XyzId/src/alpaka/classes_cuda_def.xml b/DataFormats/XyzId/src/alpaka/classes_cuda_def.xml new file mode 100644 index 0000000000000..c0ccfb0c71efe --- /dev/null +++ b/DataFormats/XyzId/src/alpaka/classes_cuda_def.xml @@ -0,0 +1,4 @@ +<lcgdict> + <class name="alpaka_cuda_async::XyzIdDeviceCollection" persistent="false"/> + <class name="edm::Wrapper<alpaka_cuda_async::XyzIdDeviceCollection>" persistent="false"/> +</lcgdict> diff --git a/DataFormats/XyzId/src/alpaka/classes_serial.h b/DataFormats/XyzId/src/alpaka/classes_serial.h new file mode 100644 index 0000000000000..47a2e8f03504c --- /dev/null +++ b/DataFormats/XyzId/src/alpaka/classes_serial.h @@ -0,0 +1,5 @@ +#define ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED + +#include "DataFormats/Common/interface/Wrapper.h" +#include "DataFormats/XyzId/interface/XyzIdSoA.h" +#include "DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h" diff --git a/DataFormats/XyzId/src/alpaka/classes_serial_def.xml b/DataFormats/XyzId/src/alpaka/classes_serial_def.xml new file mode 100644 index 0000000000000..2d855f273f3b8 --- /dev/null +++ b/DataFormats/XyzId/src/alpaka/classes_serial_def.xml @@ -0,0 +1,4 @@ +<lcgdict> + <class name="alpaka_serial_sync::XyzIdDeviceCollection"/> + <class name="edm::Wrapper<alpaka_serial_sync::XyzIdDeviceCollection>" splitLevel="0"/> +</lcgdict> diff --git a/DataFormats/XyzId/src/classes.h b/DataFormats/XyzId/src/classes.h new file mode 100644 index 0000000000000..2547bae676dfe --- /dev/null +++ b/DataFormats/XyzId/src/classes.h @@ -0,0 +1 @@ +#include "DataFormats/XyzId/interface/XyzIdSoA.h" diff --git a/DataFormats/XyzId/src/classes_def.xml b/DataFormats/XyzId/src/classes_def.xml new file mode 100644 index 0000000000000..59c9e3eab4437 --- /dev/null +++ b/DataFormats/XyzId/src/classes_def.xml @@ -0,0 +1,3 @@ +<lcgdict> + <class name="XyzIdSoA"/> +</lcgdict> diff --git a/DataFormats/XyzIdCudaAsync/BuildFile.xml b/DataFormats/XyzIdCudaAsync/BuildFile.xml new file mode 100644 index 0000000000000..ae79b036a8be7 --- /dev/null +++ b/DataFormats/XyzIdCudaAsync/BuildFile.xml @@ -0,0 +1,9 @@ +<use name="alpaka-cuda"/> +<use name="rootcore"/> +<use name="DataFormats/Common"/> +<use name="DataFormats/XyzId"/> +<flags LCG_DICT_HEADER="classes_cuda.h"/> +<flags LCG_DICT_XML="classes_cuda_def.xml"/> +<export> + <lib name="1"/> +</export> diff --git a/DataFormats/XyzIdCudaAsync/src/classes_cuda.h b/DataFormats/XyzIdCudaAsync/src/classes_cuda.h new file mode 120000 index 0000000000000..1f02d4849ccd4 --- /dev/null +++ b/DataFormats/XyzIdCudaAsync/src/classes_cuda.h @@ -0,0 +1 @@ +../../XyzId/src/alpaka/classes_cuda.h \ No newline at end of file diff --git a/DataFormats/XyzIdCudaAsync/src/classes_cuda_def.xml b/DataFormats/XyzIdCudaAsync/src/classes_cuda_def.xml new file mode 120000 index 0000000000000..5368a08c26ff4 --- /dev/null +++ b/DataFormats/XyzIdCudaAsync/src/classes_cuda_def.xml @@ -0,0 +1 @@ +../../XyzId/src/alpaka/classes_cuda_def.xml \ No newline at end of file diff --git a/DataFormats/XyzIdSerialSync/BuildFile.xml b/DataFormats/XyzIdSerialSync/BuildFile.xml new file mode 100644 index 0000000000000..55fbe28b28abe --- /dev/null +++ b/DataFormats/XyzIdSerialSync/BuildFile.xml @@ -0,0 +1,9 @@ +<use name="alpaka-serial"/> +<use name="rootcore"/> +<use name="DataFormats/Common"/> +<use name="DataFormats/XyzId"/> +<flags LCG_DICT_HEADER="classes_serial.h"/> +<flags LCG_DICT_XML="classes_serial_def.xml"/> +<export> + <lib name="1"/> +</export> diff --git a/DataFormats/XyzIdSerialSync/src/classes_serial.h b/DataFormats/XyzIdSerialSync/src/classes_serial.h new file mode 120000 index 0000000000000..a752a7e7997b1 --- /dev/null +++ b/DataFormats/XyzIdSerialSync/src/classes_serial.h @@ -0,0 +1 @@ +../../XyzId/src/alpaka/classes_serial.h \ No newline at end of file diff --git a/DataFormats/XyzIdSerialSync/src/classes_serial_def.xml b/DataFormats/XyzIdSerialSync/src/classes_serial_def.xml new file mode 120000 index 0000000000000..8a0fa91cac09c --- /dev/null +++ b/DataFormats/XyzIdSerialSync/src/classes_serial_def.xml @@ -0,0 +1 @@ +../../XyzId/src/alpaka/classes_serial_def.xml \ No newline at end of file diff --git a/HeterogeneousCore/AlpakaCore/BuildFile.xml b/HeterogeneousCore/AlpakaCore/BuildFile.xml new file mode 100644 index 0000000000000..f839a92152d40 --- /dev/null +++ b/HeterogeneousCore/AlpakaCore/BuildFile.xml @@ -0,0 +1,6 @@ +<use name="FWCore/Framework"/> +<use name="FWCore/ServiceRegistry"/> +<use name="HeterogeneousCore/AlpakaInterface"/> +<export> + <lib name="1"/> +</export> diff --git a/HeterogeneousCore/AlpakaCore/interface/MakerMacros.h b/HeterogeneousCore/AlpakaCore/interface/MakerMacros.h new file mode 100644 index 0000000000000..3096f1f3fcf21 --- /dev/null +++ b/HeterogeneousCore/AlpakaCore/interface/MakerMacros.h @@ -0,0 +1,11 @@ +#ifndef HeterogeneousCore_AlpakaCore_interface_MakerMacros_h +#define HeterogeneousCore_AlpakaCore_interface_MakerMacros_h + +#include "FWCore/Framework/interface/MakerMacros.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +// force expanding ALPAKA_ACCELERATOR_NAMESPACE before stringification inside DEFINE_FWK_MODULE +#define DEFINE_FWK_ALPAKA_MODULE2(name) DEFINE_FWK_MODULE(name) +#define DEFINE_FWK_ALPAKA_MODULE(name) DEFINE_FWK_ALPAKA_MODULE2(ALPAKA_ACCELERATOR_NAMESPACE::name) + +#endif // HeterogeneousCore_AlpakaCore_interface_MakerMacros_h diff --git a/HeterogeneousCore/AlpakaInterface/BuildFile.xml b/HeterogeneousCore/AlpakaInterface/BuildFile.xml new file mode 100644 index 0000000000000..06905828f6ea6 --- /dev/null +++ b/HeterogeneousCore/AlpakaInterface/BuildFile.xml @@ -0,0 +1,4 @@ +<use name="alpaka"/> +<export> + <lib name="1"/> +</export> diff --git a/HeterogeneousCore/AlpakaInterface/README.md b/HeterogeneousCore/AlpakaInterface/README.md new file mode 100644 index 0000000000000..709098b772665 --- /dev/null +++ b/HeterogeneousCore/AlpakaInterface/README.md @@ -0,0 +1,6 @@ +## HeterogeneousCore/AlpakaInterface + +This package only depends on the `alpaka` header-only external library, and +provides the interface used by other packages in CMSSW. + +It is safe to be used inside DataFormats packages. diff --git a/HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h b/HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h new file mode 100644 index 0000000000000..a5ea8c0289594 --- /dev/null +++ b/HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h @@ -0,0 +1,164 @@ +#ifndef HeterogeneousCore_AlpakaInterface_interface_alpaka_config_h +#define HeterogeneousCore_AlpakaInterface_interface_alpaka_config_h + +#include <type_traits> + +#include <alpaka/alpaka.hpp> + +#include "FWCore/Utilities/interface/stringize.h" + +namespace alpaka_common { + + // common types and dimensions + using Idx = uint32_t; + using Extent = uint32_t; + using Offsets = Extent; + + using Dim0D = alpaka::DimInt<0u>; + using Dim1D = alpaka::DimInt<1u>; + using Dim2D = alpaka::DimInt<2u>; + using Dim3D = alpaka::DimInt<3u>; + + template <typename TDim> + using Vec = alpaka::Vec<TDim, Idx>; + using Vec1D = Vec<Dim1D>; + using Vec2D = Vec<Dim2D>; + using Vec3D = Vec<Dim3D>; + using Scalar = Vec<Dim0D>; + + template <typename TDim> + using WorkDiv = alpaka::WorkDivMembers<TDim, Idx>; + using WorkDiv1D = WorkDiv<Dim1D>; + using WorkDiv2D = WorkDiv<Dim2D>; + using WorkDiv3D = WorkDiv<Dim3D>; + + // host types + using DevHost = alpaka::DevCpu; + using PltfHost = alpaka::Pltf<DevHost>; + +} // namespace alpaka_common + +#ifdef ALPAKA_ACC_GPU_CUDA_ENABLED +namespace alpaka_cuda_async { + using namespace alpaka_common; + + using Platform = alpaka::PltfCudaRt; + using Device = alpaka::DevCudaRt; + using Queue = alpaka::QueueCudaRtNonBlocking; + using Event = alpaka::EventCudaRt; + + template <typename TDim> + using Acc = alpaka::AccGpuCudaRt<TDim, Idx>; + using Acc1D = Acc<Dim1D>; + using Acc2D = Acc<Dim2D>; + using Acc3D = Acc<Dim3D>; + +} // namespace alpaka_cuda_async + +#ifdef ALPAKA_ACCELERATOR_NAMESPACE +#define ALPAKA_DUPLICATE_NAMESPACE +#else +#define ALPAKA_ACCELERATOR_NAMESPACE alpaka_cuda_async +#define ALPAKA_TYPE_SUFFIX CudaAsync +#endif + +#endif // ALPAKA_ACC_GPU_CUDA_ENABLED + +#ifdef ALPAKA_ACC_GPU_HIP_ENABLED +namespace alpaka_hip_async { + using namespace alpaka_common; + + using Platform = alpaka::PltfHipRt; + using Device = alpaka::DevHipRt; + using Queue = alpaka::QueueHipRtNonBlocking; + using Event = alpaka::EventHipRt; + + template <typename TDim> + using Acc = alpaka::AccGpuHipRt<TDim, Idx>; + using Acc1D = Acc<Dim1D>; + using Acc2D = Acc<Dim2D>; + using Acc3D = Acc<Dim3D>; + +} // namespace alpaka_hip_async + +#ifdef ALPAKA_ACCELERATOR_NAMESPACE +#define ALPAKA_DUPLICATE_NAMESPACE +#else +#define ALPAKA_ACCELERATOR_NAMESPACE alpaka_hip_async +#define ALPAKA_TYPE_SUFFIX HipAsync +#endif + +#endif // ALPAKA_ACC_GPU_HIP_ENABLED + +#ifdef ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED +namespace alpaka_serial_sync { + using namespace alpaka_common; + + using Platform = alpaka::PltfCpu; + using Device = alpaka::DevCpu; + using Queue = alpaka::QueueCpuBlocking; + using Event = alpaka::EventCpu; + + template <typename TDim> + using Acc = alpaka::AccCpuSerial<TDim, Idx>; + using Acc1D = Acc<Dim1D>; + using Acc2D = Acc<Dim2D>; + using Acc3D = Acc<Dim3D>; + +} // namespace alpaka_serial_sync + +#ifdef ALPAKA_ACCELERATOR_NAMESPACE +#define ALPAKA_DUPLICATE_NAMESPACE +#else +#define ALPAKA_ACCELERATOR_NAMESPACE alpaka_serial_sync +#define ALPAKA_TYPE_SUFFIX SerialSync +#endif + +#endif // ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED + +#ifdef ALPAKA_ACC_CPU_B_TBB_T_SEQ_ENABLED +namespace alpaka_tbb_async { + using namespace alpaka_common; + + using Platform = alpaka::PltfCpu; + using Device = alpaka::DevCpu; + using Queue = alpaka::QueueCpuNonBlocking; + using Event = alpaka::EventCpu; + + template <typename TDim> + using Acc = alpaka::AccCpuTbbBlocks<TDim, Idx>; + using Acc1D = Acc<Dim1D>; + using Acc2D = Acc<Dim2D>; + using Acc3D = Acc<Dim3D>; + +} // namespace alpaka_tbb_async + +#ifdef ALPAKA_ACCELERATOR_NAMESPACE +#define ALPAKA_DUPLICATE_NAMESPACE +#else +#define ALPAKA_ACCELERATOR_NAMESPACE alpaka_tbb_async +#define ALPAKA_TYPE_SUFFIX TbbAsync +#endif + +#endif // ALPAKA_ACC_CPU_B_TBB_T_SEQ_ENABLED + +#if defined ALPAKA_DUPLICATE_NAMESPACE +#error Only one alpaka backend symbol can be defined at the same time: ALPAKA_ACC_GPU_CUDA_ENABLED, ALPAKA_ACC_GPU_HIP_ENABLED, ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED, ALPAKA_ACC_CPU_B_TBB_T_SEQ_ENABLED. +#endif + +#if defined ALPAKA_ACCELERATOR_NAMESPACE + +// create a new backend-specific identifier based on the original type name and a backend-specific suffix +#define ALPAKA_TYPE_ALIAS__(TYPE, SUFFIX) TYPE##SUFFIX +#define ALPAKA_TYPE_ALIAS_(TYPE, SUFFIX) ALPAKA_TYPE_ALIAS__(TYPE, SUFFIX) +#define ALPAKA_TYPE_ALIAS(TYPE) ALPAKA_TYPE_ALIAS_(TYPE, ALPAKA_TYPE_SUFFIX) + +// declare the backend-specific identifier as an alias for the namespace-based type name +#define DECLARE_ALPAKA_TYPE_ALIAS(TYPE) using ALPAKA_TYPE_ALIAS(TYPE) = ALPAKA_ACCELERATOR_NAMESPACE::TYPE + +// define a null-terminated string containing the backend-specific identifier +#define ALPAKA_TYPE_ALIAS_NAME(TYPE) EDM_STRINGIZE(ALPAKA_TYPE_ALIAS(TYPE)) + +#endif // ALPAKA_ACCELERATOR_NAMESPACE + +#endif // HeterogeneousCore_AlpakaInterface_interface_alpaka_config_h diff --git a/HeterogeneousCore/AlpakaInterface/interface/alpaka/host.h b/HeterogeneousCore/AlpakaInterface/interface/alpaka/host.h new file mode 100644 index 0000000000000..39a54b3dffe51 --- /dev/null +++ b/HeterogeneousCore/AlpakaInterface/interface/alpaka/host.h @@ -0,0 +1,9 @@ +#ifndef HeterogeneousCore_AlpakaInterface_interface_alpaka_host_h +#define HeterogeneousCore_AlpakaInterface_interface_alpaka_host_h + +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +// alpaka host device +inline const alpaka_common::DevHost host = alpaka::getDevByIdx<alpaka_common::PltfHost>(0u); + +#endif // HeterogeneousCore_AlpakaInterface_interface_alpaka_host_h diff --git a/HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h b/HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h new file mode 100644 index 0000000000000..17a8c7d512cd4 --- /dev/null +++ b/HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h @@ -0,0 +1,41 @@ +#ifndef HeterogeneousCore_AlpakaServices_interface_AlpakaService_h +#define HeterogeneousCore_AlpakaServices_interface_AlpakaService_h + +#include <vector> + +#include <alpaka/alpaka.hpp> + +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +namespace edm { + class ActivityRegistry; + class ConfigurationDescriptions; + class ParameterSet; +} // namespace edm + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class AlpakaService { + public: + AlpakaService(edm::ParameterSet const& config, edm::ActivityRegistry&); + ~AlpakaService(); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + bool enabled() const { return enabled_; } + + std::vector<Device> const& devices() const { return devices_; } + + Device const& device(uint32_t index) const { return devices_.at(index); } + + private: + bool enabled_ = false; + bool verbose_ = false; + std::vector<Device> devices_; + }; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +DECLARE_ALPAKA_TYPE_ALIAS(AlpakaService); + +#endif // HeterogeneousCore_AlpakaServices_interface_AlpakaService_h diff --git a/HeterogeneousCore/AlpakaServices/plugins/alpaka/plugins.cc b/HeterogeneousCore/AlpakaServices/plugins/alpaka/plugins.cc new file mode 100644 index 0000000000000..cda77778585b7 --- /dev/null +++ b/HeterogeneousCore/AlpakaServices/plugins/alpaka/plugins.cc @@ -0,0 +1,5 @@ +#include "FWCore/ServiceRegistry/interface/ServiceMaker.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" +#include "HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h" + +DEFINE_FWK_SERVICE(ALPAKA_TYPE_ALIAS(AlpakaService)); diff --git a/HeterogeneousCore/AlpakaServices/src/alpaka/AlpakaService.cc b/HeterogeneousCore/AlpakaServices/src/alpaka/AlpakaService.cc new file mode 100644 index 0000000000000..4e00b3ec9be0f --- /dev/null +++ b/HeterogeneousCore/AlpakaServices/src/alpaka/AlpakaService.cc @@ -0,0 +1,86 @@ +#include <iomanip> +#include <iostream> +#include <limits> + +#include <boost/core/demangle.hpp> + +#include <alpaka/alpaka.hpp> + +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h" + +#ifdef ALPAKA_ACC_GPU_CUDA_ENABLED +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "HeterogeneousCore/CUDAServices/interface/CUDAService.h" +#endif // ALPAKA_ACC_GPU_CUDA_ENABLED + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + AlpakaService::AlpakaService(edm::ParameterSet const& config, edm::ActivityRegistry&) + : enabled_(config.getUntrackedParameter<bool>("enabled")), + verbose_(config.getUntrackedParameter<bool>("verbose")) { +#ifdef ALPAKA_ACC_GPU_CUDA_ENABLED + // rely on the CUDAService to initialise the CUDA devices + edm::Service<CUDAService> cudaService; +#endif // ALPAKA_ACC_GPU_CUDA_ENABLED + + // TODO + // - handle alpaka caching allocators ? + // - extract and print more information about the platform and devices + + if (not enabled_) { + edm::LogInfo("AlpakaService") << ALPAKA_TYPE_ALIAS_NAME(AlpakaService) << " disabled by configuration"; + return; + } + +#ifdef ALPAKA_ACC_GPU_CUDA_ENABLED + if (not cudaService->enabled()) { + enabled_ = false; + edm::LogInfo("AlpakaService") << ALPAKA_TYPE_ALIAS_NAME(AlpakaService) << " disabled by CUDAService"; + return; + } +#endif // ALPAKA_ACC_GPU_CUDA_ENABLED + + // enumerate all devices on this platform + uint32_t n = alpaka::getDevCount<Platform>(); + if (n == 0) { + const std::string platform = boost::core::demangle(typeid(Platform).name()); + edm::LogWarning("AlpakaService") << "Could not find any divices on platform " << platform << ".\n" + << "Disabling " << ALPAKA_TYPE_ALIAS_NAME(AlpakaService) << "."; + enabled_ = false; + return; + } + + devices_.reserve(n); + for (uint32_t i = 0; i < n; ++i) { + devices_.push_back(alpaka::getDevByIdx<Platform>(i)); + //assert(getDeviceIndex(devices_.back()) == static_cast<int>(i)); + } + + { + const char* suffix[] = {"s.", ":", "s:"}; + edm::LogInfo out("AlpakaService"); + out << ALPAKA_TYPE_ALIAS_NAME(AlpakaService) << " succesfully initialised.\n"; + out << "Found " << n << " device" << suffix[n < 2 ? n : 2]; + for (auto const& device : devices_) { + out << "\n - " << alpaka::getName(device); + } + } + } + + AlpakaService::~AlpakaService() { + // TODO + } + + void AlpakaService::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.addUntracked<bool>("enabled", true); + desc.addUntracked<bool>("verbose", false); + + descriptions.add(ALPAKA_TYPE_ALIAS_NAME(AlpakaService), desc); + } + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/BuildFile.xml b/HeterogeneousCore/AlpakaServicesCudaAsync/BuildFile.xml new file mode 100644 index 0000000000000..25ca7a0280a51 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/BuildFile.xml @@ -0,0 +1,11 @@ +<use name="alpaka-cuda"/> +<use name="boost"/> +<use name="FWCore/MessageLogger"/> +<use name="FWCore/ParameterSet"/> +<use name="HeterogeneousCore/AlpakaCore" source_only="1"/> +<use name="HeterogeneousCore/AlpakaInterface" source_only="1"/> +<!-- This dependency is added only for the CUDA backend --> +<use name="HeterogeneousCore/CUDAServices"/> +<export> + <lib name="1"/> +</export> diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/README.md b/HeterogeneousCore/AlpakaServicesCudaAsync/README.md new file mode 100644 index 0000000000000..1ed2480ba9ef1 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/README.md @@ -0,0 +1,7 @@ +## HeterogeneousCore/AlpakaServicesCudaAsync + +This is a dummy package to emulate the expected behaviour of the build system. +The .../alpaka/ directories are symlinked from HeterogeneousCore/AlpakaServices +to avoid the scram error about the inclusion of private source files. +Its content should eventually be built from HeterogeneousCore/AlpakaServices for +the cuda async backend. diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/BuildFile.xml b/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/BuildFile.xml new file mode 100644 index 0000000000000..b58a61405ce5b --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/BuildFile.xml @@ -0,0 +1,12 @@ +<library file="*.cc" name="HeterogeneousCoreAlpakaServicesCudaAsyncPlugins"> + <use name="alpaka-cuda"/> + <use name="FWCore/ServiceRegistry"/> + <use name="HeterogeneousCore/AlpakaCore" source_only="1"/> + <!-- + The dependency on "HeterogeneousCore/AlpakaServices" should automatically expand to + "HeterogeneousCore/AlpakaServices" and "HeterogeneousCore/AlpakaServicesCudaAsync" + (if they exist) + --> + <use name="HeterogeneousCore/AlpakaServicesCudaAsync"/> + <flags EDM_PLUGIN="1"/> +</library> diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/alpaka b/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/alpaka new file mode 120000 index 0000000000000..c07bb7e4fcd38 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/alpaka @@ -0,0 +1 @@ +../../AlpakaServices/plugins/alpaka \ No newline at end of file diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/plugins.cc b/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/plugins.cc new file mode 100644 index 0000000000000..209f67887da0f --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/plugins/plugins.cc @@ -0,0 +1,3 @@ +#define ALPAKA_ACC_GPU_CUDA_ENABLED +#define ALPAKA_HOST_ONLY +#include "alpaka/plugins.cc" diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/src/AlpakaService.cc b/HeterogeneousCore/AlpakaServicesCudaAsync/src/AlpakaService.cc new file mode 100644 index 0000000000000..7cfacc86c0e3a --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/src/AlpakaService.cc @@ -0,0 +1,3 @@ +#define ALPAKA_ACC_GPU_CUDA_ENABLED +#define ALPAKA_HOST_ONLY +#include "alpaka/AlpakaService.cc" diff --git a/HeterogeneousCore/AlpakaServicesCudaAsync/src/alpaka b/HeterogeneousCore/AlpakaServicesCudaAsync/src/alpaka new file mode 120000 index 0000000000000..2bf74ab3a89bd --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesCudaAsync/src/alpaka @@ -0,0 +1 @@ +../../AlpakaServices/src/alpaka \ No newline at end of file diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/BuildFile.xml b/HeterogeneousCore/AlpakaServicesSerialSync/BuildFile.xml new file mode 100644 index 0000000000000..55da51db92b65 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/BuildFile.xml @@ -0,0 +1,9 @@ +<use name="alpaka-serial"/> +<use name="boost"/> +<use name="FWCore/MessageLogger"/> +<use name="FWCore/ParameterSet"/> +<use name="HeterogeneousCore/AlpakaCore" source_only="1"/> +<use name="HeterogeneousCore/AlpakaInterface" source_only="1"/> +<export> + <lib name="1"/> +</export> diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/README.md b/HeterogeneousCore/AlpakaServicesSerialSync/README.md new file mode 100644 index 0000000000000..c80ed197a4207 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/README.md @@ -0,0 +1,7 @@ +## HeterogeneousCore/AlpakaServicesSerialSync + +This is a dummy package to emulate the expected behaviour of the build system. +The .../alpaka/ directories are symlinked from HeterogeneousCore/AlpakaServices +to avoid the scram error about the inclusion of private source files. +Its content should eventually be built from HeterogeneousCore/AlpakaServices for +the serial sync backend. diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/plugins/BuildFile.xml b/HeterogeneousCore/AlpakaServicesSerialSync/plugins/BuildFile.xml new file mode 100644 index 0000000000000..62d665c5174f2 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/plugins/BuildFile.xml @@ -0,0 +1,12 @@ +<library file="*.cc" name="HeterogeneousCoreAlpakaServicesSerialSyncPlugins"> + <use name="alpaka-serial"/> + <use name="FWCore/ServiceRegistry"/> + <use name="HeterogeneousCore/AlpakaCore" source_only="1"/> + <!-- + The dependency on "HeterogeneousCore/AlpakaServices" should automatically expand to + "HeterogeneousCore/AlpakaServices" and "HeterogeneousCore/AlpakaServicesSerialSync" + (if they exist) + --> + <use name="HeterogeneousCore/AlpakaServicesSerialSync"/> + <flags EDM_PLUGIN="1"/> +</library> diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/plugins/alpaka b/HeterogeneousCore/AlpakaServicesSerialSync/plugins/alpaka new file mode 120000 index 0000000000000..c07bb7e4fcd38 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/plugins/alpaka @@ -0,0 +1 @@ +../../AlpakaServices/plugins/alpaka \ No newline at end of file diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/plugins/plugins.cc b/HeterogeneousCore/AlpakaServicesSerialSync/plugins/plugins.cc new file mode 100644 index 0000000000000..139665715a41e --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/plugins/plugins.cc @@ -0,0 +1,2 @@ +#define ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED +#include "alpaka/plugins.cc" diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/src/AlpakaService.cc b/HeterogeneousCore/AlpakaServicesSerialSync/src/AlpakaService.cc new file mode 100644 index 0000000000000..3e62d6a1d9781 --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/src/AlpakaService.cc @@ -0,0 +1,2 @@ +#define ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED +#include "alpaka/AlpakaService.cc" diff --git a/HeterogeneousCore/AlpakaServicesSerialSync/src/alpaka b/HeterogeneousCore/AlpakaServicesSerialSync/src/alpaka new file mode 120000 index 0000000000000..2bf74ab3a89bd --- /dev/null +++ b/HeterogeneousCore/AlpakaServicesSerialSync/src/alpaka @@ -0,0 +1 @@ +../../AlpakaServices/src/alpaka \ No newline at end of file diff --git a/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlgo.dev.cc b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlgo.dev.cc new file mode 100644 index 0000000000000..26799232178e3 --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlgo.dev.cc @@ -0,0 +1,22 @@ +#include <alpaka/alpaka.hpp> + +#include "DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +#include "XyzIdAlgo.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + void XyzIdAlgo::fill(Queue& queue, XyzIdDeviceCollection& collection) const { + auto const& deviceProperties = alpaka::getAccDevProps<Acc1D>(alpaka::getDev(queue)); + uint32_t maxThreadsPerBlock = deviceProperties.m_blockThreadExtentMax[0]; + + uint32_t threadsPerBlock = maxThreadsPerBlock; + uint32_t blocksPerGrid = (collection->size() + threadsPerBlock - 1) / threadsPerBlock; + uint32_t elementsPerThread = 1; + auto workDiv = WorkDiv1D{blocksPerGrid, threadsPerBlock, elementsPerThread}; + + alpaka::exec<Acc1D>(queue, workDiv, XyzIdAlgoKernel{}, &collection->id(0), collection->size()); + } + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE diff --git a/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlgo.h b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlgo.h new file mode 100644 index 0000000000000..0c7d65639d535 --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlgo.h @@ -0,0 +1,29 @@ +#ifndef HeterogeneousCore_AlpakaTest_plugins_alpaka_XyzIdAlgo_h +#define HeterogeneousCore_AlpakaTest_plugins_alpaka_XyzIdAlgo_h + +#include <alpaka/alpaka.hpp> + +#include "DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +class XyzIdAlgoKernel { +public: + template <typename TAcc> + ALPAKA_FN_ACC void operator()(TAcc const& acc, int32_t* id, int32_t size) const { + int32_t idx = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0u]; + if (idx < size) { + id[idx] = idx; + } + } +}; + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class XyzIdAlgo { + public: + void fill(Queue& queue, XyzIdDeviceCollection& collection) const; + }; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#endif // HeterogeneousCore_AlpakaTest_plugins_alpaka_XyzIdAlgo_h diff --git a/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaAnalyzer.cc b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaAnalyzer.cc new file mode 100644 index 0000000000000..77009605d16ac --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaAnalyzer.cc @@ -0,0 +1,53 @@ +// The "Analyzer" makes sense only in the cpu memory space +#if defined(ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED) + +#include <cassert> +#include <string> +#include <iostream> + +#include "DataFormats/XyzId/interface/XyzIdHostCollection.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDAnalyzer.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class XyzIdAlpakaAnalyzer : public edm::stream::EDAnalyzer<> { + public: + XyzIdAlpakaAnalyzer(edm::ParameterSet const& config) + : source_{config.getParameter<edm::InputTag>("source")}, token_{consumes<XyzIdHostCollection>(source_)} {} + + void analyze(edm::Event const& event, edm::EventSetup const&) override { + XyzIdHostCollection const& product = event.get(token_); + + for (int32_t i = 0; i < product->size(); ++i) { + //std::cout << source_ << "[" << i << "] = " << product->id(i) << std::endl; + assert(product->id(i) == i); + } + std::cout << "XyzIdAlpakaAnalyzer:\n" << source_.encode() << ".size() = " << product->size() << std::endl; + } + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add<edm::InputTag>("source"); + descriptions.addWithDefaultLabel(desc); + } + + private: + const edm::InputTag source_; + const edm::EDGetTokenT<XyzIdHostCollection> token_; + }; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#include "HeterogeneousCore/AlpakaCore/interface/MakerMacros.h" +DEFINE_FWK_ALPAKA_MODULE(XyzIdAlpakaAnalyzer); + +#endif // defined(ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED) diff --git a/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaProducer.cc b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaProducer.cc new file mode 100644 index 0000000000000..328d4b7e4e681 --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaProducer.cc @@ -0,0 +1,76 @@ +#include <optional> +#include <string> + +#include <alpaka/alpaka.hpp> + +#include "DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/host.h" +#include "HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h" + +#include "XyzIdAlgo.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class XyzIdAlpakaProducer : public edm::stream::EDProducer<> { + public: + XyzIdAlpakaProducer(edm::ParameterSet const& config) + : deviceToken_{produces<XyzIdDeviceCollection>()}, size_{config.getParameter<int32_t>("size")} {} + + void beginStream(edm::StreamID sid) override { + // choose a device based on the EDM stream number + edm::Service<ALPAKA_TYPE_ALIAS(AlpakaService)> service; + if (not service->enabled()) { + throw cms::Exception("Configuration") << ALPAKA_TYPE_ALIAS_NAME(AlpakaService) << " is disabled."; + } + auto& devices = service->devices(); + unsigned int index = sid.value() % devices.size(); + device_ = devices[index]; + } + + void produce(edm::Event& event, edm::EventSetup const&) override { + // create a queue to submit async work + Queue queue{*device_}; + XyzIdDeviceCollection deviceProduct{size_, *device_}; + + // run the algorithm, potentially asynchronously + algo_.fill(queue, deviceProduct); + + // wait for any asynchronous work to complete + alpaka::wait(queue); + + event.emplace(deviceToken_, std::move(deviceProduct)); + } + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add<int32_t>("size"); + descriptions.addWithDefaultLabel(desc); + } + + private: + const edm::EDPutTokenT<XyzIdDeviceCollection> deviceToken_; + const int32_t size_; + + // device associated to the EDM stream + std::optional<Device> device_; + + // implementation of the algorithm + XyzIdAlgo algo_; + }; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#include "HeterogeneousCore/AlpakaCore/interface/MakerMacros.h" +DEFINE_FWK_ALPAKA_MODULE(XyzIdAlpakaProducer); diff --git a/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaTranscriber.cc b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaTranscriber.cc new file mode 100644 index 0000000000000..33bdbc3ca52c2 --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/plugins/alpaka/XyzIdAlpakaTranscriber.cc @@ -0,0 +1,78 @@ +// The "Transcriber" makes sense only across different memory spaces +#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) or defined(ALPAKA_ACC_GPU_HIP_ENABLED) + +#include <optional> +#include <string> + +#include <alpaka/alpaka.hpp> + +#include "DataFormats/XyzId/interface/XyzIdHostCollection.h" +#include "DataFormats/XyzId/interface/alpaka/XyzIdDeviceCollection.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/config.h" +#include "HeterogeneousCore/AlpakaInterface/interface/alpaka/host.h" +#include "HeterogeneousCore/AlpakaServices/interface/alpaka/AlpakaService.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class XyzIdAlpakaTranscriber : public edm::stream::EDProducer<> { + public: + XyzIdAlpakaTranscriber(edm::ParameterSet const& config) + : deviceToken_{consumes<XyzIdDeviceCollection>(config.getParameter<edm::InputTag>("source"))}, + hostToken_{produces<XyzIdHostCollection>()} {} + + void beginStream(edm::StreamID sid) override { + // choose a device based on the EDM stream number + edm::Service<ALPAKA_TYPE_ALIAS(AlpakaService)> service; + if (not service->enabled()) { + throw cms::Exception("Configuration") << ALPAKA_TYPE_ALIAS_NAME(AlpakaService) << " is disabled."; + } + auto& devices = service->devices(); + unsigned int index = sid.value() % devices.size(); + device = devices[index]; + } + + void produce(edm::Event& event, edm::EventSetup const&) override { + // create a queue to submit async work + Queue queue{*device}; + XyzIdDeviceCollection const& deviceProduct = event.get(deviceToken_); + + XyzIdHostCollection hostProduct{deviceProduct->size(), host, *device}; + alpaka::memcpy(queue, hostProduct.buffer(), deviceProduct.buffer()); + + // wait for any async work to complete + alpaka::wait(queue); + + event.emplace(hostToken_, std::move(hostProduct)); + } + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add<edm::InputTag>("source"); + descriptions.addWithDefaultLabel(desc); + } + + private: + const edm::EDGetTokenT<XyzIdDeviceCollection> deviceToken_; + const edm::EDPutTokenT<XyzIdHostCollection> hostToken_; + + // device associated to the EDM stream + std::optional<Device> device; + }; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#include "HeterogeneousCore/AlpakaCore/interface/MakerMacros.h" +DEFINE_FWK_ALPAKA_MODULE(XyzIdAlpakaTranscriber); + +#endif // defined(ALPAKA_ACC_GPU_CUDA_ENABLED) or defined(ALPAKA_ACC_GPU_HIP_ENABLED) diff --git a/HeterogeneousCore/AlpakaTest/test/reader.py b/HeterogeneousCore/AlpakaTest/test/reader.py new file mode 100644 index 0000000000000..8ad0fe6631f56 --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/test/reader.py @@ -0,0 +1,26 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("Reader") + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring('file:xyzid.root') +) + +process.load("FWCore.MessageService.MessageLogger_cfi") + +process.AlpakaServiceSerialSync = cms.Service("AlpakaServiceSerialSync") +process.MessageLogger.AlpakaService = cms.untracked.PSet() + +process.xyzIdAlpakaAnalyzerFromCuda = cms.EDAnalyzer('alpaka_serial_sync::XyzIdAlpakaAnalyzer', + source = cms.InputTag('xyzIdAlpakaTranscriberFromCuda') +) + +process.xyzIdAlpakaAnalyzerSerial = cms.EDAnalyzer('alpaka_serial_sync::XyzIdAlpakaAnalyzer', + source = cms.InputTag('xyzIdAlpakaProducerSerial') +) + +process.cuda_path = cms.Path(process.xyzIdAlpakaAnalyzerFromCuda) + +process.serial_path = cms.Path(process.xyzIdAlpakaAnalyzerSerial) + +process.maxEvents.input = 10 diff --git a/HeterogeneousCore/AlpakaTest/test/writer.py b/HeterogeneousCore/AlpakaTest/test/writer.py new file mode 100644 index 0000000000000..1888082264c39 --- /dev/null +++ b/HeterogeneousCore/AlpakaTest/test/writer.py @@ -0,0 +1,56 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("Writer") + +process.source = cms.Source("EmptySource") + +process.load("FWCore.MessageService.MessageLogger_cfi") + +process.add_(cms.Service("CUDAService")) +process.MessageLogger.CUDAService = cms.untracked.PSet() + +process.AlpakaServiceCudaAsync = cms.Service("AlpakaServiceCudaAsync") +process.AlpakaServiceSerialSync = cms.Service("AlpakaServiceSerialSync") +process.MessageLogger.AlpakaService = cms.untracked.PSet() + +process.xyzIdAlpakaProducerCuda = cms.EDProducer('alpaka_cuda_async::XyzIdAlpakaProducer', + size = cms.int32(42) +) + +process.xyzIdAlpakaTranscriberFromCuda = cms.EDProducer('alpaka_cuda_async::XyzIdAlpakaTranscriber', + source = cms.InputTag('xyzIdAlpakaProducerCuda') +) + +process.xyzIdAlpakaAnalyzerFromCuda = cms.EDAnalyzer('alpaka_serial_sync::XyzIdAlpakaAnalyzer', + source = cms.InputTag('xyzIdAlpakaTranscriberFromCuda') +) + +process.xyzIdAlpakaProducerSerial = cms.EDProducer('alpaka_serial_sync::XyzIdAlpakaProducer', + size = cms.int32(42) +) + +process.xyzIdAlpakaAnalyzerSerial = cms.EDAnalyzer('alpaka_serial_sync::XyzIdAlpakaAnalyzer', + source = cms.InputTag('xyzIdAlpakaProducerSerial') +) + +process.output = cms.OutputModule("PoolOutputModule", + fileName = cms.untracked.string("xyzid.root"), + outputCommands = cms.untracked.vstring( + 'drop *', + 'keep *_xyzIdAlpakaTranscriberFromCuda_*_*', + 'keep *_xyzIdAlpakaProducerSerial_*_*', + ) +) + +process.cuda_path = cms.Path( + process.xyzIdAlpakaProducerCuda + + process.xyzIdAlpakaTranscriberFromCuda + + process.xyzIdAlpakaAnalyzerFromCuda) + +process.serial_path = cms.Path( + process.xyzIdAlpakaProducerSerial + + process.xyzIdAlpakaAnalyzerSerial) + +process.output_path = cms.EndPath(process.output) + +process.maxEvents.input = 10 diff --git a/HeterogeneousCore/AlpakaTestCudaAsync/README.md b/HeterogeneousCore/AlpakaTestCudaAsync/README.md new file mode 100644 index 0000000000000..8a9d0d206ce07 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestCudaAsync/README.md @@ -0,0 +1,7 @@ +## HeterogeneousCore/AlpakaTestCudaAsync + +This is a dummy package to emulate the expected behaviour of the build system. +The .../alpaka/ directories are symlinked from HeterogeneousCore/AlpakaTest +to avoid the scram error about the inclusion of private source files. +Its content should eventually be built from HeterogeneousCore/AlpakaTest for +the cuda async backend. diff --git a/HeterogeneousCore/AlpakaTestCudaAsync/plugins/BuildFile.xml b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/BuildFile.xml new file mode 100644 index 0000000000000..8529f569de5b7 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/BuildFile.xml @@ -0,0 +1,11 @@ +<library file="*.cc *.cu" name="HeterogeneousCoreAlpakaTestCudaAsyncPlugins"> + <use name="alpaka-cuda"/> + <use name="DataFormats/XyzId"/> + <use name="DataFormats/XyzIdCudaAsync"/> + <use name="FWCore/Framework"/> + <use name="FWCore/ParameterSet"/> + <use name="FWCore/Utilities"/> + <use name="HeterogeneousCore/AlpakaCore" source_only="1"/> + <use name="HeterogeneousCore/AlpakaInterface" source_only="1"/> + <flags EDM_PLUGIN="1"/> +</library> diff --git a/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdAlgo.cu b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdAlgo.cu new file mode 100644 index 0000000000000..a4618c8d71139 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdAlgo.cu @@ -0,0 +1,2 @@ +#define ALPAKA_ACC_GPU_CUDA_ENABLED +#include "alpaka/XyzIdAlgo.dev.cc" diff --git a/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdCudaProducer.cc b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdCudaProducer.cc new file mode 100644 index 0000000000000..3467195dec554 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdCudaProducer.cc @@ -0,0 +1,3 @@ +#define ALPAKA_ACC_GPU_CUDA_ENABLED +#define ALPAKA_HOST_ONLY +#include "alpaka/XyzIdAlpakaProducer.cc" diff --git a/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdCudaTranscriber.cc b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdCudaTranscriber.cc new file mode 100644 index 0000000000000..2ed64289cf715 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/XyzIdCudaTranscriber.cc @@ -0,0 +1,3 @@ +#define ALPAKA_ACC_GPU_CUDA_ENABLED +#define ALPAKA_HOST_ONLY +#include "alpaka/XyzIdAlpakaTranscriber.cc" diff --git a/HeterogeneousCore/AlpakaTestCudaAsync/plugins/alpaka b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/alpaka new file mode 120000 index 0000000000000..9ec1e721cb8fe --- /dev/null +++ b/HeterogeneousCore/AlpakaTestCudaAsync/plugins/alpaka @@ -0,0 +1 @@ +../../AlpakaTest/plugins/alpaka \ No newline at end of file diff --git a/HeterogeneousCore/AlpakaTestSerialSync/README.md b/HeterogeneousCore/AlpakaTestSerialSync/README.md new file mode 100644 index 0000000000000..64acdcc267cf6 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestSerialSync/README.md @@ -0,0 +1,7 @@ +## HeterogeneousCore/AlpakaTestSerialSync + +This is a dummy package to emulate the expected behaviour of the build system. +The .../alpaka/ directories are symlinked from HeterogeneousCore/AlpakaTest +to avoid the scram error about the inclusion of private source files. +Its content should eventually be built from HeterogeneousCore/AlpakaTest for +the serial sync backend. diff --git a/HeterogeneousCore/AlpakaTestSerialSync/plugins/BuildFile.xml b/HeterogeneousCore/AlpakaTestSerialSync/plugins/BuildFile.xml new file mode 100644 index 0000000000000..67cf1ce54e721 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestSerialSync/plugins/BuildFile.xml @@ -0,0 +1,11 @@ +<library file="*.cc" name="HeterogeneousCoreAlpakaTestSerialSyncPlugins"> + <use name="alpaka-serial"/> + <use name="DataFormats/XyzId"/> + <use name="DataFormats/XyzIdSerialSync"/> + <use name="FWCore/Framework"/> + <use name="FWCore/ParameterSet"/> + <use name="FWCore/Utilities"/> + <use name="HeterogeneousCore/AlpakaCore" source_only="1"/> + <use name="HeterogeneousCore/AlpakaInterface" source_only="1"/> + <flags EDM_PLUGIN="1"/> +</library> diff --git a/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdAlgo.cc b/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdAlgo.cc new file mode 100644 index 0000000000000..e923455e18aa8 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdAlgo.cc @@ -0,0 +1,2 @@ +#define ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED +#include "alpaka/XyzIdAlgo.dev.cc" diff --git a/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdAnalyzer.cc b/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdAnalyzer.cc new file mode 100644 index 0000000000000..e8ead247dbca9 --- /dev/null +++ b/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdAnalyzer.cc @@ -0,0 +1,2 @@ +#define ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED +#include "alpaka/XyzIdAlpakaAnalyzer.cc" diff --git a/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdProducer.cc b/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdProducer.cc new file mode 100644 index 0000000000000..a5c73492c455c --- /dev/null +++ b/HeterogeneousCore/AlpakaTestSerialSync/plugins/XyzIdProducer.cc @@ -0,0 +1,2 @@ +#define ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED +#include "alpaka/XyzIdAlpakaProducer.cc" diff --git a/HeterogeneousCore/AlpakaTestSerialSync/plugins/alpaka b/HeterogeneousCore/AlpakaTestSerialSync/plugins/alpaka new file mode 120000 index 0000000000000..9ec1e721cb8fe --- /dev/null +++ b/HeterogeneousCore/AlpakaTestSerialSync/plugins/alpaka @@ -0,0 +1 @@ +../../AlpakaTest/plugins/alpaka \ No newline at end of file