Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-08-15 01:07:42

0001 #ifndef HeterogeneousCore_AlpakaCore_interface_EventCache_h
0002 #define HeterogeneousCore_AlpakaCore_interface_EventCache_h
0003 
0004 #include <memory>
0005 #include <utility>
0006 #include <vector>
0007 
0008 #include <alpaka/alpaka.hpp>
0009 
0010 #include "FWCore/Utilities/interface/ReusableObjectHolder.h"
0011 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0013 #include "HeterogeneousCore/AlpakaInterface/interface/AlpakaServiceFwd.h"
0014 
0015 namespace cms::alpakatools {
0016 
0017   template <typename Event>
0018   class EventCache {
0019   public:
0020 #ifdef ALPAKA_ACC_GPU_CUDA_ENABLED
0021     friend class alpaka_cuda_async::AlpakaService;
0022 #endif
0023 #ifdef ALPAKA_ACC_GPU_HIP_ENABLED
0024     friend class alpaka_hip_async::AlpakaService;
0025 #endif
0026 #ifdef ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED
0027     friend class alpaka_serial_sync::AlpakaService;
0028 #endif
0029 #ifdef ALPAKA_ACC_CPU_B_TBB_T_SEQ_ENABLED
0030     friend class alpaka_tbb_async::AlpakaService;
0031 #endif
0032 
0033     using Device = alpaka::Dev<Event>;
0034     using Platform = alpaka::Pltf<Device>;
0035 
0036     // EventCache should be constructed by the first call to
0037     // getEventCache() only if we have any devices present
0038     EventCache() : cache_(alpaka::getDevCount<Platform>()) {}
0039 
0040     // Gets a (cached) event for the current device. The event
0041     // will be returned to the cache by the shared_ptr destructor. The
0042     // returned event is guaranteed to be in the state where all
0043     // captured work has completed.
0044     //
0045     // This function is thread safe
0046     std::shared_ptr<Event> get(Device dev) {
0047       auto event = makeOrGet(dev);
0048       // captured work has completed, or a just-created event
0049       if (alpaka::isComplete(*event)) {
0050         return event;
0051       }
0052 
0053       // Got an event with incomplete captured work. Try again until we
0054       // get a completed (or a just-created) event. Need to keep all
0055       // incomplete events until a completed event is found in order to
0056       // avoid ping-pong with an incomplete event.
0057       std::vector<std::shared_ptr<Event>> ptrs{std::move(event)};
0058       bool completed;
0059       do {
0060         event = makeOrGet(dev);
0061         completed = alpaka::isComplete(*event);
0062         if (not completed) {
0063           ptrs.emplace_back(std::move(event));
0064         }
0065       } while (not completed);
0066       return event;
0067     }
0068 
0069   private:
0070     std::shared_ptr<Event> makeOrGet(Device dev) {
0071       return cache_[alpaka::getNativeHandle(dev)].makeOrGet([dev]() { return std::make_unique<Event>(dev); });
0072     }
0073 
0074     // not thread safe, intended to be called only from AlpakaService
0075     void clear() {
0076       // Reset the contents of the caches, but leave an
0077       // edm::ReusableObjectHolder alive for each device. This is needed
0078       // mostly for the unit tests, where the function-static
0079       // EventCache lives through multiple tests (and go through
0080       // multiple shutdowns of the framework).
0081       cache_.clear();
0082       cache_.resize(alpaka::getDevCount<Platform>());
0083     }
0084 
0085     std::vector<edm::ReusableObjectHolder<Event>> cache_;
0086   };
0087 
0088   // Gets the global instance of a EventCache
0089   // This function is thread safe
0090   template <typename Event>
0091   EventCache<Event>& getEventCache() {
0092     // the public interface is thread safe
0093     CMS_THREAD_SAFE static EventCache<Event> cache;
0094     return cache;
0095   }
0096 
0097 }  // namespace cms::alpakatools
0098 
0099 #endif  // HeterogeneousCore_AlpakaCore_interface_EventCache_h