blob: 6b8f5a654d9042d8eb2c60186984bd3fdab29c85 [file] [log] [blame]
Clement Courbet96715412018-05-07 09:09:48 +00001//===-- Clustering.h --------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// Utilities to compute benchmark result clusters.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H
16#define LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H
17
18#include "BenchmarkResult.h"
19#include "llvm/Support/Error.h"
20#include <vector>
21
22namespace exegesis {
23
24class InstructionBenchmarkClustering {
25public:
26 // Clusters `Points` using DBSCAN with the given parameters. See the cc file
27 // for more explanations on the algorithm.
28 static llvm::Expected<InstructionBenchmarkClustering>
29 create(const std::vector<InstructionBenchmark> &Points, size_t MinPts,
30 double Epsilon);
31
32 class ClusterId {
33 public:
34 static ClusterId noise() { return ClusterId(kNoise); }
35 static ClusterId error() { return ClusterId(kError); }
36 static ClusterId makeValid(int Id) {
37 assert(Id >= 0);
38 return ClusterId(Id);
39 }
40 ClusterId() : Id_(kUndef) {}
41 bool operator==(const ClusterId &O) const { return Id_ == O.Id_; }
42
43 bool isValid() const { return Id_ >= 0; }
44 bool isUndef() const { return Id_ == kUndef; }
45 bool isNoise() const { return Id_ == kNoise; }
46 bool isError() const { return Id_ == kError; }
47
48 // Precondition: isValid().
49 size_t getId() const {
50 assert(isValid());
51 return static_cast<size_t>(Id_);
52 }
53
54 private:
55 explicit ClusterId(int Id) : Id_(Id) {}
56 static constexpr const int kUndef = -1;
57 static constexpr const int kNoise = -2;
58 static constexpr const int kError = -3;
59 int Id_;
60 };
61
62 struct Cluster {
63 Cluster() = delete;
64 explicit Cluster(const ClusterId &Id) : Id(Id) {}
65
66 const ClusterId Id;
67 // Indices of benchmarks within the cluster.
68 std::vector<int> PointIndices;
69 };
70
71 ClusterId getClusterIdForPoint(size_t P) const {
72 return ClusterIdForPoint_[P];
73 }
74
Clement Courbet37f0ca02018-05-15 12:08:00 +000075 const std::vector<InstructionBenchmark> &getPoints() const { return Points_; }
76
Clement Courbet96715412018-05-07 09:09:48 +000077 const Cluster &getCluster(ClusterId Id) const {
78 assert(!Id.isUndef() && "unlabeled cluster");
79 if (Id.isNoise()) {
80 return NoiseCluster_;
81 }
82 if (Id.isError()) {
83 return ErrorCluster_;
84 }
85 return Clusters_[Id.getId()];
86 }
87
88 const std::vector<Cluster> &getValidClusters() const { return Clusters_; }
89
90private:
Clement Courbet37f0ca02018-05-15 12:08:00 +000091 InstructionBenchmarkClustering(
92 const std::vector<InstructionBenchmark> &Points);
93 llvm::Error validateAndSetup();
94 void dbScan(size_t MinPts, double EpsilonSquared);
95 const std::vector<InstructionBenchmark> &Points_;
Clement Courbet96715412018-05-07 09:09:48 +000096 int NumDimensions_ = 0;
97 // ClusterForPoint_[P] is the cluster id for Points[P].
98 std::vector<ClusterId> ClusterIdForPoint_;
99 std::vector<Cluster> Clusters_;
100 Cluster NoiseCluster_;
101 Cluster ErrorCluster_;
102};
103
104} // namespace exegesis
105
106#endif // LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H