Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 28 additions & 27 deletions libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class BinaryOpSingleOutputPerf {
public:
typedef OutputType Func(InputType, InputType);

static void run_perf_in_range(Func myFunc, Func otherFunc,
StorageType startingBit, StorageType endingBit,
size_t N, size_t rounds, std::ofstream &log) {
static void run_perf_in_range(Func FuncA, Func FuncB, StorageType startingBit,
StorageType endingBit, size_t N, size_t rounds,
std::ofstream &log) {
if (sizeof(StorageType) <= sizeof(size_t))
N = cpp::min(N, static_cast<size_t>(endingBit - startingBit));

Expand All @@ -54,48 +54,48 @@ class BinaryOpSingleOutputPerf {

Timer timer;
timer.start();
runner(myFunc);
runner(FuncA);
timer.stop();

double my_average = static_cast<double>(timer.nanoseconds()) / N / rounds;
log << "-- My function --\n";
double a_average = static_cast<double>(timer.nanoseconds()) / N / rounds;
log << "-- Function A --\n";
log << " Total time : " << timer.nanoseconds() << " ns \n";
log << " Average runtime : " << my_average << " ns/op \n";
log << " Average runtime : " << a_average << " ns/op \n";
log << " Ops per second : "
<< static_cast<uint64_t>(1'000'000'000.0 / my_average) << " op/s \n";
<< static_cast<uint64_t>(1'000'000'000.0 / a_average) << " op/s \n";

timer.start();
runner(otherFunc);
runner(FuncB);
timer.stop();

double other_average =
static_cast<double>(timer.nanoseconds()) / N / rounds;
log << "-- Other function --\n";
double b_average = static_cast<double>(timer.nanoseconds()) / N / rounds;
log << "-- Function B --\n";
log << " Total time : " << timer.nanoseconds() << " ns \n";
log << " Average runtime : " << other_average << " ns/op \n";
log << " Average runtime : " << b_average << " ns/op \n";
log << " Ops per second : "
<< static_cast<uint64_t>(1'000'000'000.0 / other_average) << " op/s \n";
<< static_cast<uint64_t>(1'000'000'000.0 / b_average) << " op/s \n";

log << "-- Average runtime ratio --\n";
log << " Mine / Other's : " << my_average / other_average << " \n";
log << "-- Average ops per second ratio --\n";
log << " A / B : " << b_average / a_average << " \n";
}

static void run_perf(Func myFunc, Func otherFunc, int rounds,
const char *logFile) {
static void run_perf(Func FuncA, Func FuncB, int rounds, const char *name_a,
const char *name_b, const char *logFile) {
std::ofstream log(logFile);
log << "Function A - " << name_a << " Function B - " << name_b << "\n";
log << " Performance tests with inputs in denormal range:\n";
run_perf_in_range(myFunc, otherFunc, /* startingBit= */ StorageType(0),
run_perf_in_range(FuncA, FuncB, /* startingBit= */ StorageType(0),
/* endingBit= */ FPBits::max_subnormal().uintval(),
1'000'001, rounds, log);
log << "\n Performance tests with inputs in normal range:\n";
run_perf_in_range(myFunc, otherFunc,
run_perf_in_range(FuncA, FuncB,
/* startingBit= */ FPBits::min_normal().uintval(),
/* endingBit= */ FPBits::max_normal().uintval(),
1'000'001, rounds, log);
log << "\n Performance tests with inputs in normal range with exponents "
"close to each other:\n";
run_perf_in_range(
myFunc, otherFunc,
FuncA, FuncB,
/* startingBit= */ FPBits(OutputType(0x1.0p-10)).uintval(),
/* endingBit= */ FPBits(OutputType(0x1.0p+10)).uintval(), 1'000'001,
rounds, log);
Expand Down Expand Up @@ -128,21 +128,22 @@ class BinaryOpSingleOutputPerf {
} // namespace testing
} // namespace LIBC_NAMESPACE_DECL

#define BINARY_OP_SINGLE_OUTPUT_PERF(OutputType, InputType, myFunc, otherFunc, \
#define BINARY_OP_SINGLE_OUTPUT_PERF(OutputType, InputType, FuncA, FuncB, \
filename) \
int main() { \
LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf< \
OutputType, InputType>::run_perf(&myFunc, &otherFunc, 1, filename); \
OutputType, InputType>::run_perf(&FuncA, &FuncB, 1, #FuncA, #FuncB, \
filename); \
return 0; \
}

#define BINARY_OP_SINGLE_OUTPUT_PERF_EX(OutputType, InputType, myFunc, \
otherFunc, rounds, filename) \
#define BINARY_OP_SINGLE_OUTPUT_PERF_EX(OutputType, InputType, FuncA, FuncB, \
rounds, filename) \
{ \
LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf< \
OutputType, InputType>::run_perf(&myFunc, &otherFunc, rounds, \
OutputType, InputType>::run_perf(&FuncA, &FuncB, 1, #FuncA, #FuncB, \
filename); \
LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf< \
OutputType, InputType>::run_perf(&myFunc, &otherFunc, rounds, \
OutputType, InputType>::run_perf(&FuncA, &FuncB, 1, #FuncA, #FuncB, \
filename); \
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ template <typename T> class SingleInputSingleOutputPerf {
public:
typedef T Func(T);

static void runPerfInRange(Func myFunc, Func otherFunc,
StorageType startingBit, StorageType endingBit,
size_t rounds, std::ofstream &log) {
static void runPerfInRange(Func FuncA, Func FuncB, StorageType startingBit,
StorageType endingBit, size_t rounds,
std::ofstream &log) {
size_t n = 10'010'001;
if (sizeof(StorageType) <= sizeof(size_t))
n = cpp::min(n, static_cast<size_t>(endingBit - startingBit));
Expand All @@ -47,40 +47,41 @@ template <typename T> class SingleInputSingleOutputPerf {

Timer timer;
timer.start();
runner(myFunc);
runner(FuncA);
timer.stop();

double myAverage = static_cast<double>(timer.nanoseconds()) / n / rounds;
log << "-- My function --\n";
double a_average = static_cast<double>(timer.nanoseconds()) / n / rounds;
log << "-- Function A --\n";
log << " Total time : " << timer.nanoseconds() << " ns \n";
log << " Average runtime : " << myAverage << " ns/op \n";
log << " Average runtime : " << a_average << " ns/op \n";
log << " Ops per second : "
<< static_cast<uint64_t>(1'000'000'000.0 / myAverage) << " op/s \n";
<< static_cast<uint64_t>(1'000'000'000.0 / a_average) << " op/s \n";

timer.start();
runner(otherFunc);
runner(FuncB);
timer.stop();

double otherAverage = static_cast<double>(timer.nanoseconds()) / n / rounds;
log << "-- Other function --\n";
double b_average = static_cast<double>(timer.nanoseconds()) / n / rounds;
log << "-- Function B --\n";
log << " Total time : " << timer.nanoseconds() << " ns \n";
log << " Average runtime : " << otherAverage << " ns/op \n";
log << " Average runtime : " << b_average << " ns/op \n";
log << " Ops per second : "
<< static_cast<uint64_t>(1'000'000'000.0 / otherAverage) << " op/s \n";
<< static_cast<uint64_t>(1'000'000'000.0 / b_average) << " op/s \n";

log << "-- Average runtime ratio --\n";
log << " Mine / Other's : " << myAverage / otherAverage << " \n";
log << "-- Average ops per second ratio --\n";
log << " A / B : " << b_average / a_average << " \n";
}

static void runPerf(Func myFunc, Func otherFunc, size_t rounds,
const char *logFile) {
static void runPerf(Func FuncA, Func FuncB, size_t rounds, const char *name_a,
const char *name_b, const char *logFile) {
std::ofstream log(logFile);
log << "Function A - " << name_a << " Function B - " << name_b << "\n";
log << " Performance tests with inputs in denormal range:\n";
runPerfInRange(myFunc, otherFunc, /* startingBit= */ StorageType(0),
runPerfInRange(FuncA, FuncB, /* startingBit= */ StorageType(0),
/* endingBit= */ FPBits::max_subnormal().uintval(), rounds,
log);
log << "\n Performance tests with inputs in normal range:\n";
runPerfInRange(myFunc, otherFunc,
runPerfInRange(FuncA, FuncB,
/* startingBit= */ FPBits::min_normal().uintval(),
/* endingBit= */ FPBits::max_normal().uintval(), rounds,
log);
Expand All @@ -90,16 +91,15 @@ template <typename T> class SingleInputSingleOutputPerf {
} // namespace testing
} // namespace LIBC_NAMESPACE_DECL

#define SINGLE_INPUT_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \
#define SINGLE_INPUT_SINGLE_OUTPUT_PERF(T, FuncA, FuncB, filename) \
int main() { \
LIBC_NAMESPACE::testing::SingleInputSingleOutputPerf<T>::runPerf( \
&myFunc, &otherFunc, 1, filename); \
&FuncA, &FuncB, 1, #FuncA, #FuncB, filename); \
return 0; \
}

#define SINGLE_INPUT_SINGLE_OUTPUT_PERF_EX(T, myFunc, otherFunc, rounds, \
filename) \
#define SINGLE_INPUT_SINGLE_OUTPUT_PERF_EX(T, FuncA, FuncB, rounds, filename) \
{ \
LIBC_NAMESPACE::testing::SingleInputSingleOutputPerf<T>::runPerf( \
&myFunc, &otherFunc, rounds, filename); \
&FuncA, &FuncB, rounds, #FuncA, #FuncB, filename); \
}
Loading