| 72 | double timer::stop() { return time_seconds(_timer_, time_now()); } |
| 73 | |
| 74 | double timeit(void (*fn)()) { |
| 75 | // Minimum target duration to limit impact of clock precision |
| 76 | constexpr double targetDurationPerTest = 0.050; |
| 77 | // samples during which the nr of cycles are determined to obtain target |
| 78 | // duration |
| 79 | constexpr int testSamples = 2; |
| 80 | // cycles needed to include CPU-GPU overlapping (if present) |
| 81 | constexpr int minCycles = 3; |
| 82 | // initial cycles used for the test samples |
| 83 | int cycles = minCycles; |
| 84 | // total number of real samples taken, of which the median is returned |
| 85 | constexpr int nrSamples = 10; |
| 86 | |
| 87 | std::array<double, nrSamples> X; |
| 88 | for (int s = -testSamples; s < nrSamples; ++s) { |
| 89 | af::sync(); |
| 90 | af::timer start = af::timer::start(); |
| 91 | for (int i = cycles; i > 0; --i) { fn(); } |
| 92 | af::sync(); |
| 93 | const double time = af::timer::stop(start); |
| 94 | if (s >= 0) { |
| 95 | // real sample, so store it for later processing |
| 96 | X[s] = time; |
| 97 | } else { |
| 98 | // test sample, so improve nr cycles |
| 99 | cycles = std::max( |
| 100 | minCycles, |
| 101 | static_cast<int>(trunc(targetDurationPerTest / time * cycles))); |
| 102 | }; |
| 103 | } |
| 104 | std::sort(X.begin(), X.end()); |
| 105 | // returns the median (iso of mean), to limit impact of outliers |
| 106 | return X[nrSamples / 2] / cycles; |
| 107 | } |
| 108 | |
| 109 | } // namespace af |