1 #include <algorithm>
2 #include <cmath>
3 #include <utility>
4 #include <vector>
5
6 #include <gtest/gtest.h>
7
8 #include <c10/util/ApproximateClock.h>
9 #include <c10/util/irange.h>
10 #include <torch/csrc/profiler/containers.h>
11 #include <torch/csrc/profiler/util.h>
12
TEST(ProfilerTest,AppendOnlyList)13 TEST(ProfilerTest, AppendOnlyList) {
14 const int n = 4096;
15 torch::profiler::impl::AppendOnlyList<int, 1024> list;
16 for (const auto i : c10::irange(n)) {
17 list.emplace_back(i);
18 ASSERT_EQ(list.size(), i + 1);
19 }
20
21 int expected = 0;
22 for (const auto i : list) {
23 ASSERT_EQ(i, expected++);
24 }
25 ASSERT_EQ(expected, n);
26
27 list.clear();
28 ASSERT_EQ(list.size(), 0);
29 }
30
TEST(ProfilerTest,AppendOnlyList_ref)31 TEST(ProfilerTest, AppendOnlyList_ref) {
32 const int n = 512;
33 torch::profiler::impl::AppendOnlyList<std::pair<int, int>, 64> list;
34 std::vector<std::pair<int, int>*> refs;
35 for (const auto _ : c10::irange(n)) {
36 refs.push_back(list.emplace_back());
37 }
38
39 for (const auto i : c10::irange(n)) {
40 *refs.at(i) = {i, 0};
41 }
42
43 int expected = 0;
44 for (const auto& i : list) {
45 ASSERT_EQ(i.first, expected++);
46 }
47 }
48
49 // Test that we can convert TSC measurements back to wall clock time.
TEST(ProfilerTest,clock_converter)50 TEST(ProfilerTest, clock_converter) {
51 const int n = 10001;
52 c10::ApproximateClockToUnixTimeConverter converter;
53 std::vector<
54 c10::ApproximateClockToUnixTimeConverter::UnixAndApproximateTimePair>
55 pairs;
56 for (const auto i : c10::irange(n)) {
57 pairs.push_back(c10::ApproximateClockToUnixTimeConverter::measurePair());
58 }
59 auto count_to_ns = converter.makeConverter();
60 std::vector<int64_t> deltas;
61 for (const auto& i : pairs) {
62 deltas.push_back(i.t_ - count_to_ns(i.approx_t_));
63 }
64 std::sort(deltas.begin(), deltas.end());
65
66 // In general it's not a good idea to put clocks in unit tests as it leads
67 // to flakiness. We mitigate this by:
68 // 1) Testing the clock itself. While the time to complete a task may
69 // vary, two clocks measuring the same time should be much more
70 // consistent.
71 // 2) Only testing the interquartile range. Context switches between
72 // calls to the two timers do occur and can result in hundreds of
73 // nanoseconds of noise, but such switches are only a few percent
74 // of cases.
75 // 3) We're willing to accept a somewhat large bias which can emerge from
76 // differences in the cost of calling each clock.
77 EXPECT_LT(std::abs(deltas[n / 2]), 200);
78 EXPECT_LT(deltas[n * 3 / 4] - deltas[n / 4], 50);
79 }
80
TEST(ProfilerTest,soft_assert)81 TEST(ProfilerTest, soft_assert) {
82 EXPECT_TRUE(SOFT_ASSERT(true));
83 torch::profiler::impl::setSoftAssertRaises(true);
84 EXPECT_ANY_THROW(SOFT_ASSERT(false));
85 torch::profiler::impl::setSoftAssertRaises(false);
86 EXPECT_NO_THROW(SOFT_ASSERT(false));
87 // Reset soft assert behavior to default
88 torch::profiler::impl::setSoftAssertRaises(std::nullopt);
89 EXPECT_NO_THROW(SOFT_ASSERT(false));
90 }
91