Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/corecel/sys/KernelRegistry.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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/KernelRegistry.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <atomic>
0010 #include <cstdint>
0011 #include <iosfwd>  // IWYU pragma: keep
0012 #include <memory>
0013 #include <mutex>
0014 #include <string>
0015 #include <string_view>
0016 #include <vector>
0017 
0018 #include "corecel/Assert.hh"
0019 #include "corecel/OpaqueId.hh"
0020 
0021 #include "KernelAttributes.hh"
0022 
0023 namespace celeritas
0024 {
0025 //---------------------------------------------------------------------------//
0026 struct KernelProfiling
0027 {
0028     using value_type = std::uint_least64_t;
0029 
0030     //!< Number of times launched
0031     std::atomic<value_type> num_launches{0};
0032     //!< Number of threads integrated over all launches
0033     std::atomic<value_type> accum_threads{0};
0034 
0035     // Increment atomic counters given the number of threads
0036     inline void log_launch(value_type num_threads);
0037 };
0038 
0039 //---------------------------------------------------------------------------//
0040 struct KernelMetadata
0041 {
0042     std::string name;
0043     KernelAttributes attributes;
0044     KernelProfiling profiling;
0045 };
0046 
0047 //! Ordered identifiers for registered kernels
0048 using KernelId = OpaqueId<KernelMetadata>;
0049 
0050 //---------------------------------------------------------------------------//
0051 /*!
0052  * Keep track of kernels and launches.
0053  *
0054  * Every "insert" creates a unique \c KernelMetadata entry in a thread-safe
0055  * fashion (in case multiple threads are launching kernels for the first time).
0056  * Thus every kernel added to the registry needs a \c static local data (i.e.,
0057  * \c KernelParamCalculator) to track whether the kernel has been added and to
0058  * keep a reference to the returned profiling data counter. Kernels are always
0059  * added sequentially and can never be removed from the registry once added.
0060  * Kernels that share the same name will create independent entries!
0061  *
0062  * This class has a thread-safe methods because it's meant to be shared
0063  * across multiple threads when running. Generally \c insert is the only method
0064  * expected to have contention across threads.
0065  */
0066 class KernelRegistry
0067 {
0068   public:
0069     // Whether profiling metrics (launch count, max threads) are collected
0070     static bool profiling();
0071 
0072     // Construct without any data
0073     KernelRegistry() = default;
0074 
0075     //// CONSTRUCTION ////
0076 
0077     // Register a kernel and return optional reference to profiling info
0078     KernelProfiling* insert(std::string_view name, KernelAttributes&& attrs);
0079 
0080     //// ACCESSORS ////
0081 
0082     //! \todo rename to size
0083     // Number of kernel diagnostics available
0084     KernelId::size_type num_kernels() const;
0085 
0086     //! \todo rename to get
0087     // Access kernel data for a single kernel
0088     KernelMetadata const& kernel(KernelId id) const;
0089 
0090   private:
0091     using UPKM = std::unique_ptr<KernelMetadata>;
0092 
0093     mutable std::mutex kernels_mutex_;
0094     std::vector<UPKM> kernels_;
0095 };
0096 
0097 //---------------------------------------------------------------------------//
0098 // FREE FUNCTIONS
0099 //---------------------------------------------------------------------------//
0100 // Globally shared registry of kernels for end-of-program diagnostics
0101 KernelRegistry& kernel_registry();
0102 
0103 // Write kernel statistics to a stream
0104 std::ostream& operator<<(std::ostream& os, KernelMetadata const& md);
0105 
0106 //---------------------------------------------------------------------------//
0107 // INLINE DEFINITIONS
0108 //---------------------------------------------------------------------------//
0109 /*!
0110  * Accumulate counters for a kernel launch.
0111  */
0112 void KernelProfiling::log_launch(value_type num_threads)
0113 {
0114     CELER_EXPECT(num_threads > 0);
0115 
0116     // Increment launches by 1 and thread count by num_threads.
0117     // We don't care in what order these values are written.
0118     this->num_launches.fetch_add(1, std::memory_order_relaxed);
0119     this->accum_threads.fetch_add(num_threads, std::memory_order_relaxed);
0120 }
0121 
0122 //---------------------------------------------------------------------------//
0123 }  // namespace celeritas