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