Skip to content

Commit

Permalink
[NFC][llvm-exegesis] Refactor Analysis::SchedClassCluster::measuremen…
Browse files Browse the repository at this point in the history
…tsMatch()

Summary:
The diff looks scary but it really isn't:
1. I moved the check for the number of measurements into `SchedClassClusterCentroid::validate()`
2. While there, added a check that we can only have a single inverse throughput measurement. I missed that when adding it initially.
3. In `Analysis::SchedClassCluster::measurementsMatch()` is called with the current LLVM values from schedule class and the values from Centroid.
3.1. The values from centroid we can already get from `SchedClassClusterCentroid::getAsPoint()`.
     This isn't 100% a NFC, because previously for inverse throughput we used `min()`. I have asked whether i have done that correctly in
     https://reviews.llvm.org/D57647?id=184939#inline-510384 but did not hear back. I think `avg()` should be used too, thus it is a fix.
3.2. Finally, refactor the computation of the LLVM-specified values into `Analysis::SchedClassCluster::getSchedClassPoint()`
     I will need that function for [[ https://bugs.llvm.org/show_bug.cgi?id=41275 | PR41275 ]]

Reviewers: courbet, gchatelet

Reviewed By: courbet

Subscribers: tschuett, jdoerfert, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D59951

llvm-svn: 357245
  • Loading branch information
LebedevRI committed Mar 29, 2019
1 parent aeaf7fc commit b8fb15d
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 31 deletions.
82 changes: 51 additions & 31 deletions llvm/tools/llvm-exegesis/lib/Analysis.cpp
Expand Up @@ -460,36 +460,33 @@ static unsigned findProcResIdx(const llvm::MCSubtargetInfo &STI,
return 0;
}

bool Analysis::SchedClassCluster::measurementsMatch(
const llvm::MCSubtargetInfo &STI, const ResolvedSchedClass &RSC,
const InstructionBenchmarkClustering &Clustering,
const double AnalysisInconsistencyEpsilonSquared_) const {
ArrayRef<PerInstructionStats> Representative = Centroid.getStats();
std::vector<BenchmarkMeasure> Analysis::SchedClassCluster::getSchedClassPoint(
InstructionBenchmark::ModeE Mode, const llvm::MCSubtargetInfo &STI,
const ResolvedSchedClass &RSC,
ArrayRef<PerInstructionStats> Representative) const {
const size_t NumMeasurements = Representative.size();
std::vector<BenchmarkMeasure> ClusterCenterPoint(NumMeasurements);

std::vector<BenchmarkMeasure> SchedClassPoint(NumMeasurements);
// Latency case.
assert(!Clustering.getPoints().empty());
const InstructionBenchmark::ModeE Mode = Clustering.getPoints()[0].Mode;

if (Mode == InstructionBenchmark::Latency) {
if (NumMeasurements != 1) {
llvm::errs()
<< "invalid number of measurements in latency mode: expected 1, got "
<< NumMeasurements << "\n";
return false;
}
assert(NumMeasurements == 1 && "Latency is a single measure.");
BenchmarkMeasure &LatencyMeasure = SchedClassPoint[0];

// Find the latency.
SchedClassPoint[0].PerInstructionValue = 0.0;
LatencyMeasure.PerInstructionValue = 0.0;

for (unsigned I = 0; I < RSC.SCDesc->NumWriteLatencyEntries; ++I) {
const llvm::MCWriteLatencyEntry *const WLE =
STI.getWriteLatencyEntry(RSC.SCDesc, I);
SchedClassPoint[0].PerInstructionValue =
std::max<double>(SchedClassPoint[0].PerInstructionValue, WLE->Cycles);
LatencyMeasure.PerInstructionValue =
std::max<double>(LatencyMeasure.PerInstructionValue, WLE->Cycles);
}
ClusterCenterPoint[0].PerInstructionValue = Representative[0].avg();
} else if (Mode == InstructionBenchmark::Uops) {
for (int I = 0, E = Representative.size(); I < E; ++I) {
const auto Key = Representative[I].key();
for (const auto &I : llvm::zip(SchedClassPoint, Representative)) {
BenchmarkMeasure &Measure = std::get<0>(I);
const PerInstructionStats &Stats = std::get<1>(I);

StringRef Key = Stats.key();
uint16_t ProcResIdx = findProcResIdx(STI, Key);
if (ProcResIdx > 0) {
// Find the pressure on ProcResIdx `Key`.
Expand All @@ -499,30 +496,53 @@ bool Analysis::SchedClassCluster::measurementsMatch(
[ProcResIdx](const std::pair<uint16_t, float> &WPR) {
return WPR.first == ProcResIdx;
});
SchedClassPoint[I].PerInstructionValue =
Measure.PerInstructionValue =
ProcResPressureIt == RSC.IdealizedProcResPressure.end()
? 0.0
: ProcResPressureIt->second;
} else if (Key == "NumMicroOps") {
SchedClassPoint[I].PerInstructionValue = RSC.SCDesc->NumMicroOps;
Measure.PerInstructionValue = RSC.SCDesc->NumMicroOps;
} else {
llvm::errs() << "expected `key` to be either a ProcResIdx or a ProcRes "
"name, got "
<< Key << "\n";
return false;
return {};
}
ClusterCenterPoint[I].PerInstructionValue = Representative[I].avg();
}
} else if (Mode == InstructionBenchmark::InverseThroughput) {
for (int I = 0, E = Representative.size(); I < E; ++I) {
SchedClassPoint[I].PerInstructionValue =
MCSchedModel::getReciprocalThroughput(STI, *RSC.SCDesc);
ClusterCenterPoint[I].PerInstructionValue = Representative[I].min();
}
assert(NumMeasurements == 1 && "Inverse Throughput is a single measure.");
BenchmarkMeasure &RThroughputMeasure = SchedClassPoint[0];

RThroughputMeasure.PerInstructionValue =
MCSchedModel::getReciprocalThroughput(STI, *RSC.SCDesc);
} else {
llvm_unreachable("unimplemented measurement matching mode");
return false;
}

return SchedClassPoint;
}

bool Analysis::SchedClassCluster::measurementsMatch(
const llvm::MCSubtargetInfo &STI, const ResolvedSchedClass &RSC,
const InstructionBenchmarkClustering &Clustering,
const double AnalysisInconsistencyEpsilonSquared_) const {
assert(!Clustering.getPoints().empty());
const InstructionBenchmark::ModeE Mode = Clustering.getPoints()[0].Mode;

if (!Centroid.validate(Mode))
return false;

const std::vector<BenchmarkMeasure> ClusterCenterPoint =
Centroid.getAsPoint();

const std::vector<BenchmarkMeasure> SchedClassPoint =
getSchedClassPoint(Mode, STI, RSC, Centroid.getStats());
if (SchedClassPoint.empty())
return false; // In Uops mode validate() may not be enough.

assert(ClusterCenterPoint.size() == SchedClassPoint.size() &&
"Expected measured/sched data dimensions to match.");

return Clustering.isNeighbour(ClusterCenterPoint, SchedClassPoint,
AnalysisInconsistencyEpsilonSquared_);
}
Expand Down
6 changes: 6 additions & 0 deletions llvm/tools/llvm-exegesis/lib/Analysis.h
Expand Up @@ -79,6 +79,12 @@ class Analysis {
// Return the cluster centroid.
const SchedClassClusterCentroid &getCentroid() const { return Centroid; }

std::vector<BenchmarkMeasure>
getSchedClassPoint(InstructionBenchmark::ModeE Mode,
const llvm::MCSubtargetInfo &STI,
const ResolvedSchedClass &SC,
ArrayRef<PerInstructionStats> Representative) const;

// Returns true if the cluster representative measurements match that of SC.
bool
measurementsMatch(const llvm::MCSubtargetInfo &STI,
Expand Down
31 changes: 31 additions & 0 deletions llvm/tools/llvm-exegesis/lib/Clustering.cpp
Expand Up @@ -363,5 +363,36 @@ std::vector<BenchmarkMeasure> SchedClassClusterCentroid::getAsPoint() const {
return ClusterCenterPoint;
}

bool SchedClassClusterCentroid::validate(
InstructionBenchmark::ModeE Mode) const {
size_t NumMeasurements = Representative.size();
switch (Mode) {
case InstructionBenchmark::Latency:
if (NumMeasurements != 1) {
llvm::errs()
<< "invalid number of measurements in latency mode: expected 1, got "
<< NumMeasurements << "\n";
return false;
}
break;
case InstructionBenchmark::Uops:
// Can have many measurements.
break;
case InstructionBenchmark::InverseThroughput:
if (NumMeasurements != 1) {
llvm::errs() << "invalid number of measurements in inverse throughput "
"mode: expected 1, got "
<< NumMeasurements << "\n";
return false;
}
break;
default:
llvm_unreachable("unimplemented measurement matching mode");
return false;
}

return true; // All good.
}

} // namespace exegesis
} // namespace llvm
2 changes: 2 additions & 0 deletions llvm/tools/llvm-exegesis/lib/Clustering.h
Expand Up @@ -156,6 +156,8 @@ class SchedClassClusterCentroid {

void addPoint(ArrayRef<BenchmarkMeasure> Point);

bool validate(InstructionBenchmark::ModeE Mode) const;

private:
// Measurement stats for the points in the SchedClassCluster.
std::vector<PerInstructionStats> Representative;
Expand Down

0 comments on commit b8fb15d

Please sign in to comment.