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 #define VIDEO_WINMAIN_ARGS
18d86ed7fbStbbdev 
19d86ed7fbStbbdev #include <iostream>
20d86ed7fbStbbdev 
21d86ed7fbStbbdev #include "oneapi/tbb/tick_count.h"
22d86ed7fbStbbdev #include "oneapi/tbb/global_control.h"
23d86ed7fbStbbdev 
24d86ed7fbStbbdev #include "common/utility/utility.hpp"
25d86ed7fbStbbdev #include "common/utility/get_default_num_threads.hpp"
26d86ed7fbStbbdev 
27d86ed7fbStbbdev #include "seismic_video.hpp"
28d86ed7fbStbbdev #include "universe.hpp"
29d86ed7fbStbbdev 
30d86ed7fbStbbdev Universe u;
31d86ed7fbStbbdev 
32d86ed7fbStbbdev struct RunOptions {
33d86ed7fbStbbdev     //! It is used for console mode for test with different number of threads and also has
34d86ed7fbStbbdev     //! meaning for GUI: threads.first  - use separate event/updating loop thread (>0) or not (0).
35d86ed7fbStbbdev     //!                  threads.second - initialization value for scheduler
36d86ed7fbStbbdev     utility::thread_number_range threads;
37d86ed7fbStbbdev     int numberOfFrames;
38d86ed7fbStbbdev     bool silent;
39d86ed7fbStbbdev     bool parallel;
RunOptionsRunOptions40d86ed7fbStbbdev     RunOptions(utility::thread_number_range threads_,
41d86ed7fbStbbdev                int number_of_frames_,
42d86ed7fbStbbdev                bool silent_,
43d86ed7fbStbbdev                bool parallel_)
44d86ed7fbStbbdev             : threads(threads_),
45d86ed7fbStbbdev               numberOfFrames(number_of_frames_),
46d86ed7fbStbbdev               silent(silent_),
47d86ed7fbStbbdev               parallel(parallel_) {}
48d86ed7fbStbbdev };
49d86ed7fbStbbdev 
ParseCommandLine(int argc,char * argv[])50d86ed7fbStbbdev RunOptions ParseCommandLine(int argc, char *argv[]) {
51d86ed7fbStbbdev     // zero number of threads means to run serial version
52d86ed7fbStbbdev     utility::thread_number_range threads(
53d86ed7fbStbbdev         utility::get_default_num_threads, 0, utility::get_default_num_threads());
54d86ed7fbStbbdev 
55d86ed7fbStbbdev     int numberOfFrames = 0;
56d86ed7fbStbbdev     bool silent = false;
57d86ed7fbStbbdev     bool serial = false;
58d86ed7fbStbbdev 
59d86ed7fbStbbdev     utility::parse_cli_arguments(
60d86ed7fbStbbdev         argc,
61d86ed7fbStbbdev         argv,
62d86ed7fbStbbdev         utility::cli_argument_pack()
63d86ed7fbStbbdev             //"-h" option for displaying help is present implicitly
64d86ed7fbStbbdev             .positional_arg(threads, "n-of-threads", utility::thread_number_range_desc)
65d86ed7fbStbbdev             .positional_arg(numberOfFrames,
66d86ed7fbStbbdev                             "n-of-frames",
67d86ed7fbStbbdev                             "number of frames the example processes internally (0 means unlimited)")
68d86ed7fbStbbdev             .arg(silent, "silent", "no output except elapsed time")
69d86ed7fbStbbdev             .arg(serial, "serial", "in GUI mode start with serial version of algorithm"));
70d86ed7fbStbbdev     return RunOptions(threads, numberOfFrames, silent, !serial);
71d86ed7fbStbbdev }
72d86ed7fbStbbdev 
main(int argc,char * argv[])73d86ed7fbStbbdev int main(int argc, char *argv[]) {
74d86ed7fbStbbdev     oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now();
75d86ed7fbStbbdev     RunOptions options = ParseCommandLine(argc, argv);
76d86ed7fbStbbdev     SeismicVideo video(u, options.numberOfFrames, options.threads.last, options.parallel);
77d86ed7fbStbbdev 
78d86ed7fbStbbdev     // video layer init
79d86ed7fbStbbdev     if (video.init_window(u.UniverseWidth, u.UniverseHeight)) {
80d86ed7fbStbbdev         video.calc_fps = true;
81d86ed7fbStbbdev         video.threaded = options.threads.first > 0;
82d86ed7fbStbbdev         // video is ok, init Universe
83d86ed7fbStbbdev         u.InitializeUniverse(video);
84d86ed7fbStbbdev         // main loop
85d86ed7fbStbbdev         video.main_loop();
86d86ed7fbStbbdev     }
87d86ed7fbStbbdev     else if (video.init_console()) {
88d86ed7fbStbbdev         // do console mode
89d86ed7fbStbbdev         if (options.numberOfFrames == 0) {
90d86ed7fbStbbdev             options.numberOfFrames = 1000;
91d86ed7fbStbbdev             std::cout << "Substituting 1000 for unlimited frames because not running interactively"
92d86ed7fbStbbdev                       << "\n";
93d86ed7fbStbbdev         }
94d86ed7fbStbbdev         for (int p = options.threads.first; p <= options.threads.last;
95d86ed7fbStbbdev              p = options.threads.step(p)) {
96d86ed7fbStbbdev             oneapi::tbb::tick_count xwayParallelismStartTime = oneapi::tbb::tick_count::now();
97d86ed7fbStbbdev             u.InitializeUniverse(video);
98d86ed7fbStbbdev             int numberOfFrames = options.numberOfFrames;
99d86ed7fbStbbdev 
100d86ed7fbStbbdev             if (p == 0) {
101d86ed7fbStbbdev                 //run a serial version
102d86ed7fbStbbdev                 for (int i = 0; i < numberOfFrames; ++i) {
103d86ed7fbStbbdev                     u.SerialUpdateUniverse();
104d86ed7fbStbbdev                 }
105d86ed7fbStbbdev             }
106d86ed7fbStbbdev             else {
107d86ed7fbStbbdev                 oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
108d86ed7fbStbbdev                                               p);
109d86ed7fbStbbdev                 for (int i = 0; i < numberOfFrames; ++i) {
110d86ed7fbStbbdev                     u.ParallelUpdateUniverse();
111d86ed7fbStbbdev                 }
112d86ed7fbStbbdev             }
113d86ed7fbStbbdev 
114d86ed7fbStbbdev             if (!options.silent) {
115d86ed7fbStbbdev                 double fps =
116d86ed7fbStbbdev                     options.numberOfFrames /
117d86ed7fbStbbdev                     ((oneapi::tbb::tick_count::now() - xwayParallelismStartTime).seconds());
118d86ed7fbStbbdev                 std::cout << fps << " frame per sec with ";
119d86ed7fbStbbdev                 if (p == 0) {
120d86ed7fbStbbdev                     std::cout << "serial code"
121d86ed7fbStbbdev                               << "\n";
122d86ed7fbStbbdev                 }
123d86ed7fbStbbdev                 else {
124d86ed7fbStbbdev                     std::cout << p << " way parallelism"
125d86ed7fbStbbdev                               << "\n";
126d86ed7fbStbbdev                 }
127d86ed7fbStbbdev             }
128d86ed7fbStbbdev         }
129d86ed7fbStbbdev     }
130d86ed7fbStbbdev     video.terminate();
131d86ed7fbStbbdev     utility::report_elapsed_time((oneapi::tbb::tick_count::now() - mainStartTime).seconds());
132d86ed7fbStbbdev     return 0;
133d86ed7fbStbbdev }
134