Summary: See PR38936 for context.
Reviewers: gchatelet
Subscribers: tschuett, llvm-commits
Differential Revision: https://reviews.llvm.org/D52500
llvm-svn: 343081
#endif
for (const auto &Measurement : Point.Measurements) {
OS << kCsvSep;
- writeMeasurementValue<kEscapeCsv>(OS, Measurement.Value);
+ writeMeasurementValue<kEscapeCsv>(OS, Measurement.PerInstructionValue);
}
OS << "\n";
}
return false;
}
// Find the latency.
- SchedClassPoint[0].Value = 0.0;
+ SchedClassPoint[0].PerInstructionValue = 0.0;
for (unsigned I = 0; I < SC.SCDesc->NumWriteLatencyEntries; ++I) {
const llvm::MCWriteLatencyEntry *const WLE =
STI.getWriteLatencyEntry(SC.SCDesc, I);
- SchedClassPoint[0].Value =
- std::max<double>(SchedClassPoint[0].Value, WLE->Cycles);
+ SchedClassPoint[0].PerInstructionValue =
+ std::max<double>(SchedClassPoint[0].PerInstructionValue, WLE->Cycles);
}
- ClusterCenterPoint[0].Value = Representative[0].avg();
+ ClusterCenterPoint[0].PerInstructionValue = Representative[0].avg();
} else if (Mode == InstructionBenchmark::Uops) {
for (int I = 0, E = Representative.size(); I < E; ++I) {
// Find the pressure on ProcResIdx `Key`.
[ProcResIdx](const std::pair<uint16_t, float> &WPR) {
return WPR.first == ProcResIdx;
});
- SchedClassPoint[I].Value =
+ SchedClassPoint[I].PerInstructionValue =
ProcResPressureIt == SC.IdealizedProcResPressure.end()
? 0.0
: ProcResPressureIt->second;
- ClusterCenterPoint[I].Value = Representative[I].avg();
+ ClusterCenterPoint[I].PerInstructionValue = Representative[I].avg();
}
} else {
llvm::errs() << "unimplemented measurement matching for mode " << Mode
const std::vector<size_t> &getPointIds() const { return PointIds; }
// Return the cluster centroid.
- const std::vector<BenchmarkMeasureStats> &getRepresentative() const {
+ const std::vector<PerInstructionStats> &getRepresentative() const {
return Representative;
}
InstructionBenchmarkClustering::ClusterId ClusterId;
std::vector<size_t> PointIds;
// Measurement stats for the points in the SchedClassCluster.
- std::vector<BenchmarkMeasureStats> Representative;
+ std::vector<PerInstructionStats> Representative;
};
void printInstructionRowCsv(size_t PointId, llvm::raw_ostream &OS) const;
// e.g. { "key": "the key", "value": 0123 }
template <> struct MappingTraits<exegesis::BenchmarkMeasure> {
static void mapping(IO &Io, exegesis::BenchmarkMeasure &Obj) {
- Io.mapRequired("key", Obj.Key);
- Io.mapRequired("value", Obj.Value);
Io.mapOptional("debug_string", Obj.DebugString);
+ Io.mapRequired("value", Obj.PerInstructionValue);
+ Io.mapOptional("per_snippet_value", Obj.PerSnippetValue);
+ Io.mapRequired("key", Obj.Key);
}
static const bool flow = true;
};
return llvm::Error::success();
}
-void BenchmarkMeasureStats::push(const BenchmarkMeasure &BM) {
+void PerInstructionStats::push(const BenchmarkMeasure &BM) {
if (Key.empty())
Key = BM.Key;
assert(Key == BM.Key);
++NumValues;
- SumValues += BM.Value;
- MaxValue = std::max(MaxValue, BM.Value);
- MinValue = std::min(MinValue, BM.Value);
+ SumValues += BM.PerInstructionValue;
+ MaxValue = std::max(MaxValue, BM.PerInstructionValue);
+ MinValue = std::min(MinValue, BM.PerInstructionValue);
}
} // namespace exegesis
struct BenchmarkMeasure {
std::string Key;
- double Value;
+ // This is the per-instruction value, i.e. measured quantity scaled per
+ // instruction.
+ double PerInstructionValue;
+ // This is the per-snippet value, i.e. measured quantity for one repetition of
+ // the whole snippet.
+ double PerSnippetValue;
std::string DebugString;
};
// Utilities to work with Benchmark measures.
// A class that measures stats over benchmark measures.
-class BenchmarkMeasureStats {
+class PerInstructionStats {
public:
void push(const BenchmarkMeasure &BM);
<< *ObjectFilePath << "\n";
const ExecutableFunction EF(State.createTargetMachine(),
getObjectFromFile(*ObjectFilePath));
- InstrBenchmark.Measurements = runMeasurements(EF, *Scratch, NumRepetitions);
+ InstrBenchmark.Measurements = runMeasurements(EF, *Scratch);
+ assert(InstrBenchmark.NumRepetitions > 0 && "invalid NumRepetitions");
+ for (BenchmarkMeasure &BM : InstrBenchmark.Measurements) {
+ // Scale the measurements by instruction.
+ BM.PerInstructionValue /= InstrBenchmark.NumRepetitions;
+ // Scale the measurements by snippet.
+ BM.PerSnippetValue *= static_cast<double>(BC.Instructions.size()) /
+ InstrBenchmark.NumRepetitions;
+ }
return InstrBenchmark;
}
private:
virtual std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
- const unsigned NumRepetitions) const = 0;
+ runMeasurements(const ExecutableFunction &EF,
+ ScratchSpace &Scratch) const = 0;
llvm::Expected<std::string>
writeObjectFile(const BenchmarkCode &Configuration,
const std::vector<BenchmarkMeasure> &Q) const {
double DistanceSquared = 0.0;
for (size_t I = 0, E = P.size(); I < E; ++I) {
- const auto Diff = P[I].Value - Q[I].Value;
+ const auto Diff = P[I].PerInstructionValue - Q[I].PerInstructionValue;
DistanceSquared += Diff * Diff;
}
return DistanceSquared <= EpsilonSquared_;
std::vector<BenchmarkMeasure>
LatencyBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
- ScratchSpace &Scratch,
- const unsigned NumRepetitions) const {
+ ScratchSpace &Scratch) const {
// Cycle measurements include some overhead from the kernel. Repeat the
// measure several times and take the minimum value.
constexpr const int NumMeasurements = 30;
if (Value < MinLatency)
MinLatency = Value;
}
- return {{"latency", static_cast<double>(MinLatency) / NumRepetitions, ""}};
+ return {{"latency", static_cast<double>(MinLatency),
+ static_cast<double>(MinLatency), ""}};
}
} // namespace exegesis
private:
std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
- const unsigned NumRepetitions) const override;
+ runMeasurements(const ExecutableFunction &EF,
+ ScratchSpace &Scratch) const override;
virtual const char *getCounterName() const;
};
std::vector<BenchmarkMeasure>
UopsBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
- ScratchSpace &Scratch,
- const unsigned NumRepetitions) const {
+ ScratchSpace &Scratch) const {
const auto &SchedModel = State.getSubtargetInfo().getSchedModel();
std::vector<BenchmarkMeasure> Result;
CounterValue += Counter.read();
}
Result.push_back({llvm::itostr(ProcResIdx),
- static_cast<double>(CounterValue) / NumRepetitions,
+ static_cast<double>(CounterValue),
+ static_cast<double>(CounterValue),
SchedModel.getProcResource(ProcResIdx)->Name});
}
return Result;
private:
std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
- const unsigned NumRepetitions) const override;
+ runMeasurements(const ExecutableFunction &EF,
+ ScratchSpace &Scratch) const override;
};
} // namespace exegesis
std::vector<InstructionBenchmark> Points(6);
// Cluster around (x=0, y=1, z=2): points {0, 3}.
- Points[0].Measurements = {{"x", 0.01, ""}, {"y", 1.02, ""}, {"z", 1.98, "A"}};
- Points[3].Measurements = {{"x", -0.01, ""}, {"y", 1.02, ""}, {"z", 1.98, ""}};
+ Points[0].Measurements = {
+ {"x", 0.01, 0.0, ""}, {"y", 1.02, 0.0, ""}, {"z", 1.98, 0.0, "A"}};
+ Points[3].Measurements = {
+ {"x", -0.01, 0.0, ""}, {"y", 1.02, 0.0, ""}, {"z", 1.98, 0.0, ""}};
// Cluster around (x=1, y=1, z=2): points {1, 4}.
- Points[1].Measurements = {{"x", 1.01, ""}, {"y", 1.02, ""}, {"z", 1.98, ""}};
- Points[4].Measurements = {{"x", 0.99, ""}, {"y", 1.02, ""}, {"z", 1.98, ""}};
+ Points[1].Measurements = {
+ {"x", 1.01, 0.0, ""}, {"y", 1.02, 0.0, ""}, {"z", 1.98, 0.0, ""}};
+ Points[4].Measurements = {
+ {"x", 0.99, 0.0, ""}, {"y", 1.02, 0.0, ""}, {"z", 1.98, 0.0, ""}};
// Cluster around (x=0, y=0, z=0): points {5}, marked as noise.
- Points[5].Measurements = {{"x", 0.0, ""}, {"y", 0.01, ""}, {"z", -0.02, ""}};
+ Points[5].Measurements = {
+ {"x", 0.0, 0.0, ""}, {"y", 0.01, 0.0, ""}, {"z", -0.02, 0.0, ""}};
// Error cluster: points {2}
Points[2].Error = "oops";
TEST(ClusteringTest, Clusters3D_InvalidSize) {
std::vector<InstructionBenchmark> Points(6);
- Points[0].Measurements = {{"x", 0.01, ""}, {"y", 1.02, ""}, {"z", 1.98, ""}};
- Points[1].Measurements = {{"y", 1.02, ""}, {"z", 1.98, ""}};
+ Points[0].Measurements = {
+ {"x", 0.01, 0.0, ""}, {"y", 1.02, 0.0, ""}, {"z", 1.98, 0.0, ""}};
+ Points[1].Measurements = {{"y", 1.02, 0.0, ""}, {"z", 1.98, 0.0, ""}};
auto Error =
InstructionBenchmarkClustering::create(Points, 2, 0.25).takeError();
ASSERT_TRUE((bool)Error);
TEST(ClusteringTest, Clusters3D_InvalidOrder) {
std::vector<InstructionBenchmark> Points(6);
- Points[0].Measurements = {{"x", 0.01, ""}, {"y", 1.02, ""}};
- Points[1].Measurements = {{"y", 1.02, ""}, {"x", 1.98, ""}};
+ Points[0].Measurements = {{"x", 0.01, 0.0, ""}, {"y", 1.02, 0.0, ""}};
+ Points[1].Measurements = {{"y", 1.02, 0.0, ""}, {"x", 1.98, 0.0, ""}};
auto Error =
InstructionBenchmarkClustering::create(Points, 2, 0.25).takeError();
ASSERT_TRUE((bool)Error);
namespace exegesis {
bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B) {
- return std::tie(A.Key, A.Value) == std::tie(B.Key, B.Value);
+ return std::tie(A.Key, A.PerInstructionValue, A.PerSnippetValue) ==
+ std::tie(B.Key, B.PerInstructionValue, B.PerSnippetValue);
}
static std::string Dump(const llvm::MCInst &McInst) {
ToDisk.CpuName = "cpu_name";
ToDisk.LLVMTriple = "llvm_triple";
ToDisk.NumRepetitions = 1;
- ToDisk.Measurements.push_back(BenchmarkMeasure{"a", 1, "debug a"});
- ToDisk.Measurements.push_back(BenchmarkMeasure{"b", 2, ""});
+ ToDisk.Measurements.push_back(BenchmarkMeasure{"a", 1, 1, "debug a"});
+ ToDisk.Measurements.push_back(BenchmarkMeasure{"b", 2, 2, ""});
ToDisk.Error = "error";
ToDisk.Info = "info";
}
}
-TEST(BenchmarkResultTest, BenchmarkMeasureStats) {
- BenchmarkMeasureStats Stats;
- Stats.push(BenchmarkMeasure{"a", 0.5, "debug a"});
- Stats.push(BenchmarkMeasure{"a", 1.5, "debug a"});
- Stats.push(BenchmarkMeasure{"a", -1.0, "debug a"});
- Stats.push(BenchmarkMeasure{"a", 0.0, "debug a"});
+TEST(BenchmarkResultTest, PerInstructionStats) {
+ PerInstructionStats Stats;
+ Stats.push(BenchmarkMeasure{"a", 0.5, 0.0, "debug a"});
+ Stats.push(BenchmarkMeasure{"a", 1.5, 0.0, "debug a"});
+ Stats.push(BenchmarkMeasure{"a", -1.0, 0.0, "debug a"});
+ Stats.push(BenchmarkMeasure{"a", 0.0, 0.0, "debug a"});
EXPECT_EQ(Stats.min(), -1.0);
EXPECT_EQ(Stats.max(), 1.5);
EXPECT_EQ(Stats.avg(), 0.25); // (0.5+1.5-1.0+0.0) / 4