1d86ed7fbStbbdev /*
2*b15aabb3Stbbdev     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 /* Example program that shows how to use parallel_for_each to do parallel preorder
18d86ed7fbStbbdev    traversal of a directed acyclic graph. */
19d86ed7fbStbbdev 
20d86ed7fbStbbdev #include <cstdlib>
21d86ed7fbStbbdev 
22d86ed7fbStbbdev #include <iostream>
23d86ed7fbStbbdev #include <vector>
24d86ed7fbStbbdev 
25d86ed7fbStbbdev #include "oneapi/tbb/tick_count.h"
26d86ed7fbStbbdev #include "oneapi/tbb/global_control.h"
27d86ed7fbStbbdev #include "common/utility/utility.hpp"
28d86ed7fbStbbdev #include "common/utility/get_default_num_threads.hpp"
29d86ed7fbStbbdev 
30d86ed7fbStbbdev #include "Graph.hpp"
31d86ed7fbStbbdev 
32d86ed7fbStbbdev // some forward declarations
33d86ed7fbStbbdev class Cell;
34d86ed7fbStbbdev void ParallelPreorderTraversal(const std::vector<Cell*>& root_set);
35d86ed7fbStbbdev 
36d86ed7fbStbbdev //------------------------------------------------------------------------
37d86ed7fbStbbdev // Test driver
38d86ed7fbStbbdev //------------------------------------------------------------------------
39d86ed7fbStbbdev static unsigned nodes = 1000;
40d86ed7fbStbbdev static unsigned traversals = 500;
41d86ed7fbStbbdev static bool SilentFlag = false;
42d86ed7fbStbbdev 
43d86ed7fbStbbdev //! Parse the command line.
ParseCommandLine(int argc,char * argv[],utility::thread_number_range & threads)44d86ed7fbStbbdev static void ParseCommandLine(int argc, char* argv[], utility::thread_number_range& threads) {
45d86ed7fbStbbdev     utility::parse_cli_arguments(
46d86ed7fbStbbdev         argc,
47d86ed7fbStbbdev         argv,
48d86ed7fbStbbdev         utility::cli_argument_pack()
49d86ed7fbStbbdev             //"-h" option for displaying help is present implicitly
50d86ed7fbStbbdev             .positional_arg(threads, "n-of-threads", utility::thread_number_range_desc)
51d86ed7fbStbbdev             .positional_arg(nodes, "n-of-nodes", "number of nodes in the graph.")
52d86ed7fbStbbdev             .positional_arg(
53d86ed7fbStbbdev                 traversals,
54d86ed7fbStbbdev                 "n-of-traversals",
55d86ed7fbStbbdev                 "number of times to evaluate the graph. Reduce it (e.g. to 100) to shorten example run time\n")
56d86ed7fbStbbdev             .arg(SilentFlag, "silent", "no output except elapsed time "));
57d86ed7fbStbbdev }
58d86ed7fbStbbdev 
main(int argc,char * argv[])59d86ed7fbStbbdev int main(int argc, char* argv[]) {
60d86ed7fbStbbdev     utility::thread_number_range threads(utility::get_default_num_threads);
61d86ed7fbStbbdev     oneapi::tbb::tick_count main_start = oneapi::tbb::tick_count::now();
62d86ed7fbStbbdev     ParseCommandLine(argc, argv, threads);
63d86ed7fbStbbdev 
64d86ed7fbStbbdev     // Start scheduler with given number of threads.
65d86ed7fbStbbdev     for (int p = threads.first; p <= threads.last; p = threads.step(p)) {
66d86ed7fbStbbdev         oneapi::tbb::tick_count t0 = oneapi::tbb::tick_count::now();
67d86ed7fbStbbdev         oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p);
68d86ed7fbStbbdev         srand(2);
69d86ed7fbStbbdev         std::size_t root_set_size = 0;
70d86ed7fbStbbdev         {
71d86ed7fbStbbdev             Graph g;
72d86ed7fbStbbdev             g.create_random_dag(nodes);
73d86ed7fbStbbdev             std::vector<Cell*> root_set;
74d86ed7fbStbbdev             g.get_root_set(root_set);
75d86ed7fbStbbdev             root_set_size = root_set.size();
76d86ed7fbStbbdev             for (unsigned int trial = 0; trial < traversals; ++trial) {
77d86ed7fbStbbdev                 ParallelPreorderTraversal(root_set);
78d86ed7fbStbbdev             }
79d86ed7fbStbbdev         }
80d86ed7fbStbbdev         oneapi::tbb::tick_count::interval_t interval = oneapi::tbb::tick_count::now() - t0;
81d86ed7fbStbbdev         if (!SilentFlag) {
82d86ed7fbStbbdev             std::cout << interval.seconds() << " seconds using " << p << " threads ("
83d86ed7fbStbbdev                       << root_set_size << " nodes in root_set)\n";
84d86ed7fbStbbdev         }
85d86ed7fbStbbdev     }
86d86ed7fbStbbdev     utility::report_elapsed_time((oneapi::tbb::tick_count::now() - main_start).seconds());
87d86ed7fbStbbdev 
88d86ed7fbStbbdev     return 0;
89d86ed7fbStbbdev }
90