//===-- Clustering.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// Utilities to compute benchmark result clusters. /// //===----------------------------------------------------------------------===// #ifndef LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H #define LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H #include "BenchmarkResult.h" #include "llvm/Support/Error.h" #include namespace exegesis { class InstructionBenchmarkClustering { public: // Clusters `Points` using DBSCAN with the given parameters. See the cc file // for more explanations on the algorithm. static llvm::Expected create(const std::vector &Points, size_t MinPts, double Epsilon); class ClusterId { public: static ClusterId noise() { return ClusterId(kNoise); } static ClusterId error() { return ClusterId(kError); } static ClusterId makeValid(int Id) { assert(Id >= 0); return ClusterId(Id); } ClusterId() : Id_(kUndef) {} bool operator==(const ClusterId &O) const { return Id_ == O.Id_; } bool isValid() const { return Id_ >= 0; } bool isUndef() const { return Id_ == kUndef; } bool isNoise() const { return Id_ == kNoise; } bool isError() const { return Id_ == kError; } // Precondition: isValid(). size_t getId() const { assert(isValid()); return static_cast(Id_); } private: explicit ClusterId(int Id) : Id_(Id) {} static constexpr const int kUndef = -1; static constexpr const int kNoise = -2; static constexpr const int kError = -3; int Id_; }; struct Cluster { Cluster() = delete; explicit Cluster(const ClusterId &Id) : Id(Id) {} const ClusterId Id; // Indices of benchmarks within the cluster. std::vector PointIndices; }; ClusterId getClusterIdForPoint(size_t P) const { return ClusterIdForPoint_[P]; } const std::vector &getPoints() const { return Points_; } const Cluster &getCluster(ClusterId Id) const { assert(!Id.isUndef() && "unlabeled cluster"); if (Id.isNoise()) { return NoiseCluster_; } if (Id.isError()) { return ErrorCluster_; } return Clusters_[Id.getId()]; } const std::vector &getValidClusters() const { return Clusters_; } private: InstructionBenchmarkClustering( const std::vector &Points); llvm::Error validateAndSetup(); void dbScan(size_t MinPts, double EpsilonSquared); const std::vector &Points_; int NumDimensions_ = 0; // ClusterForPoint_[P] is the cluster id for Points[P]. std::vector ClusterIdForPoint_; std::vector Clusters_; Cluster NoiseCluster_; Cluster ErrorCluster_; }; } // namespace exegesis #endif // LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H