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