26 #if defined(ALLOC_USE_PTHREADS) 30 #include <sys/syscall.h> 37 inline auto thread_id() {
38 #if defined(ALLOC_USE_PTHREADS) 44 return pthread_self();
46 return syscall(SYS_gettid);
50 struct ThreadTracker {
51 static constexpr unsigned int kHashedEntries = 128;
52 static constexpr unsigned int kExtraEntries = 128;
53 static constexpr unsigned int kTotalEntries = kHashedEntries + kExtraEntries;
54 using entry_type = decltype(thread_id());
55 static constexpr entry_type kUnusedEntry = ~entry_type(0);
56 std::array<std::atomic<entry_type>, kHashedEntries> hashed_threads_;
57 std::array<std::atomic<entry_type>, kExtraEntries> extra_threads_;
62 for (
auto&
v : hashed_threads_) {
66 for (
auto&
v : extra_threads_) {
71 std::size_t thread_index() {
72 auto id = thread_id();
73 auto index = thread_index_guess(
id);
74 auto used_id = hashed_threads_[
index].load();
80 auto expected = entry_type(
index + 1);
81 if (used_id == expected) {
82 if (hashed_threads_[
index].compare_exchange_strong(expected,
id)) {
86 return find_new_index(
id);
90 return find_index(
id);
94 std::size_t thread_index_guess(entry_type
id)
const {
95 #if defined(ALLOC_USE_PTHREADS) 96 return (
id / 0x700) % kHashedEntries;
98 return id % kHashedEntries;
102 std::size_t find_new_index(entry_type
id) {
103 std::size_t
index = 0;
104 for (
auto&
v : extra_threads_) {
105 entry_type expected = kUnusedEntry;
107 if (
v.compare_exchange_strong(expected,
id)) {
108 return index + kHashedEntries;
118 std::size_t find_index(entry_type
id) {
119 std::size_t
index = 0;
120 for (
auto const&
v : extra_threads_) {
122 return index + kHashedEntries;
126 return find_new_index(
id);
130 static ThreadTracker& getTracker() {
131 static ThreadTracker s_tracker;
138 static void startOnThread() { threadAllocInfo().reset(); }
140 auto&
t = threadAllocInfo();
152 return s_info[getTracker().thread_index()];
154 void allocCalled(
size_t iRequested,
size_t iActual,
void const*)
final {
155 auto& allocInfo = threadAllocInfo();
156 if (not allocInfo.active_) {
159 allocInfo.nAllocations_ += 1;
160 allocInfo.requested_ += iRequested;
162 if (allocInfo.maxSingleAlloc_ < iRequested) {
163 allocInfo.maxSingleAlloc_ = iRequested;
166 allocInfo.presentActual_ += iActual;
167 if (allocInfo.presentActual_ > static_cast<long long>(allocInfo.maxActual_)) {
168 allocInfo.maxActual_ = allocInfo.presentActual_;
171 void deallocCalled(
size_t iActual,
void const*)
final {
172 auto& allocInfo = threadAllocInfo();
173 if (not allocInfo.active_) {
177 allocInfo.nDeallocations_ += 1;
178 allocInfo.presentActual_ -= iActual;
179 if (allocInfo.presentActual_ < 0) {
180 if (allocInfo.minActual_ == 0
or allocInfo.minActual_ > allocInfo.presentActual_) {
181 allocInfo.minActual_ = allocInfo.presentActual_;
197 MonitorAdaptor::startOnThread();
209 return &MonitorAdaptor::stopOnThread();
218 MonitorAdaptor::startOnThread();
226 return &MonitorAdaptor::stopOnThread();
244 nEventsToSkip_(iPS.getUntrackedParameter<unsigned
int>(
"nEventsToSkip")),
245 filter_(&moduleIDs_) {
248 if (nEventsToSkip_ > 0) {
249 filter_.setGlobalKeep(
false);
251 if (not moduleNames_.empty()) {
254 if (
found != moduleNames_.end()) {
256 std::sort(moduleIDs_.begin(), moduleIDs_.end());
261 auto label = iDescription.label_;
263 label = iDescription.type_;
266 if (
found != moduleNames_.end()) {
268 moduleIDs_.push_back(-1 * (iDescription.id_ + 1));
269 std::sort(moduleIDs_.begin(), moduleIDs_.end());
273 if (nEventsToSkip_ > 0) {
276 if (nEventsStarted_ > nEventsToSkip_) {
277 filter_.setGlobalKeep(
true);
287 ps.
addUntracked<std::vector<std::string>>(
"moduleNames", std::vector<std::string>());
298 unsigned int nEventsToSkip_ = 0;
299 std::atomic<unsigned int> nEventsStarted_{0};
void watchPostESModuleRegistration(PostESModuleRegistration::slot_type const &iSlot)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void watchPreModuleConstruction(PreModuleConstruction::slot_type const &iSlot)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
const ThreadAllocInfo * stopOnThread() const
bool startOnThread() const
TEMPL(T2) struct Divides void
std::atomic< bool > globalKeep_
T getUntrackedParameter(std::string const &, T const &) const
bool forThisModule(unsigned int iID)
Filter(std::vector< int > const *moduleIDs)
ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE int binary_search(const unsigned int *data, unsigned int search_val, unsigned int ndata)
void setupFile(std::string const &iFileName, edm::ActivityRegistry &iRegistry, Filter const *iFilter)
void addDefault(ParameterSetDescription const &psetDescription)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
edm::service::moduleAlloc::Filter filter_
std::vector< int > moduleIDs_
bool keepModuleInfo(int moduleID) const
std::vector< std::string > moduleNames_
void setGlobalKeep(bool iShouldKeep)
#define DEFINE_FWK_SERVICE(type)
std::vector< int > const * moduleIDs_
void watchPreSourceEvent(PreSourceEvent::slot_type const &iSlot)
ModuleAllocMonitor(edm::ParameterSet const &iPS, edm::ActivityRegistry &iAR)
static void fillDescriptions(edm::ConfigurationDescriptions &iDesc)