Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-26 09:34:38

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/sys/DeviceEvent.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <memory>
0010 
0011 #include "corecel/Assert.hh"  // IWYU pragma: keep
0012 #include "corecel/Macros.hh"
0013 #include "corecel/sys/ThreadId.hh"
0014 
0015 #if CELER_DEVICE_SOURCE
0016 #    include "corecel/DeviceRuntimeApi.hh"
0017 #endif
0018 
0019 namespace celeritas
0020 {
0021 //---------------------------------------------------------------------------//
0022 class Device;
0023 class Stream;
0024 
0025 //---------------------------------------------------------------------------//
0026 /*!
0027  * Minimal wrapper around a CUDA/HIP event for synchronization.
0028  *
0029  * Events provide a mechanism for querying the status of asynchronous
0030  * operations on GPU streams and synchronizing between host and device, and
0031  * synchronizing between streams.
0032  *
0033  * \par States
0034  * - \b Constructed: when built with an active device, the instance
0035  *   evaluates to \c true and manages an event object.
0036  * - \b Null: when constructed with a nullptr, or when \c moved from, the class
0037  *   instance is \c false. It does not manage an event.
0038  *   The \c sync function is a null-op (the event is always
0039  *   \c ready ), and \c record cannot be called.
0040  *
0041  * If no device is enabled (or Celeritas is compiled without CUDA/HIP support),
0042  * only the null state is available.
0043  *
0044  * \par Example
0045  * \code
0046   // Setup:
0047   DeviceEvent my_kernel(celeritas::device());
0048   assert(my_kernel.ready());
0049   // Later...
0050   launch_kernel_async(state.stream());
0051   my_kernel.record(state.stream());
0052   // Then do CPU work until the kernel or CPU is done
0053   while (!cpu_work_done() && !my_kernel.ready())
0054   {
0055       cpu_work();
0056   }
0057  * \endcode
0058  * Use \c my_kernel.sync() before the kernel launch to wait on the previous
0059  * kernel launch before going again.
0060  */
0061 class DeviceEvent
0062 {
0063   public:
0064 #if !CELER_USE_DEVICE
0065     //! Event implementation is unavailable
0066     using EventT = std::nullptr_t;
0067 #elif !defined(CELER_DEVICE_RUNTIME_INCLUDED)
0068     //! Sentinel type to indicate compilation error: include runtime downstream
0069     using MissingDeviceRuntime = void;
0070 #else
0071     //! Actual CUDA/HIP stream opaque pointer
0072     using EventT = CELER_DEVICE_API_SYMBOL(Event_t);
0073 #endif
0074 
0075   public:
0076     // Construct with a device context
0077     explicit DeviceEvent(Device const& d);
0078     // Construct a null event
0079     DeviceEvent(std::nullptr_t);
0080     CELER_DEFAULT_MOVE_DELETE_COPY(DeviceEvent);
0081     ~DeviceEvent() = default;
0082 
0083     // Whether the event is valid (not null or moved-from)
0084     inline explicit operator bool() const;
0085 
0086 #if defined(CELER_DEVICE_RUNTIME_INCLUDED) || !CELER_USE_DEVICE
0087     EventT get() const;
0088 #else
0089     MissingDeviceRuntime get() const {}
0090 #endif
0091 
0092     // Record this event on the stream
0093     void record(Stream const& s);
0094 
0095     // Query event status
0096     bool ready() const;
0097 
0098     // Block the host until the recorded event is complete
0099     void sync() const;
0100 
0101   private:
0102     struct Impl;
0103     struct ImplDeleter
0104     {
0105         void operator()(Impl*) noexcept;
0106     };
0107 
0108     std::unique_ptr<Impl, ImplDeleter> impl_{};
0109 };
0110 
0111 //---------------------------------------------------------------------------//
0112 /*!
0113  * Whether the event is valid (not null or moved-from).
0114  */
0115 DeviceEvent::operator bool() const
0116 {
0117     return static_cast<bool>(impl_);
0118 }
0119 
0120 //---------------------------------------------------------------------------//
0121 }  // namespace celeritas