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(Points, 2, 0.25); 50 ASSERT_TRUE((bool)Clustering); 51 EXPECT_THAT(Clustering.get().getValidClusters(), 52 UnorderedElementsAre(HasPoints({0, 3}), HasPoints({1, 4}))); 53 EXPECT_THAT(Clustering.get().getCluster( 54 InstructionBenchmarkClustering::ClusterId::noise()), 55 HasPoints({5})); 56 EXPECT_THAT(Clustering.get().getCluster( 57 InstructionBenchmarkClustering::ClusterId::error()), 58 HasPoints({2})); 59 60 EXPECT_EQ(Clustering.get().getClusterIdForPoint(2), 61 InstructionBenchmarkClustering::ClusterId::error()); 62 EXPECT_EQ(Clustering.get().getClusterIdForPoint(5), 63 InstructionBenchmarkClustering::ClusterId::noise()); 64 EXPECT_EQ(Clustering.get().getClusterIdForPoint(0), 65 Clustering.get().getClusterIdForPoint(3)); 66 EXPECT_EQ(Clustering.get().getClusterIdForPoint(1), 67 Clustering.get().getClusterIdForPoint(4)); 68 } 69 70 TEST(ClusteringTest, Clusters3D_InvalidSize) { 71 std::vector<InstructionBenchmark> Points(6); 72 Points[0].Measurements = { 73 {"x", 0.01, 0.0}, {"y", 1.02, 0.0}, {"z", 1.98, 0.0}}; 74 Points[1].Measurements = {{"y", 1.02, 0.0}, {"z", 1.98, 0.0}}; 75 auto Error = 76 InstructionBenchmarkClustering::create(Points, 2, 0.25).takeError(); 77 ASSERT_TRUE((bool)Error); 78 consumeError(std::move(Error)); 79 } 80 81 TEST(ClusteringTest, Clusters3D_InvalidOrder) { 82 std::vector<InstructionBenchmark> Points(6); 83 Points[0].Measurements = {{"x", 0.01, 0.0}, {"y", 1.02, 0.0}}; 84 Points[1].Measurements = {{"y", 1.02, 0.0}, {"x", 1.98, 0.0}}; 85 auto Error = 86 InstructionBenchmarkClustering::create(Points, 2, 0.25).takeError(); 87 ASSERT_TRUE((bool)Error); 88 consumeError(std::move(Error)); 89 } 90 91 TEST(ClusteringTest, Ordering) { 92 ASSERT_LT(InstructionBenchmarkClustering::ClusterId::makeValid(1), 93 InstructionBenchmarkClustering::ClusterId::makeValid(2)); 94 95 ASSERT_LT(InstructionBenchmarkClustering::ClusterId::makeValid(2), 96 InstructionBenchmarkClustering::ClusterId::noise()); 97 98 ASSERT_LT(InstructionBenchmarkClustering::ClusterId::makeValid(2), 99 InstructionBenchmarkClustering::ClusterId::error()); 100 101 ASSERT_LT(InstructionBenchmarkClustering::ClusterId::noise(), 102 InstructionBenchmarkClustering::ClusterId::error()); 103 } 104 105 TEST(ClusteringTest, Ordering1) { 106 std::vector<InstructionBenchmark> Points(3); 107 108 Points[0].Measurements = { 109 {"x", 0.0, 0.0}}; 110 Points[1].Measurements = { 111 {"x", 1.0, 0.0}}; 112 Points[2].Measurements = { 113 {"x", 2.0, 0.0}}; 114 115 auto Clustering = InstructionBenchmarkClustering::create(Points, 2, 1.1); 116 ASSERT_TRUE((bool)Clustering); 117 EXPECT_THAT(Clustering.get().getValidClusters(), 118 UnorderedElementsAre(HasPoints({0, 1, 2}))); 119 } 120 121 TEST(ClusteringTest, Ordering2) { 122 std::vector<InstructionBenchmark> Points(3); 123 124 Points[0].Measurements = { 125 {"x", 0.0, 0.0}}; 126 Points[1].Measurements = { 127 {"x", 2.0, 0.0}}; 128 Points[2].Measurements = { 129 {"x", 1.0, 0.0}}; 130 131 auto Clustering = InstructionBenchmarkClustering::create(Points, 2, 1.1); 132 ASSERT_TRUE((bool)Clustering); 133 EXPECT_THAT(Clustering.get().getValidClusters(), 134 UnorderedElementsAre(HasPoints({0, 1, 2}))); 135 } 136 137 } // namespace 138 } // namespace exegesis 139 } // namespace llvm 140