xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/ClusteringTest.cpp (revision c2423fe6899aad89fe0ac2aa4b873cb79ec15bd0)
1 //===-- ClusteringTest.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Clustering.h"
10 #include "BenchmarkResult.h"
11 #include "llvm/Support/Error.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15 
16 namespace llvm {
17 namespace exegesis {
18 
19 namespace {
20 
21 using testing::Field;
22 using testing::UnorderedElementsAre;
23 using testing::UnorderedElementsAreArray;
24 
25 static const auto HasPoints = [](const std::vector<int> &Indices) {
26   return Field(&InstructionBenchmarkClustering::Cluster::PointIndices,
27                  UnorderedElementsAreArray(Indices));
28 };
29 
30 TEST(ClusteringTest, Clusters3D) {
31   std::vector<InstructionBenchmark> Points(6);
32 
33   // Cluster around (x=0, y=1, z=2): points {0, 3}.
34   Points[0].Measurements = {
35       {"x", 0.01, 0.0}, {"y", 1.02, 0.0}, {"z", 1.98, 0.0}};
36   Points[3].Measurements = {
37       {"x", -0.01, 0.0}, {"y", 1.02, 0.0}, {"z", 1.98, 0.0}};
38   // Cluster around (x=1, y=1, z=2): points {1, 4}.
39   Points[1].Measurements = {
40       {"x", 1.01, 0.0}, {"y", 1.02, 0.0}, {"z", 1.98, 0.0}};
41   Points[4].Measurements = {
42       {"x", 0.99, 0.0}, {"y", 1.02, 0.0}, {"z", 1.98, 0.0}};
43   // Cluster around (x=0, y=0, z=0): points {5}, marked as noise.
44   Points[5].Measurements = {
45       {"x", 0.0, 0.0}, {"y", 0.01, 0.0}, {"z", -0.02, 0.0}};
46   // Error cluster: points {2}
47   Points[2].Error = "oops";
48 
49   auto Clustering = InstructionBenchmarkClustering::create(
50       Points, InstructionBenchmarkClustering::ModeE::Dbscan, 2, 0.25);
51   ASSERT_TRUE((bool)Clustering);
52   EXPECT_THAT(Clustering.get().getValidClusters(),
53               UnorderedElementsAre(HasPoints({0, 3}), HasPoints({1, 4})));
54   EXPECT_THAT(Clustering.get().getCluster(
55                   InstructionBenchmarkClustering::ClusterId::noise()),
56               HasPoints({5}));
57   EXPECT_THAT(Clustering.get().getCluster(
58                   InstructionBenchmarkClustering::ClusterId::error()),
59               HasPoints({2}));
60 
61   EXPECT_EQ(Clustering.get().getClusterIdForPoint(2),
62             InstructionBenchmarkClustering::ClusterId::error());
63   EXPECT_EQ(Clustering.get().getClusterIdForPoint(5),
64             InstructionBenchmarkClustering::ClusterId::noise());
65   EXPECT_EQ(Clustering.get().getClusterIdForPoint(0),
66             Clustering.get().getClusterIdForPoint(3));
67   EXPECT_EQ(Clustering.get().getClusterIdForPoint(1),
68             Clustering.get().getClusterIdForPoint(4));
69 }
70 
71 TEST(ClusteringTest, Clusters3D_InvalidSize) {
72   std::vector<InstructionBenchmark> Points(6);
73   Points[0].Measurements = {
74       {"x", 0.01, 0.0}, {"y", 1.02, 0.0}, {"z", 1.98, 0.0}};
75   Points[1].Measurements = {{"y", 1.02, 0.0}, {"z", 1.98, 0.0}};
76   auto Error =
77       InstructionBenchmarkClustering::create(
78           Points, InstructionBenchmarkClustering::ModeE::Dbscan, 2, 0.25)
79           .takeError();
80   ASSERT_TRUE((bool)Error);
81   consumeError(std::move(Error));
82 }
83 
84 TEST(ClusteringTest, Clusters3D_InvalidOrder) {
85   std::vector<InstructionBenchmark> Points(6);
86   Points[0].Measurements = {{"x", 0.01, 0.0}, {"y", 1.02, 0.0}};
87   Points[1].Measurements = {{"y", 1.02, 0.0}, {"x", 1.98, 0.0}};
88   auto Error =
89       InstructionBenchmarkClustering::create(
90           Points, InstructionBenchmarkClustering::ModeE::Dbscan, 2, 0.25)
91           .takeError();
92   ASSERT_TRUE((bool)Error);
93   consumeError(std::move(Error));
94 }
95 
96 TEST(ClusteringTest, Ordering) {
97   ASSERT_LT(InstructionBenchmarkClustering::ClusterId::makeValid(1),
98             InstructionBenchmarkClustering::ClusterId::makeValid(2));
99 
100   ASSERT_LT(InstructionBenchmarkClustering::ClusterId::makeValid(2),
101             InstructionBenchmarkClustering::ClusterId::noise());
102 
103   ASSERT_LT(InstructionBenchmarkClustering::ClusterId::makeValid(2),
104             InstructionBenchmarkClustering::ClusterId::error());
105 
106   ASSERT_LT(InstructionBenchmarkClustering::ClusterId::noise(),
107             InstructionBenchmarkClustering::ClusterId::error());
108 }
109 
110 TEST(ClusteringTest, Ordering1) {
111   std::vector<InstructionBenchmark> Points(3);
112 
113   Points[0].Measurements = {
114       {"x", 0.0, 0.0}};
115   Points[1].Measurements = {
116       {"x", 1.0, 0.0}};
117   Points[2].Measurements = {
118       {"x", 2.0, 0.0}};
119 
120   auto Clustering = InstructionBenchmarkClustering::create(
121       Points, InstructionBenchmarkClustering::ModeE::Dbscan, 2, 1.1);
122   ASSERT_TRUE((bool)Clustering);
123   EXPECT_THAT(Clustering.get().getValidClusters(),
124               UnorderedElementsAre(HasPoints({0, 1, 2})));
125 }
126 
127 TEST(ClusteringTest, Ordering2) {
128   std::vector<InstructionBenchmark> Points(3);
129 
130   Points[0].Measurements = {
131       {"x", 0.0, 0.0}};
132   Points[1].Measurements = {
133       {"x", 2.0, 0.0}};
134   Points[2].Measurements = {
135       {"x", 1.0, 0.0}};
136 
137   auto Clustering = InstructionBenchmarkClustering::create(
138       Points, InstructionBenchmarkClustering::ModeE::Dbscan, 2, 1.1);
139   ASSERT_TRUE((bool)Clustering);
140   EXPECT_THAT(Clustering.get().getValidClusters(),
141               UnorderedElementsAre(HasPoints({0, 1, 2})));
142 }
143 
144 } // namespace
145 } // namespace exegesis
146 } // namespace llvm
147