[libc][automemcpy] Introduce geomean of scores as a tie breaker

Differential Revision: https://reviews.llvm.org/D120040
This commit is contained in:
Guillaume Chatelet 2022-02-17 12:31:00 +00:00
parent 6457f42bde
commit da5a4f16e8
4 changed files with 32 additions and 22 deletions

View File

@ -60,7 +60,8 @@ struct PerDistributionData {
struct FunctionData {
FunctionId Id;
StringMap<PerDistributionData> PerDistributionData;
GradeHistogram GradeHisto = {}; // GradeEnum indexed array
double ScoresGeoMean; // Geomean of scores for each distribution.
GradeHistogram GradeHisto = {}; // GradeEnum indexed array
Grade::GradeEnum FinalGrade = Grade::BAD; // Overall grade for this function
};

View File

@ -168,14 +168,17 @@ void fillScores(MutableArrayRef<FunctionData> Functions) {
}
void castVotes(MutableArrayRef<FunctionData> Functions) {
for (FunctionData &Function : Functions)
for (FunctionData &Function : Functions) {
Function.ScoresGeoMean = 1.0;
for (const auto &Pair : Function.PerDistributionData) {
const StringRef Distribution = Pair.getKey();
const double Score = Pair.getValue().Score;
Function.ScoresGeoMean *= Score;
const auto G = Grade::judge(Score);
++(Function.GradeHisto[G]);
Function.PerDistributionData[Distribution].Grade = G;
}
}
for (FunctionData &Function : Functions) {
const auto &GradeHisto = Function.GradeHisto;

View File

@ -141,18 +141,16 @@ int Main(int argc, char **argv) {
fillScores(Functions);
castVotes(Functions);
// TODO: Implement tie breaking algorithm.
// Present data by function type, Grade and Geomean of scores.
std::sort(Functions.begin(), Functions.end(),
[](const FunctionData &A, const FunctionData &B) {
return A.FinalGrade < B.FinalGrade;
const auto Less = [](const FunctionData &FD) {
return std::make_tuple(FD.Id.Type, FD.FinalGrade,
-FD.ScoresGeoMean);
};
return Less(A) < Less(B);
});
// Present data by function type.
std::stable_sort(Functions.begin(), Functions.end(),
[](const FunctionData &A, const FunctionData &B) {
return A.Id.Type < B.Id.Type;
});
// Print result.
for (const FunctionData &Function : Functions) {
outs() << formatv("{0,-10}", Grade::getString(Function.FinalGrade));

View File

@ -139,27 +139,35 @@ TEST(AutomemcpyJsonResultsAnalyzer, castVotes) {
EXPECT_THAT(Data[1].Id, Foo2);
EXPECT_THAT(Data[2].Id, Foo3);
const auto GetDistData = [&Data](size_t Index, StringRef Name) {
return Data[Index].PerDistributionData.lookup(Name);
};
// Distribution A
// Throughput is 0, 1 and 7, so normalized scores are 0, 1/7 and 1.
EXPECT_NEAR(Data[0].PerDistributionData.lookup("A").Score, 0, kAbsErr);
EXPECT_NEAR(Data[1].PerDistributionData.lookup("A").Score, 1. / 7, kAbsErr);
EXPECT_NEAR(Data[2].PerDistributionData.lookup("A").Score, 1, kAbsErr);
EXPECT_THAT(GetDistData(0, "A").Score, DoubleNear(0, kAbsErr));
EXPECT_THAT(GetDistData(1, "A").Score, DoubleNear(1. / 7, kAbsErr));
EXPECT_THAT(GetDistData(2, "A").Score, DoubleNear(1, kAbsErr));
// which are turned into grades BAD, MEDIOCRE and EXCELLENT.
EXPECT_THAT(Data[0].PerDistributionData.lookup("A").Grade, Grade::BAD);
EXPECT_THAT(Data[1].PerDistributionData.lookup("A").Grade, Grade::MEDIOCRE);
EXPECT_THAT(Data[2].PerDistributionData.lookup("A").Grade, Grade::EXCELLENT);
EXPECT_THAT(GetDistData(0, "A").Grade, Grade::BAD);
EXPECT_THAT(GetDistData(1, "A").Grade, Grade::MEDIOCRE);
EXPECT_THAT(GetDistData(2, "A").Grade, Grade::EXCELLENT);
// Distribution B
// Throughput is 30, 100 and 100, so normalized scores are 0, 1 and 1.
EXPECT_NEAR(Data[0].PerDistributionData.lookup("B").Score, 0, kAbsErr);
EXPECT_NEAR(Data[1].PerDistributionData.lookup("B").Score, 1, kAbsErr);
EXPECT_NEAR(Data[2].PerDistributionData.lookup("B").Score, 1, kAbsErr);
EXPECT_THAT(GetDistData(0, "B").Score, DoubleNear(0, kAbsErr));
EXPECT_THAT(GetDistData(1, "B").Score, DoubleNear(1, kAbsErr));
EXPECT_THAT(GetDistData(2, "B").Score, DoubleNear(1, kAbsErr));
// which are turned into grades BAD, EXCELLENT and EXCELLENT.
EXPECT_THAT(Data[0].PerDistributionData.lookup("B").Grade, Grade::BAD);
EXPECT_THAT(Data[1].PerDistributionData.lookup("B").Grade, Grade::EXCELLENT);
EXPECT_THAT(Data[2].PerDistributionData.lookup("B").Grade, Grade::EXCELLENT);
EXPECT_THAT(GetDistData(0, "B").Grade, Grade::BAD);
EXPECT_THAT(GetDistData(1, "B").Grade, Grade::EXCELLENT);
EXPECT_THAT(GetDistData(2, "B").Grade, Grade::EXCELLENT);
// Now looking from the functions point of view.
EXPECT_THAT(Data[0].ScoresGeoMean, DoubleNear(0, kAbsErr));
EXPECT_THAT(Data[1].ScoresGeoMean, DoubleNear(1. * (1. / 7), kAbsErr));
EXPECT_THAT(Data[2].ScoresGeoMean, DoubleNear(1, kAbsErr));
// Note the array is indexed by GradeEnum values (EXCELLENT=0 / BAD = 6)
EXPECT_THAT(Data[0].GradeHisto, ElementsAre(0, 0, 0, 0, 0, 0, 2));
EXPECT_THAT(Data[1].GradeHisto, ElementsAre(1, 0, 0, 0, 0, 1, 0));