Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////
2 : // Spetabaru - Berenger Bramas MPCDF - 2017
3 : // Under LGPL Licence, please you must read the LICENCE file.
4 : ///////////////////////////////////////////////////////////////////////////
5 : #ifndef SPUTILS_HPP
6 : #define SPUTILS_HPP
7 :
8 : #include <thread>
9 : #include <string>
10 : #include <sstream>
11 : #include <cstring>
12 : #include <functional>
13 : #include <memory>
14 :
15 : #ifndef _GNU_SOURCE
16 : #define _GNU_SOURCE
17 : #endif
18 : #include <sys/types.h>
19 : #include <unistd.h>
20 : #include <sys/syscall.h>
21 :
22 : #ifdef __APPLE__
23 : #include "MacOSX.hpp"
24 : #else
25 : #include <sched.h>
26 : #endif
27 :
28 : #include <cassert>
29 :
30 : #include "SpDebug.hpp"
31 : #include "small_vector.hpp"
32 :
33 : /**
34 : * Utils methods
35 : */
36 : namespace SpUtils{
37 : /** Return the default number of threads using hardware's capacity */
38 39 : inline int DefaultNumThreads(){
39 39 : if(getenv("OMP_NUM_THREADS")){
40 0 : std::istringstream iss(getenv("OMP_NUM_THREADS"),std::istringstream::in);
41 0 : int nbThreads = -1;
42 0 : iss >> nbThreads;
43 0 : if( /*iss.tellg()*/ iss.eof() ) return nbThreads;
44 : }
45 39 : return static_cast<int>(std::thread::hardware_concurrency());
46 : }
47 :
48 : inline bool DefaultToBind(const int inNumThreads){
49 : if(getenv("OMP_PROC_BIND")){
50 : return strcmp(getenv("OMP_PROC_BIND"), "TRUE") == 0
51 : || strcmp(getenv("OMP_PROC_BIND"), "true") == 0
52 : || strcmp(getenv("OMP_PROC_BIND"), "1") == 0;
53 : }
54 : return (inNumThreads <= static_cast<int>(std::thread::hardware_concurrency()));
55 : }
56 :
57 : inline void BindToCore(const int inCoreId){
58 : cpu_set_t mask;
59 : CPU_ZERO(&mask);
60 : CPU_SET(inCoreId, &mask);
61 :
62 : #ifdef __APPLE__
63 : [[maybe_unused]] int retValue = macosspecific::sched_setaffinity_np(pthread_self(), sizeof(mask), &mask);
64 : assert(retValue == 0);
65 : #else
66 : pid_t tid = static_cast<pid_t>(syscall(SYS_gettid));
67 : [[maybe_unused]] int retValue = sched_setaffinity(tid, sizeof(mask), &mask);
68 : assert(retValue == 0);
69 : #endif
70 :
71 : SpDebugPrint() << "Bind to " << inCoreId << " core";
72 : }
73 :
74 : /** Return the current binding (bit a position n is set to 1 when bind
75 : * to core n)
76 : */
77 : inline void GetBinding(cpu_set_t *mask){
78 : CPU_ZERO(mask);
79 :
80 : #ifdef __APPLE__
81 : [[maybe_unused]] int retValue = macosspecific::sched_getaffinity_np(pthread_self(), sizeof(*mask), mask);
82 : assert(retValue == 0);
83 : #else
84 : pid_t tid = static_cast<pid_t>(syscall(SYS_gettid));
85 : // Get the affinity
86 : [[maybe_unused]] int retValue = sched_getaffinity(tid, sizeof(*mask), mask);
87 : assert(retValue == 0);
88 : #endif
89 : }
90 :
91 : /** Return the current thread id */
92 : long int GetThreadId();
93 :
94 : /** Return true if the code is executed from a task */
95 4 : inline bool IsInTask(){
96 4 : return GetThreadId() != 0;
97 : }
98 :
99 : /** Set current thread Id */
100 : void SetThreadId(const long int inThreadId);
101 :
102 : /** Replace all substring in a string */
103 1797 : inline std::string ReplaceAllInString(std::string sentence, const std::string& itemToReplace, const std::string& inSubstitutionString){
104 2336 : for(std::string::size_type idxFound = sentence.find(itemToReplace); idxFound != std::string::npos; idxFound = sentence.find(itemToReplace)){
105 539 : sentence.replace(idxFound, itemToReplace.size(), inSubstitutionString);
106 : }
107 1797 : return sentence;
108 : }
109 :
110 : /** To perform some assert/check */
111 : inline void CheckCorrect(const char* test, const bool isCorrect, const int line, const char* file){
112 : if(!isCorrect){
113 : std::cout << "Error in file " << file << " line " << line << std::endl;
114 : std::cout << "Test was " << test << std::endl;
115 : exit(-1);
116 : }
117 : }
118 :
119 : template <typename CallableTy, typename TupleTy, std::size_t... Is,
120 : std::enable_if_t<sizeof...(Is) == 0 || std::conjunction_v<std::is_invocable<CallableTy, std::tuple_element_t<Is, std::remove_reference_t<TupleTy>>>...>, int> = 0>
121 1601 : static void foreach_in_tuple_impl(CallableTy &&c, TupleTy &&t, std::index_sequence<Is...>) {
122 : if constexpr(sizeof...(Is) > 0) {
123 : using RetTy = std::invoke_result_t<CallableTy, std::tuple_element_t<0, std::remove_reference_t<TupleTy>>>;
124 :
125 : if constexpr(std::is_same_v<RetTy, bool>) {
126 9 : (std::invoke(std::forward<CallableTy>(c), std::get<Is>(std::forward<TupleTy>(t))) || ...);
127 : } else {
128 1583 : (static_cast<void>(std::invoke(std::forward<CallableTy>(c), std::get<Is>(std::forward<TupleTy>(t)))),...);
129 : }
130 : }
131 1601 : }
132 :
133 : template <typename CallableTy, typename TupleTy, std::size_t... Is,
134 : std::enable_if_t<sizeof...(Is) != 0 && std::conjunction_v<std::is_invocable<CallableTy, std::integral_constant<size_t, Is>,
135 : std::tuple_element_t<Is, std::remove_reference_t<TupleTy>>>...>, int> = 0>
136 1070 : static void foreach_in_tuple_impl(CallableTy &&c, TupleTy &&t, std::index_sequence<Is...>) {
137 : if constexpr(sizeof...(Is) > 0) {
138 : using RetTy = std::invoke_result_t<CallableTy, std::integral_constant<size_t, 0>, std::tuple_element_t<0, std::remove_reference_t<TupleTy>>>;
139 :
140 : if constexpr(std::is_same_v<RetTy, bool>) {
141 : (std::invoke(std::forward<CallableTy>(c), std::integral_constant<size_t, Is>{}, std::get<Is>(std::forward<TupleTy>(t))) || ...);
142 : } else {
143 1070 : (static_cast<void>(std::invoke(std::forward<CallableTy>(c), std::integral_constant<size_t, Is>{}, std::get<Is>(std::forward<TupleTy>(t)))),...);
144 : }
145 : }
146 1070 : }
147 :
148 : template <typename CallableTy, typename TupleTy>
149 2671 : static void foreach_in_tuple(CallableTy &&c, TupleTy &&t) {
150 2671 : foreach_in_tuple_impl(std::forward<CallableTy>(c), std::forward<TupleTy>(t), std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<TupleTy>>>{});
151 2671 : }
152 : }
153 :
154 : #define spetabaru_xstr(s) spetabaru_str(s)
155 : #define spetabaru_str(s) #s
156 : #define always_assert(X) SpUtils::CheckCorrect(spetabaru_str(X), (X), __LINE__, __FILE__)
157 :
158 : #endif
|