1*d86ed7fbStbbdev /* 2*d86ed7fbStbbdev Copyright (c) 2005-2020 Intel Corporation 3*d86ed7fbStbbdev 4*d86ed7fbStbbdev Licensed under the Apache License, Version 2.0 (the "License"); 5*d86ed7fbStbbdev you may not use this file except in compliance with the License. 6*d86ed7fbStbbdev You may obtain a copy of the License at 7*d86ed7fbStbbdev 8*d86ed7fbStbbdev http://www.apache.org/licenses/LICENSE-2.0 9*d86ed7fbStbbdev 10*d86ed7fbStbbdev Unless required by applicable law or agreed to in writing, software 11*d86ed7fbStbbdev distributed under the License is distributed on an "AS IS" BASIS, 12*d86ed7fbStbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d86ed7fbStbbdev See the License for the specific language governing permissions and 14*d86ed7fbStbbdev limitations under the License. 15*d86ed7fbStbbdev */ 16*d86ed7fbStbbdev 17*d86ed7fbStbbdev #include <cstring> 18*d86ed7fbStbbdev #include <cctype> 19*d86ed7fbStbbdev #include <cstdlib> 20*d86ed7fbStbbdev #include <cstdio> 21*d86ed7fbStbbdev 22*d86ed7fbStbbdev #include <string> 23*d86ed7fbStbbdev 24*d86ed7fbStbbdev // Apple clang and MSVC defines their own specializations for std::hash<std::basic_string<T, Traits, Alloc>> 25*d86ed7fbStbbdev #if !(_LIBCPP_VERSION) && !(_CPPLIB_VER) 26*d86ed7fbStbbdev 27*d86ed7fbStbbdev namespace std { 28*d86ed7fbStbbdev 29*d86ed7fbStbbdev template <typename CharT, typename Traits, typename Allocator> 30*d86ed7fbStbbdev class hash<std::basic_string<CharT, Traits, Allocator>> { 31*d86ed7fbStbbdev public: 32*d86ed7fbStbbdev std::size_t operator()(const std::basic_string<CharT, Traits, Allocator>& s) const { 33*d86ed7fbStbbdev std::size_t h = 0; 34*d86ed7fbStbbdev for (const CharT* c = s.c_str(); *c; ++c) { 35*d86ed7fbStbbdev h = h * hash_multiplier ^ char_hash(*c); 36*d86ed7fbStbbdev } 37*d86ed7fbStbbdev return h; 38*d86ed7fbStbbdev } 39*d86ed7fbStbbdev 40*d86ed7fbStbbdev private: 41*d86ed7fbStbbdev static constexpr std::size_t hash_multiplier = (std::size_t)( 42*d86ed7fbStbbdev (sizeof(std::size_t) == sizeof(unsigned)) ? 2654435769U : 11400714819323198485ULL); 43*d86ed7fbStbbdev 44*d86ed7fbStbbdev std::hash<CharT> char_hash; 45*d86ed7fbStbbdev }; // strunt hash<std::basic_string> 46*d86ed7fbStbbdev 47*d86ed7fbStbbdev } // namespace std 48*d86ed7fbStbbdev 49*d86ed7fbStbbdev #endif // !(_LIBCPP_VERSION || _CPPLIB_VER) 50*d86ed7fbStbbdev 51*d86ed7fbStbbdev #include "oneapi/tbb/concurrent_hash_map.h" 52*d86ed7fbStbbdev #include "oneapi/tbb/blocked_range.h" 53*d86ed7fbStbbdev #include "oneapi/tbb/parallel_for.h" 54*d86ed7fbStbbdev #include "oneapi/tbb/tick_count.h" 55*d86ed7fbStbbdev #include "oneapi/tbb/tbb_allocator.h" 56*d86ed7fbStbbdev #include "oneapi/tbb/global_control.h" 57*d86ed7fbStbbdev 58*d86ed7fbStbbdev #include "common/utility/utility.hpp" 59*d86ed7fbStbbdev #include "common/utility/get_default_num_threads.hpp" 60*d86ed7fbStbbdev 61*d86ed7fbStbbdev #include <map> 62*d86ed7fbStbbdev 63*d86ed7fbStbbdev //! Count collisions 64*d86ed7fbStbbdev std::map<std::size_t, int> hashes; 65*d86ed7fbStbbdev int c = 0; 66*d86ed7fbStbbdev 67*d86ed7fbStbbdev //! String type 68*d86ed7fbStbbdev typedef std::basic_string<char, std::char_traits<char>, oneapi::tbb::tbb_allocator<char>> MyString; 69*d86ed7fbStbbdev 70*d86ed7fbStbbdev //! Set to true to counts. 71*d86ed7fbStbbdev static bool verbose = false; 72*d86ed7fbStbbdev static bool silent = false; 73*d86ed7fbStbbdev static bool count_collisions = false; 74*d86ed7fbStbbdev //! Problem size 75*d86ed7fbStbbdev long N = 1000000; 76*d86ed7fbStbbdev const int size_factor = 2; 77*d86ed7fbStbbdev 78*d86ed7fbStbbdev //! A concurrent hash table that maps strings to ints. 79*d86ed7fbStbbdev typedef oneapi::tbb::concurrent_hash_map<MyString, int> StringTable; 80*d86ed7fbStbbdev 81*d86ed7fbStbbdev //! Function object for counting occurrences of strings. 82*d86ed7fbStbbdev struct Tally { 83*d86ed7fbStbbdev StringTable& table; 84*d86ed7fbStbbdev Tally(StringTable& table_) : table(table_) {} 85*d86ed7fbStbbdev void operator()(const oneapi::tbb::blocked_range<MyString*> range) const { 86*d86ed7fbStbbdev for (MyString* p = range.begin(); p != range.end(); ++p) { 87*d86ed7fbStbbdev StringTable::accessor a; 88*d86ed7fbStbbdev table.insert(a, *p); 89*d86ed7fbStbbdev a->second += 1; 90*d86ed7fbStbbdev } 91*d86ed7fbStbbdev } 92*d86ed7fbStbbdev }; 93*d86ed7fbStbbdev 94*d86ed7fbStbbdev static MyString* Data; 95*d86ed7fbStbbdev 96*d86ed7fbStbbdev static void CountOccurrences(int nthreads) { 97*d86ed7fbStbbdev StringTable table; 98*d86ed7fbStbbdev 99*d86ed7fbStbbdev oneapi::tbb::tick_count t0 = oneapi::tbb::tick_count::now(); 100*d86ed7fbStbbdev oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<MyString*>(Data, Data + N, 1000), 101*d86ed7fbStbbdev Tally(table)); 102*d86ed7fbStbbdev oneapi::tbb::tick_count t1 = oneapi::tbb::tick_count::now(); 103*d86ed7fbStbbdev 104*d86ed7fbStbbdev int n = 0; 105*d86ed7fbStbbdev for (StringTable::iterator i = table.begin(); i != table.end(); ++i) { 106*d86ed7fbStbbdev if (verbose && nthreads) 107*d86ed7fbStbbdev printf("%s %d\n", i->first.c_str(), i->second); 108*d86ed7fbStbbdev if (!silent && count_collisions) { 109*d86ed7fbStbbdev // it doesn't count real collisions in hash_map, a mask should be applied on hash value 110*d86ed7fbStbbdev hashes[std::hash<MyString>()(i->first) & 0xFFFF]++; 111*d86ed7fbStbbdev } 112*d86ed7fbStbbdev n += i->second; 113*d86ed7fbStbbdev } 114*d86ed7fbStbbdev if (!silent && count_collisions) { 115*d86ed7fbStbbdev for (auto i = hashes.begin(); i != hashes.end(); ++i) 116*d86ed7fbStbbdev c += i->second - 1; 117*d86ed7fbStbbdev printf("hashes = %d collisions = %d ", hashes.size(), c); 118*d86ed7fbStbbdev c = 0; 119*d86ed7fbStbbdev hashes.clear(); 120*d86ed7fbStbbdev } 121*d86ed7fbStbbdev 122*d86ed7fbStbbdev if (!silent) 123*d86ed7fbStbbdev printf( 124*d86ed7fbStbbdev "total = %d unique = %u time = %g\n", n, unsigned(table.size()), (t1 - t0).seconds()); 125*d86ed7fbStbbdev } 126*d86ed7fbStbbdev 127*d86ed7fbStbbdev /// Generator of random words 128*d86ed7fbStbbdev 129*d86ed7fbStbbdev struct Sound { 130*d86ed7fbStbbdev const char* chars; 131*d86ed7fbStbbdev int rates[3]; // beginning, middle, ending 132*d86ed7fbStbbdev }; 133*d86ed7fbStbbdev Sound Vowels[] = { 134*d86ed7fbStbbdev { "e", { 445, 6220, 1762 } }, { "a", { 704, 5262, 514 } }, { "i", { 402, 5224, 162 } }, 135*d86ed7fbStbbdev { "o", { 248, 3726, 191 } }, { "u", { 155, 1669, 23 } }, { "y", { 4, 400, 989 } }, 136*d86ed7fbStbbdev { "io", { 5, 512, 18 } }, { "ia", { 1, 329, 111 } }, { "ea", { 21, 370, 16 } }, 137*d86ed7fbStbbdev { "ou", { 32, 298, 4 } }, { "ie", { 0, 177, 140 } }, { "ee", { 2, 183, 57 } }, 138*d86ed7fbStbbdev { "ai", { 17, 206, 7 } }, { "oo", { 1, 215, 7 } }, { "au", { 40, 111, 2 } }, 139*d86ed7fbStbbdev { "ua", { 0, 102, 4 } }, { "ui", { 0, 104, 1 } }, { "ei", { 6, 94, 3 } }, 140*d86ed7fbStbbdev { "ue", { 0, 67, 28 } }, { "ay", { 1, 42, 52 } }, { "ey", { 1, 14, 80 } }, 141*d86ed7fbStbbdev { "oa", { 5, 84, 3 } }, { "oi", { 2, 81, 1 } }, { "eo", { 1, 71, 5 } }, 142*d86ed7fbStbbdev { "iou", { 0, 61, 0 } }, { "oe", { 2, 46, 9 } }, { "eu", { 12, 43, 0 } }, 143*d86ed7fbStbbdev { "iu", { 0, 45, 0 } }, { "ya", { 12, 19, 5 } }, { "ae", { 7, 18, 10 } }, 144*d86ed7fbStbbdev { "oy", { 0, 10, 13 } }, { "ye", { 8, 7, 7 } }, { "ion", { 0, 0, 20 } }, 145*d86ed7fbStbbdev { "ing", { 0, 0, 20 } }, { "ium", { 0, 0, 10 } }, { "er", { 0, 0, 20 } } 146*d86ed7fbStbbdev }; 147*d86ed7fbStbbdev Sound Consonants[] = { 148*d86ed7fbStbbdev { "r", { 483, 1414, 1110 } }, { "n", { 312, 1548, 1114 } }, { "t", { 363, 1653, 251 } }, 149*d86ed7fbStbbdev { "l", { 424, 1341, 489 } }, { "c", { 734, 735, 260 } }, { "m", { 732, 785, 161 } }, 150*d86ed7fbStbbdev { "d", { 558, 612, 389 } }, { "s", { 574, 570, 405 } }, { "p", { 519, 361, 98 } }, 151*d86ed7fbStbbdev { "b", { 528, 356, 30 } }, { "v", { 197, 598, 16 } }, { "ss", { 3, 191, 567 } }, 152*d86ed7fbStbbdev { "g", { 285, 430, 42 } }, { "st", { 142, 323, 180 } }, { "h", { 470, 89, 30 } }, 153*d86ed7fbStbbdev { "nt", { 0, 350, 231 } }, { "ng", { 0, 117, 442 } }, { "f", { 319, 194, 19 } }, 154*d86ed7fbStbbdev { "ll", { 1, 414, 83 } }, { "w", { 249, 131, 64 } }, { "k", { 154, 179, 47 } }, 155*d86ed7fbStbbdev { "nd", { 0, 279, 92 } }, { "bl", { 62, 235, 0 } }, { "z", { 35, 223, 16 } }, 156*d86ed7fbStbbdev { "sh", { 112, 69, 79 } }, { "ch", { 139, 95, 25 } }, { "th", { 70, 143, 39 } }, 157*d86ed7fbStbbdev { "tt", { 0, 219, 19 } }, { "tr", { 131, 104, 0 } }, { "pr", { 186, 41, 0 } }, 158*d86ed7fbStbbdev { "nc", { 0, 223, 2 } }, { "j", { 184, 32, 1 } }, { "nn", { 0, 188, 20 } }, 159*d86ed7fbStbbdev { "rt", { 0, 148, 51 } }, { "ct", { 0, 160, 29 } }, { "rr", { 0, 182, 3 } }, 160*d86ed7fbStbbdev { "gr", { 98, 87, 0 } }, { "ck", { 0, 92, 86 } }, { "rd", { 0, 81, 88 } }, 161*d86ed7fbStbbdev { "x", { 8, 102, 48 } }, { "ph", { 47, 101, 10 } }, { "br", { 115, 43, 0 } }, 162*d86ed7fbStbbdev { "cr", { 92, 60, 0 } }, { "rm", { 0, 131, 18 } }, { "ns", { 0, 124, 18 } }, 163*d86ed7fbStbbdev { "sp", { 81, 55, 4 } }, { "sm", { 25, 29, 85 } }, { "sc", { 53, 83, 1 } }, 164*d86ed7fbStbbdev { "rn", { 0, 100, 30 } }, { "cl", { 78, 42, 0 } }, { "mm", { 0, 116, 0 } }, 165*d86ed7fbStbbdev { "pp", { 0, 114, 2 } }, { "mp", { 0, 99, 14 } }, { "rs", { 0, 96, 16 } }, 166*d86ed7fbStbbdev { "rl", { 0, 97, 7 } }, { "rg", { 0, 81, 15 } }, { "pl", { 56, 39, 0 } }, 167*d86ed7fbStbbdev { "sn", { 32, 62, 1 } }, { "str", { 38, 56, 0 } }, { "dr", { 47, 44, 0 } }, 168*d86ed7fbStbbdev { "fl", { 77, 13, 1 } }, { "fr", { 77, 11, 0 } }, { "ld", { 0, 47, 38 } }, 169*d86ed7fbStbbdev { "ff", { 0, 62, 20 } }, { "lt", { 0, 61, 19 } }, { "rb", { 0, 75, 4 } }, 170*d86ed7fbStbbdev { "mb", { 0, 72, 7 } }, { "rc", { 0, 76, 1 } }, { "gg", { 0, 74, 1 } }, 171*d86ed7fbStbbdev { "pt", { 1, 56, 10 } }, { "bb", { 0, 64, 1 } }, { "sl", { 48, 17, 0 } }, 172*d86ed7fbStbbdev { "dd", { 0, 59, 2 } }, { "gn", { 3, 50, 4 } }, { "rk", { 0, 30, 28 } }, 173*d86ed7fbStbbdev { "nk", { 0, 35, 20 } }, { "gl", { 40, 14, 0 } }, { "wh", { 45, 6, 0 } }, 174*d86ed7fbStbbdev { "ntr", { 0, 50, 0 } }, { "rv", { 0, 47, 1 } }, { "ght", { 0, 19, 29 } }, 175*d86ed7fbStbbdev { "sk", { 23, 17, 5 } }, { "nf", { 0, 46, 0 } }, { "cc", { 0, 45, 0 } }, 176*d86ed7fbStbbdev { "ln", { 0, 41, 0 } }, { "sw", { 36, 4, 0 } }, { "rp", { 0, 36, 4 } }, 177*d86ed7fbStbbdev { "dn", { 0, 38, 0 } }, { "ps", { 14, 19, 5 } }, { "nv", { 0, 38, 0 } }, 178*d86ed7fbStbbdev { "tch", { 0, 21, 16 } }, { "nch", { 0, 26, 11 } }, { "lv", { 0, 35, 0 } }, 179*d86ed7fbStbbdev { "wn", { 0, 14, 21 } }, { "rf", { 0, 32, 3 } }, { "lm", { 0, 30, 5 } }, 180*d86ed7fbStbbdev { "dg", { 0, 34, 0 } }, { "ft", { 0, 18, 15 } }, { "scr", { 23, 10, 0 } }, 181*d86ed7fbStbbdev { "rch", { 0, 24, 6 } }, { "rth", { 0, 23, 7 } }, { "rh", { 13, 15, 0 } }, 182*d86ed7fbStbbdev { "mpl", { 0, 29, 0 } }, { "cs", { 0, 1, 27 } }, { "gh", { 4, 10, 13 } }, 183*d86ed7fbStbbdev { "ls", { 0, 23, 3 } }, { "ndr", { 0, 25, 0 } }, { "tl", { 0, 23, 1 } }, 184*d86ed7fbStbbdev { "ngl", { 0, 25, 0 } }, { "lk", { 0, 15, 9 } }, { "rw", { 0, 23, 0 } }, 185*d86ed7fbStbbdev { "lb", { 0, 23, 1 } }, { "tw", { 15, 8, 0 } }, { "chr", { 18, 4, 0 } }, 186*d86ed7fbStbbdev { "dl", { 0, 23, 0 } }, { "ctr", { 0, 22, 0 } }, { "nst", { 0, 21, 0 } }, 187*d86ed7fbStbbdev { "lc", { 0, 22, 0 } }, { "sch", { 16, 4, 0 } }, { "ths", { 0, 1, 20 } }, 188*d86ed7fbStbbdev { "nl", { 0, 21, 0 } }, { "lf", { 0, 15, 6 } }, { "ssn", { 0, 20, 0 } }, 189*d86ed7fbStbbdev { "xt", { 0, 18, 1 } }, { "xp", { 0, 20, 0 } }, { "rst", { 0, 15, 5 } }, 190*d86ed7fbStbbdev { "nh", { 0, 19, 0 } }, { "wr", { 14, 5, 0 } } 191*d86ed7fbStbbdev }; 192*d86ed7fbStbbdev const int VowelsNumber = sizeof(Vowels) / sizeof(Sound); 193*d86ed7fbStbbdev const int ConsonantsNumber = sizeof(Consonants) / sizeof(Sound); 194*d86ed7fbStbbdev int VowelsRatesSum[3] = { 0, 0, 0 }, ConsonantsRatesSum[3] = { 0, 0, 0 }; 195*d86ed7fbStbbdev 196*d86ed7fbStbbdev int CountRateSum(Sound sounds[], const int num, const int part) { 197*d86ed7fbStbbdev int sum = 0; 198*d86ed7fbStbbdev for (int i = 0; i < num; i++) 199*d86ed7fbStbbdev sum += sounds[i].rates[part]; 200*d86ed7fbStbbdev return sum; 201*d86ed7fbStbbdev } 202*d86ed7fbStbbdev 203*d86ed7fbStbbdev const char* GetLetters(int type, const int part) { 204*d86ed7fbStbbdev Sound* sounds; 205*d86ed7fbStbbdev int rate, i = 0; 206*d86ed7fbStbbdev if (type & 1) 207*d86ed7fbStbbdev sounds = Vowels, rate = rand() % VowelsRatesSum[part]; 208*d86ed7fbStbbdev else 209*d86ed7fbStbbdev sounds = Consonants, rate = rand() % ConsonantsRatesSum[part]; 210*d86ed7fbStbbdev do { 211*d86ed7fbStbbdev rate -= sounds[i++].rates[part]; 212*d86ed7fbStbbdev } while (rate > 0); 213*d86ed7fbStbbdev return sounds[--i].chars; 214*d86ed7fbStbbdev } 215*d86ed7fbStbbdev 216*d86ed7fbStbbdev static void CreateData() { 217*d86ed7fbStbbdev for (int i = 0; i < 3; i++) { 218*d86ed7fbStbbdev ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i); 219*d86ed7fbStbbdev VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i); 220*d86ed7fbStbbdev } 221*d86ed7fbStbbdev for (int i = 0; i < N; ++i) { 222*d86ed7fbStbbdev int type = rand(); 223*d86ed7fbStbbdev Data[i] = GetLetters(type++, 0); 224*d86ed7fbStbbdev for (int j = 0; j < type % size_factor; ++j) 225*d86ed7fbStbbdev Data[i] += GetLetters(type++, 1); 226*d86ed7fbStbbdev Data[i] += GetLetters(type, 2); 227*d86ed7fbStbbdev } 228*d86ed7fbStbbdev MyString planet = Data[12]; 229*d86ed7fbStbbdev planet[0] = toupper(planet[0]); 230*d86ed7fbStbbdev MyString helloworld = Data[0]; 231*d86ed7fbStbbdev helloworld[0] = toupper(helloworld[0]); 232*d86ed7fbStbbdev helloworld += ", " + Data[1] + " " + Data[2] + " " + Data[3] + " " + Data[4] + " " + Data[5]; 233*d86ed7fbStbbdev if (!silent) 234*d86ed7fbStbbdev printf("Message from planet '%s': %s!\nAnalyzing whole text...\n", 235*d86ed7fbStbbdev planet.c_str(), 236*d86ed7fbStbbdev helloworld.c_str()); 237*d86ed7fbStbbdev } 238*d86ed7fbStbbdev 239*d86ed7fbStbbdev int main(int argc, char* argv[]) { 240*d86ed7fbStbbdev StringTable table; 241*d86ed7fbStbbdev oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now(); 242*d86ed7fbStbbdev srand(2); 243*d86ed7fbStbbdev 244*d86ed7fbStbbdev //! Working threads count 245*d86ed7fbStbbdev // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value 246*d86ed7fbStbbdev // The example interprets 0 threads as "run serially, then fully subscribed" 247*d86ed7fbStbbdev utility::thread_number_range threads(utility::get_default_num_threads, 0); 248*d86ed7fbStbbdev 249*d86ed7fbStbbdev utility::parse_cli_arguments( 250*d86ed7fbStbbdev argc, 251*d86ed7fbStbbdev argv, 252*d86ed7fbStbbdev utility::cli_argument_pack() 253*d86ed7fbStbbdev //"-h" option for displaying help is present implicitly 254*d86ed7fbStbbdev .positional_arg(threads, "n-of-threads", utility::thread_number_range_desc) 255*d86ed7fbStbbdev .positional_arg(N, "n-of-strings", "number of strings") 256*d86ed7fbStbbdev .arg(verbose, "verbose", "verbose mode") 257*d86ed7fbStbbdev .arg(silent, "silent", "no output except elapsed time") 258*d86ed7fbStbbdev .arg(count_collisions, "count_collisions", "print the count of collisions")); 259*d86ed7fbStbbdev 260*d86ed7fbStbbdev if (silent) 261*d86ed7fbStbbdev verbose = false; 262*d86ed7fbStbbdev 263*d86ed7fbStbbdev Data = new MyString[N]; 264*d86ed7fbStbbdev CreateData(); 265*d86ed7fbStbbdev 266*d86ed7fbStbbdev if (threads.first) { 267*d86ed7fbStbbdev for (int p = threads.first; p <= threads.last; p = threads.step(p)) { 268*d86ed7fbStbbdev if (!silent) 269*d86ed7fbStbbdev printf("threads = %d ", p); 270*d86ed7fbStbbdev oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p); 271*d86ed7fbStbbdev CountOccurrences(p); 272*d86ed7fbStbbdev } 273*d86ed7fbStbbdev } 274*d86ed7fbStbbdev else { // Number of threads wasn't set explicitly. Run serial and parallel version 275*d86ed7fbStbbdev { // serial run 276*d86ed7fbStbbdev if (!silent) 277*d86ed7fbStbbdev printf("serial run "); 278*d86ed7fbStbbdev oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, 1); 279*d86ed7fbStbbdev CountOccurrences(1); 280*d86ed7fbStbbdev } 281*d86ed7fbStbbdev { // parallel run (number of threads is selected automatically) 282*d86ed7fbStbbdev if (!silent) 283*d86ed7fbStbbdev printf("parallel run "); 284*d86ed7fbStbbdev oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, 285*d86ed7fbStbbdev utility::get_default_num_threads()); 286*d86ed7fbStbbdev CountOccurrences(0); 287*d86ed7fbStbbdev } 288*d86ed7fbStbbdev } 289*d86ed7fbStbbdev 290*d86ed7fbStbbdev delete[] Data; 291*d86ed7fbStbbdev 292*d86ed7fbStbbdev utility::report_elapsed_time((oneapi::tbb::tick_count::now() - mainStartTime).seconds()); 293*d86ed7fbStbbdev 294*d86ed7fbStbbdev return 0; 295*d86ed7fbStbbdev } 296