BioDynaMo  v1.05.120-25dc9790
thread_info.h
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2021 CERN & University of Surrey for the benefit of the
4 // BioDynaMo collaboration. All Rights Reserved.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // See the LICENSE file distributed with this work for details.
10 // See the NOTICE file distributed with this work for additional information
11 // regarding copyright ownership.
12 //
13 // -----------------------------------------------------------------------------
14 
15 #ifndef CORE_UTIL_THREAD_INFO_H_
16 #define CORE_UTIL_THREAD_INFO_H_
17 
18 #include <omp.h>
19 #include <sched.h>
20 #include <atomic>
21 #include <vector>
22 
23 #include "core/util/log.h"
24 #include "core/util/numa.h"
25 
26 namespace bdm {
27 
31 class ThreadInfo {
32  public:
33  static ThreadInfo* GetInstance();
34 
35  ThreadInfo(const ThreadInfo&) = delete;
36  ThreadInfo& operator=(const ThreadInfo&) = delete;
37 
38  // FIXME add test
39  int GetMyThreadId() const { return omp_get_thread_num(); }
40 
41  // FIXME add test
42  int GetMyNumaNode() const { return GetNumaNode(GetMyThreadId()); }
43 
45  int GetMyNumaThreadId() const { return GetNumaThreadId(GetMyThreadId()); }
46 
48  int GetNumaNodes() const { return numa_nodes_; }
49 
51  int GetNumaNode(int omp_thread_id) const {
52  return thread_numa_mapping_[omp_thread_id];
53  }
54 
56  int GetThreadsInNumaNode(int numa_node) const {
57  return threads_in_numa_[numa_node];
58  }
59 
61  int GetNumaThreadId(int omp_thread_id) const {
62  return numa_thread_id_[omp_thread_id];
63  }
64 
66  int GetMaxThreads() const { return max_threads_; }
67 
70  uint64_t GetUniversalThreadId() const;
71 
72  uint64_t GetMaxUniversalThreadId() const { return thread_counter_; }
73 
78  void Renew() {
79  max_threads_ = omp_get_max_threads();
80  numa_nodes_ = static_cast<uint16_t>(numa_num_configured_nodes());
81 
82  thread_numa_mapping_.clear();
83  numa_thread_id_.clear();
84  threads_in_numa_.clear();
85 
87  numa_thread_id_.resize(max_threads_, 0);
88  threads_in_numa_.resize(numa_nodes_, 0);
89 
90 // (openmp thread id -> numa node)
91 #pragma omp parallel
92  {
93  int tid = omp_get_thread_num();
95  }
96 
97  // (numa -> number of associated threads), and
98  // (omp_thread_id -> thread id in numa)
99  for (uint16_t n = 0; n < numa_nodes_; n++) {
100  int cnt = 0;
101  for (int t = 0; t < max_threads_; t++) {
102  int numa = thread_numa_mapping_[t];
103  if (n == numa) {
104  numa_thread_id_[t] = cnt;
105  cnt++;
106  }
107  }
108  threads_in_numa_[n] = cnt;
109  }
110  }
111 
112  friend std::ostream& operator<<(std::ostream& str, const ThreadInfo& ti) {
113  str << "max_threads\t\t: " << ti.max_threads_
114  << "\nnum_numa nodes\t\t: " << ti.numa_nodes_;
115 
116  str << "\nthread to numa mapping\t: ";
117  for (auto& el : ti.thread_numa_mapping_) {
118  str << el << " ";
119  }
120 
121  str << "\nthread id in numa node\t: ";
122  for (auto& el : ti.numa_thread_id_) {
123  str << el << " ";
124  }
125 
126  str << "\nnum threads per numa\t: ";
127  for (auto& el : ti.threads_in_numa_) {
128  str << el << " ";
129  }
130  str << "\n";
131  return str;
132  }
133 
134  private:
135  static std::atomic<uint64_t> thread_counter_;
136 
140  uint16_t numa_nodes_;
141 
145  std::vector<int> thread_numa_mapping_;
146 
150  std::vector<int> numa_thread_id_;
151 
156  std::vector<int> threads_in_numa_;
157 
159  auto proc_bind = omp_get_proc_bind();
160  if (proc_bind != 1 && proc_bind != 4) {
161  // 4 corresponds to OMP_PROC_BIND=spread
162  // Due to some reason some OpenMP implementations set proc bind to spread
163  // even though OMP_PROC_BIND is set to true.
164  // A performance analysis showed almost identical results between true,
165  // and spread.
166  Log::Warning(
167  "ThreadInfo::ThreadInfo",
168  "The environment variable OMP_PROC_BIND must be set to "
169  "true prior to running BioDynaMo ('export OMP_PROC_BIND=true')");
170  }
171  Renew();
172  }
173 };
174 
175 } // namespace bdm
176 
177 #endif // CORE_UTIL_THREAD_INFO_H_
numa_node_of_cpu
int numa_node_of_cpu(int)
Definition: numa.h:30
bdm::ThreadInfo::ThreadInfo
ThreadInfo()
Definition: thread_info.h:158
bdm::ThreadInfo::GetInstance
static ThreadInfo * GetInstance()
Definition: thread_info.cc:21
bdm
Definition: agent.cc:39
bdm::ThreadInfo::GetNumaNodes
int GetNumaNodes() const
Returns the number of NUMA nodes on this machine.
Definition: thread_info.h:48
bdm::ThreadInfo::thread_counter_
static std::atomic< uint64_t > thread_counter_
Definition: thread_info.h:135
bdm::ThreadInfo::GetMyNumaThreadId
int GetMyNumaThreadId() const
Return the numa thread id of an openmp thread.
Definition: thread_info.h:45
bdm::ThreadInfo::thread_numa_mapping_
std::vector< int > thread_numa_mapping_
Definition: thread_info.h:145
bdm::ThreadInfo::GetNumaThreadId
int GetNumaThreadId(int omp_thread_id) const
Return the numa thread id of an openmp thread.
Definition: thread_info.h:61
bdm::Log::Warning
static void Warning(const std::string &location, const Args &... parts)
Prints warning message.
Definition: log.h:67
sched_getcpu
int sched_getcpu()
Definition: numa.h:40
bdm::ThreadInfo::GetMyNumaNode
int GetMyNumaNode() const
Definition: thread_info.h:42
bdm::ThreadInfo::numa_nodes_
uint16_t numa_nodes_
Number of NUMA nodes on this machine.
Definition: thread_info.h:140
numa.h
numa_num_configured_nodes
int numa_num_configured_nodes()
Definition: numa.h:27
bdm::ThreadInfo::operator=
ThreadInfo & operator=(const ThreadInfo &)=delete
log.h
bdm::ThreadInfo::Renew
void Renew()
Definition: thread_info.h:78
bdm::ThreadInfo::threads_in_numa_
std::vector< int > threads_in_numa_
Definition: thread_info.h:156
bdm::ThreadInfo::numa_thread_id_
std::vector< int > numa_thread_id_
Definition: thread_info.h:150
bdm::ThreadInfo::GetMaxThreads
int GetMaxThreads() const
Return the maximum number of threads.
Definition: thread_info.h:66
bdm::ThreadInfo::GetMaxUniversalThreadId
uint64_t GetMaxUniversalThreadId() const
Definition: thread_info.h:72
bdm::ThreadInfo::max_threads_
int max_threads_
Maximum number of threads for this simulation.
Definition: thread_info.h:138
bdm::ThreadInfo::operator<<
friend std::ostream & operator<<(std::ostream &str, const ThreadInfo &ti)
Definition: thread_info.h:112
bdm::ThreadInfo::GetMyThreadId
int GetMyThreadId() const
Definition: thread_info.h:39
bdm::ThreadInfo::GetUniversalThreadId
uint64_t GetUniversalThreadId() const
Definition: thread_info.cc:26
bdm::ThreadInfo
This class stores information about each thread. (e.g. to which NUMA node it belongs to....
Definition: thread_info.h:31
bdm::ThreadInfo::GetNumaNode
int GetNumaNode(int omp_thread_id) const
Returns the numa node the given openmp thread is bound to.
Definition: thread_info.h:51
bdm::ThreadInfo::GetThreadsInNumaNode
int GetThreadsInNumaNode(int numa_node) const
Returns the number of threads in a given NUMA node.
Definition: thread_info.h:56