blob: 2027207a4b6c0a007a409361ad604e0d25f582e4 [file] [log] [blame]
Po-Hsien Wang00777b22019-04-24 16:37:09 -07001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <getopt.h>
6#include <sys/time.h>
7#include <unistd.h>
8#include <algorithm>
9#include <iterator>
10#include <map>
11#include <vector>
12
13#include "submitTest.h"
14#include "utils.h"
15
16// g_iteration determines the total iteration to run for each test
17int g_iteration = 1;
18// g_verbose determine the logging level to print into the screen.
19int g_verbose = false;
20// g_vlayer enables the vulkan verification layer if it is set.
21int g_vlayer = false;
22// g_notemp skips the temperature checking if it is set.
23int g_notemp = false;
24
25// all_tests list all the available tests.
26std::vector<vkbench::testBase*> all_tests = {
27 new vkbench::SubmitTest(10),
28 new vkbench::SubmitTest(100),
29 new vkbench::SubmitTest(1000),
30 new vkbench::SubmitTest(10000),
31};
32// kLongOptions defines the options for argument options.
33const static struct option kLongOptions[] = {
34 {"iterations", required_argument, nullptr, 'i'},
35 {"tests", required_argument, nullptr, 't'},
36 {"blacklist", required_argument, nullptr, 'b'},
37 {"list", no_argument, nullptr, 'l'},
38 {"help", no_argument, nullptr, 'h'},
39 {"notemp", no_argument, &g_notemp, 1},
40 {"vlayer", no_argument, &g_vlayer, 1},
41 {"verbose", no_argument, &g_verbose, 1},
42 {0, 0, 0, 0}};
43
44// TimeTest times the test by looping it iteration times.
45inline uint64_t TimeTest(vkbench::testBase* test, uint64_t iteration) {
46 uint64_t start = GetUTime();
47 bool passed = true;
48 try {
49 test->TestSetup();
50 for (int i = 0; i < iteration && passed; i++) {
51 passed = test->TestRun();
52 }
53 test->TestCleanup();
54 } catch (std::system_error e) {
55 DEBUG("Error while timing test %s.", test->Name())
56 throw e;
57 }
58 if (!passed) {
59 return std::numeric_limits<uint64_t>::max();
60 }
61 return GetUTime() - start;
62}
63
64// Run the test and pre/post processes.
65// @param target_temperature: The test would try to start until the machine get
66// to this temperature unless notemp is set.
67// @param duration_us: The test would to iterate till duration_us is reached.
68// @return: true if the test passes.
69bool Run(vkbench::testBase* test,
70 const double init_temperature,
71 const uint64_t duration_us = 1000000) {
72 try {
73 test->VkInitialization();
74 test->TestInitialization();
75 if (!g_notemp) {
76 double temperature = 0;
77 double cooldown_temperature = std::min(45.0, init_temperature + 6.0);
78 double
79 wait = WaitForCoolMachine(cooldown_temperature, 30.0, &temperature);
80 LOG("Waited %f second for machine temperature to cool down to %f.", wait,
81 temperature)
82 }
83 // Do some iterations since initial timings may vary.
84 TimeTest(test, 2);
85 // Target minimum iteration is 1s for each test.
86 uint64_t time = 0;
87 uint64_t iteration = 1;
88 double score = -1.f;
89 do {
90 time = TimeTest(test, iteration);
91 DEBUG("iterations: %llu, time: %llu us, time/iter: %llu us", iteration,
92 time, time / iteration)
93 if (time > duration_us) {
94 if (time == std::numeric_limits<uint64_t>::max()) {
95 return false;
96 } else {
97 score = time / iteration;
98 break;
99 }
100 }
101 iteration = iteration * 2;
102 } while ((1ull << 40) > iteration);
103// Returns 0.0 if it ran max iterations in less than test time.
104 if (score <= 0.01f) LOG("%s: measurement may not be accurate.",
105 test->Name())
106 score = test->FormatMeasurement(score);
107 LOG("@RESULT: %46s = %10.2f %-15s", test->Name(), score, test->Unit())
108
109 } catch (std::system_error e) {
110 DEBUG("Error while running test: %s", e.what())
111 return false;
112 }
113 test->TestDestroy();
114 test->VkDestroy();
115 return true;
116}
117
118void PrintTests() {
119 for (const auto& test : all_tests) {
120 LOG("%s: %s", test->Name(), test->Desp())
121 }
122}
123
124void PrintHelp() {
125 LOG(R",(
126Usage: vkbench [OPTIONS]
127 -i, --iterations=N Specify the iterations to run the tests.
128 -t, --tests=TESTS Tests to run in colon separated form.
129 -b, --blacklist=TESTS Tests to not run in colon separated form.
130 --list List the tests available.
131 --verbose Show verbose messages.
132 --vlayer Enable vulkan verification layer.
133 --notemp Do not wait for temperature to cool down.),")
134}
135
136bool ParseArgv(int argc, char** argv) {
137 std::vector<std::string> enabled_tests;
138 std::vector<std::string> disabled_tests;
139 int c;
140 int option_index = 0;
141 while ((c = getopt_long(argc, argv, "i:t:b:", kLongOptions, &option_index)) !=
142 -1) {
143 if (c == 'i') {
144 g_iteration = atoi(optarg);
145 } else if (c == 't') {
146 enabled_tests = SplitString(std::string(optarg), ':');
147 } else if (c == 'b') {
148 disabled_tests = SplitString(std::string(optarg), ':');
149 } else if (c == 'l') {
150 PrintTests();
151 return false;
152 } else if (c == '?' || c == 'h') {
153 PrintHelp();
154 return false;
155 }
156 }
157
158 if (optind < argc) {
159 ERROR("Unknown argv: ")
160 while (optind < argc) ERROR("%s ", argv[optind++])
161 return false;
162 }
163
164 all_tests.erase(
165 remove_if(
166 all_tests.begin(), all_tests.end(),
167 [enabled_tests, disabled_tests](const vkbench::testBase* test) {
168 bool isDisabled =
169 !IsItemInVector(enabled_tests, test->Name(), true) ||
170 IsItemInVector(disabled_tests, test->Name(), false);
171 if (isDisabled)
172 delete test;
173 return isDisabled;
174 }),
175 all_tests.end());
176 return true;
177}
178
179int main(int argc, char* argv[]) {
180 if (!ParseArgv(argc, argv))
181 return 0;
182
183 double init_temperature = g_notemp ? 40 : GetMachineTemperature();
184 std::map<const char*, int> failed_test;
185 LOG("@TEST_BEGIN")
186 PrintDateTime();
187 for (auto i = 0; i<all_tests.size(); i++ ){
188 auto &test = all_tests[i];
189 for (auto iter = 0; iter < g_iteration; i++) {
190 if (!Run(test, init_temperature, 1000000 )) {
191 failed_test[test->Name()] += 1;
192 }
193 }
194 }
195 PrintDateTime();
196 LOG("@TEST_END")
197
198 for (auto& keyval : failed_test) {
199 LOG("%s failed %d times.", keyval.first, keyval.second)
200 }
201
202 for (auto& test : all_tests) {
203 delete test;
204 }
205
206 return 0;
207}