xref: /aosp_15_r20/external/pytorch/test/cpp/profiler/containers.cpp (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
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