Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:52:49

0001 #ifndef CUDADataFormats_Common_ProductBase_h
0002 #define CUDADataFormats_Common_ProductBase_h
0003 
0004 #include <atomic>
0005 #include <memory>
0006 
0007 #include "HeterogeneousCore/CUDAUtilities/interface/SharedStreamPtr.h"
0008 #include "HeterogeneousCore/CUDAUtilities/interface/SharedEventPtr.h"
0009 
0010 namespace cms {
0011   namespace cuda {
0012     namespace impl {
0013       class ScopedContextBase;
0014     }
0015 
0016     /**
0017      * Base class for all instantiations of CUDA<T> to hold the
0018      * non-T-dependent members.
0019      */
0020     class ProductBase {
0021     public:
0022       ProductBase() = default;  // Needed only for ROOT dictionary generation
0023       ~ProductBase();
0024 
0025       ProductBase(const ProductBase&) = delete;
0026       ProductBase& operator=(const ProductBase&) = delete;
0027       ProductBase(ProductBase&& other)
0028           : stream_{std::move(other.stream_)},
0029             event_{std::move(other.event_)},
0030             mayReuseStream_{other.mayReuseStream_.load()},
0031             device_{other.device_} {}
0032       ProductBase& operator=(ProductBase&& other) {
0033         stream_ = std::move(other.stream_);
0034         event_ = std::move(other.event_);
0035         mayReuseStream_ = other.mayReuseStream_.load();
0036         device_ = other.device_;
0037         return *this;
0038       }
0039 
0040       bool isValid() const { return stream_.get() != nullptr; }
0041       bool isAvailable() const;
0042 
0043       int device() const { return device_; }
0044 
0045       // cudaStream_t is a pointer to a thread-safe object, for which a
0046       // mutable access is needed even if the cms::cuda::ScopedContext itself
0047       // would be const. Therefore it is ok to return a non-const
0048       // pointer from a const method here.
0049       cudaStream_t stream() const { return stream_.get(); }
0050 
0051       // cudaEvent_t is a pointer to a thread-safe object, for which a
0052       // mutable access is needed even if the cms::cuda::ScopedContext itself
0053       // would be const. Therefore it is ok to return a non-const
0054       // pointer from a const method here.
0055       cudaEvent_t event() const { return event_.get(); }
0056 
0057     protected:
0058       explicit ProductBase(int device, SharedStreamPtr stream, SharedEventPtr event)
0059           : stream_{std::move(stream)}, event_{std::move(event)}, device_{device} {}
0060 
0061     private:
0062       friend class impl::ScopedContextBase;
0063       friend class ScopedContextProduce;
0064 
0065       // The following function is intended to be used only from ScopedContext
0066       const SharedStreamPtr& streamPtr() const { return stream_; }
0067 
0068       bool mayReuseStream() const {
0069         bool expected = true;
0070         bool changed = mayReuseStream_.compare_exchange_strong(expected, false);
0071         // If the current thread is the one flipping the flag, it may
0072         // reuse the stream.
0073         return changed;
0074       }
0075 
0076       // The cudaStream_t is really shared among edm::Event products, so
0077       // using shared_ptr also here
0078       SharedStreamPtr stream_;  //!
0079       // shared_ptr because of caching in cms::cuda::EventCache
0080       SharedEventPtr event_;  //!
0081 
0082       // This flag tells whether the CUDA stream may be reused by a
0083       // consumer or not. The goal is to have a "chain" of modules to
0084       // queue their work to the same stream.
0085       mutable std::atomic<bool> mayReuseStream_ = true;  //!
0086 
0087       // The CUDA device associated with this product
0088       int device_ = -1;  //!
0089     };
0090   }  // namespace cuda
0091 }  // namespace cms
0092 
0093 #endif