Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-19 04:04:41

0001 #include <optional>
0002 #include <type_traits>
0003 
0004 #include <alpaka/alpaka.hpp>
0005 
0006 #define CATCH_CONFIG_MAIN
0007 #include <catch.hpp>
0008 
0009 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0010 #include "HeterogeneousCore/AlpakaInterface/interface/CopyToDevice.h"
0011 #include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/moveToDeviceAsync.h"
0013 #include "HeterogeneousCore/AlpakaInterface/interface/workdivision.h"
0014 
0015 // each test binary is built for a single Alpaka backend
0016 using namespace ALPAKA_ACCELERATOR_NAMESPACE;
0017 
0018 namespace {
0019   template <typename T>
0020   class TestHostBuffer {
0021   public:
0022     using Buffer = cms::alpakatools::host_buffer<T[]>;
0023     using ConstBuffer = cms::alpakatools::const_host_buffer<T[]>;
0024 
0025     template <typename TQueue>
0026     TestHostBuffer(TQueue const& queue, int size) : buffer_(cms::alpakatools::make_host_buffer<T[]>(queue, size)) {}
0027 
0028     TestHostBuffer(TestHostBuffer const&) = delete;
0029     TestHostBuffer& operator=(TestHostBuffer const&) = delete;
0030     ;
0031     TestHostBuffer(TestHostBuffer&& other) {
0032       buffer_ = std::move(*other.buffer_);
0033       other.buffer_.reset();
0034     }
0035     TestHostBuffer& operator=(TestHostBuffer& other) {
0036       buffer_ = std::move(*other.buffer_);
0037       other.buffer_.reset();
0038       return this;
0039     }
0040 
0041     bool has_value() const { return buffer_.has_value(); }
0042 
0043     T* data() { return buffer_->data(); }
0044 
0045     Buffer buffer() { return *buffer_; }
0046     ConstBuffer buffer() const { return *buffer_; }
0047 
0048   private:
0049     std::optional<Buffer> buffer_;
0050   };
0051 
0052   template <typename T, typename TDev>
0053   class TestDeviceBuffer {
0054   public:
0055     using Buffer = cms::alpakatools::device_buffer<TDev, T[]>;
0056 
0057     template <typename TQueue>
0058     TestDeviceBuffer(TQueue const& queue, int size) : buffer_(cms::alpakatools::make_device_buffer<T[]>(queue, size)) {}
0059 
0060     T* data() { return buffer_.data(); }
0061 
0062     Buffer buffer() { return buffer_; }
0063 
0064   private:
0065     Buffer buffer_;
0066   };
0067 
0068   template <typename T>
0069   void fillBuffer(TestHostBuffer<T>& buffer) {
0070     for (int i = 0, size = alpaka::getExtentProduct(buffer.buffer()); i < size; ++i) {
0071       buffer.data()[i] = i;
0072     }
0073   }
0074 }  // namespace
0075 
0076 namespace cms::alpakatools {
0077   template <typename T>
0078   struct CopyToDevice<TestHostBuffer<T>> {
0079     template <typename TQueue>
0080     static auto copyAsync(TQueue& queue, TestHostBuffer<T> const& hostBuffer) {
0081       TestDeviceBuffer<T, alpaka::Dev<TQueue>> deviceBuffer(queue, alpaka::getExtentProduct(hostBuffer.buffer()));
0082       alpaka::memcpy(queue, deviceBuffer.buffer(), hostBuffer.buffer());
0083       return deviceBuffer;
0084     }
0085   };
0086 }  // namespace cms::alpakatools
0087 
0088 TEST_CASE("Test moveToDeviceAsync() for the " EDM_STRINGIZE(ALPAKA_ACCELERATOR_NAMESPACE) " backend",
0089           "[" EDM_STRINGIZE(ALPAKA_ACCELERATOR_NAMESPACE) "]") {
0090   // run the test on each device
0091   for (auto const& device : cms::alpakatools::devices<Platform>()) {
0092     auto queue = Queue(device);
0093     constexpr int size = 32;
0094     TestHostBuffer<int> buffer_host(queue, size);
0095     fillBuffer(buffer_host);
0096     auto const* ptr_host = buffer_host.data();
0097 
0098     auto buffer_device = cms::alpakatools::moveToDeviceAsync(queue, std::move(buffer_host));
0099     REQUIRE(not buffer_host.has_value());
0100     if constexpr (std::is_same_v<Device, alpaka_common::DevHost>) {
0101       REQUIRE(buffer_device.data() == ptr_host);
0102     } else {
0103       REQUIRE(buffer_device.data() != ptr_host);
0104     }
0105     alpaka::exec<Acc1D>(
0106         queue,
0107         cms::alpakatools::make_workdiv<Acc1D>(1, size),
0108         [] ALPAKA_FN_ACC(Acc1D const& acc, int const* data) {
0109           for (int i : cms::alpakatools::uniform_elements(acc)) {
0110             assert(data[i] == i);
0111           }
0112         },
0113         buffer_device.data());
0114     alpaka::wait(queue);
0115 
0116     /* the following should not compile
0117     auto buffer2_host = cms::alpakatools::make_host_buffer<int>();
0118     auto buffer2_device = cms::alpakatools::moveToDeviceAsync(queue, std::move(buffer2_host));
0119     */
0120   }
0121 }