[libc-commits] [libc] 8d64ed8 - [libc] Generate one benchmark per implementation
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Thu Jun 17 05:18:11 PDT 2021
Author: Guillaume Chatelet
Date: 2021-06-17T12:14:10Z
New Revision: 8d64ed854449467a3a5fc4450c71a4525a24c4be
URL: https://github.com/llvm/llvm-project/commit/8d64ed854449467a3a5fc4450c71a4525a24c4be
DIFF: https://github.com/llvm/llvm-project/commit/8d64ed854449467a3a5fc4450c71a4525a24c4be.diff
LOG: [libc] Generate one benchmark per implementation
We now generate as many benchmarks as there are implementations.
Differential Revision: https://reviews.llvm.org/D102156
Added:
Modified:
libc/benchmarks/CMakeLists.txt
libc/benchmarks/LibcMemoryBenchmarkMain.cpp
Removed:
################################################################################
diff --git a/libc/benchmarks/CMakeLists.txt b/libc/benchmarks/CMakeLists.txt
index 80ff7818c916c..feff80cf45010 100644
--- a/libc/benchmarks/CMakeLists.txt
+++ b/libc/benchmarks/CMakeLists.txt
@@ -145,11 +145,27 @@ add_libc_benchmark_unittest(json-test
# Benchmarking tool
#==============================================================================
-add_executable(libc-benchmark-main
- EXCLUDE_FROM_ALL
- LibcMemoryBenchmarkMain.cpp
-)
-foreach(entrypoint_target libc.src.string.memcpy libc.src.string.memset)
- get_target_property(entrypoint_object_file ${entrypoint_target} "OBJECT_FILE_RAW")
- target_link_libraries(libc-benchmark-main PUBLIC json ${entrypoint_object_file})
-endforeach()
+# Benchmark all implementations that can run on the target CPU.
+function(add_libc_multi_impl_benchmark name)
+ get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations)
+ foreach(fq_config_name IN LISTS fq_implementations)
+ get_target_property(required_cpu_features ${fq_config_name} REQUIRE_CPU_FEATURES)
+ cpu_supports(can_run "${required_cpu_features}")
+ if(can_run)
+ set(benchmark_name ${fq_config_name}_benchmark)
+ add_executable(${benchmark_name}
+ EXCLUDE_FROM_ALL
+ LibcMemoryBenchmarkMain.cpp
+ )
+ get_target_property(entrypoint_object_file ${fq_config_name} "OBJECT_FILE_RAW")
+ target_link_libraries(${benchmark_name} PUBLIC json ${entrypoint_object_file})
+ string(TOUPPER ${name} name_upper)
+ target_compile_definitions(${benchmark_name} PRIVATE "-DLIBC_BENCHMARK_FUNCTION_${name_upper}=1" "-DLIBC_BENCHMARK_FUNCTION_NAME=\"${fq_config_name}\"")
+ else()
+ message(STATUS "Skipping benchmark for '${fq_config_name}' insufficient host cpu features '${required_cpu_features}'")
+ endif()
+ endforeach()
+endfunction()
+
+add_libc_multi_impl_benchmark(memcpy)
+add_libc_multi_impl_benchmark(memset)
diff --git a/libc/benchmarks/LibcMemoryBenchmarkMain.cpp b/libc/benchmarks/LibcMemoryBenchmarkMain.cpp
index 02b62bc74029a..e3d455423de29 100644
--- a/libc/benchmarks/LibcMemoryBenchmarkMain.cpp
+++ b/libc/benchmarks/LibcMemoryBenchmarkMain.cpp
@@ -27,17 +27,9 @@ extern void *memset(void *, int, size_t);
namespace llvm {
namespace libc_benchmarks {
-enum Function { memcpy, memset };
-
static cl::opt<std::string>
StudyName("study-name", cl::desc("The name for this study"), cl::Required);
-static cl::opt<Function>
- MemoryFunction("function", cl::desc("Sets the function to benchmark:"),
- cl::values(clEnumVal(memcpy, "__llvm_libc::memcpy"),
- clEnumVal(memset, "__llvm_libc::memset")),
- cl::Required);
-
static cl::opt<std::string>
SizeDistributionName("size-distribution-name",
cl::desc("The name of the distribution to use"));
@@ -75,12 +67,12 @@ struct ParameterType {
unsigned SizeBytes : 16; // max : 16 KiB - 1
};
-struct MemcpyBenchmark {
+#if defined(LIBC_BENCHMARK_FUNCTION_MEMCPY)
+struct Benchmark {
static constexpr auto GetDistributions = &getMemcpySizeDistributions;
static constexpr size_t BufferCount = 2;
- static void amend(Study &S) { S.Configuration.Function = "memcpy"; }
- MemcpyBenchmark(const size_t BufferSize)
+ Benchmark(const size_t BufferSize)
: SrcBuffer(BufferSize), DstBuffer(BufferSize) {}
inline auto functor() {
@@ -94,13 +86,12 @@ struct MemcpyBenchmark {
AlignedBuffer SrcBuffer;
AlignedBuffer DstBuffer;
};
-
-struct MemsetBenchmark {
+#elif defined(LIBC_BENCHMARK_FUNCTION_MEMSET)
+struct Benchmark {
static constexpr auto GetDistributions = &getMemsetSizeDistributions;
static constexpr size_t BufferCount = 1;
- static void amend(Study &S) { S.Configuration.Function = "memset"; }
- MemsetBenchmark(const size_t BufferSize) : DstBuffer(BufferSize) {}
+ Benchmark(const size_t BufferSize) : DstBuffer(BufferSize) {}
inline auto functor() {
return [this](ParameterType P) {
@@ -112,9 +103,11 @@ struct MemsetBenchmark {
AlignedBuffer DstBuffer;
};
+#else
+#error "Missing LIBC_BENCHMARK_FUNCTION_XXX definition"
+#endif
-template <typename Benchmark> struct Harness : Benchmark {
- using Benchmark::functor;
+struct Harness : Benchmark {
Harness(const size_t BufferSize, size_t BatchParameterCount,
std::function<unsigned()> SizeSampler,
@@ -140,11 +133,6 @@ template <typename Benchmark> struct Harness : Benchmark {
std::function<unsigned()> OffsetSampler;
};
-struct IBenchmark {
- virtual ~IBenchmark() {}
- virtual Study run() = 0;
-};
-
size_t getL1DataCacheSize() {
const std::vector<CacheInfo> &CacheInfos = HostState::get().Caches;
const auto IsL1DataCache = [](const CacheInfo &CI) {
@@ -156,7 +144,7 @@ size_t getL1DataCacheSize() {
report_fatal_error("Unable to read L1 Cache Data Size");
}
-template <typename Benchmark> struct MemfunctionBenchmark : IBenchmark {
+struct MemfunctionBenchmark {
MemfunctionBenchmark(int64_t L1Size = getL1DataCacheSize())
: AvailableSize(L1Size - L1LeftAsideBytes - ParameterStorageBytes),
BufferSize(AvailableSize / Benchmark::BufferCount),
@@ -217,12 +205,10 @@ template <typename Benchmark> struct MemfunctionBenchmark : IBenchmark {
else
SC.SizeDistributionName = SizeDistributionName;
SC.AccessAlignment = MaybeAlign(AlignedAccess);
-
- // Delegate specific flags and configuration.
- Benchmark::amend(Study);
+ SC.Function = LIBC_BENCHMARK_FUNCTION_NAME;
}
- Study run() override {
+ Study run() {
if (SweepMode)
runSweepMode();
else
@@ -280,8 +266,7 @@ template <typename Benchmark> struct MemfunctionBenchmark : IBenchmark {
void runTrials(const BenchmarkOptions &Options,
std::function<unsigned()> SizeSampler,
std::function<unsigned()> OffsetSampler) {
- Harness<Benchmark> B(BufferSize, BatchParameterCount, SizeSampler,
- OffsetSampler);
+ Harness B(BufferSize, BatchParameterCount, SizeSampler, OffsetSampler);
for (size_t i = 0; i < NumTrials; ++i) {
const BenchmarkResult Result = benchmark(Options, B, B.functor());
Study.Measurements.push_back(Result.BestGuess);
@@ -313,15 +298,6 @@ template <typename Benchmark> struct MemfunctionBenchmark : IBenchmark {
}
};
-std::unique_ptr<IBenchmark> getMemfunctionBenchmark() {
- switch (MemoryFunction) {
- case memcpy:
- return std::make_unique<MemfunctionBenchmark<MemcpyBenchmark>>();
- case memset:
- return std::make_unique<MemfunctionBenchmark<MemsetBenchmark>>();
- }
-}
-
void writeStudy(const Study &S) {
std::error_code EC;
raw_fd_ostream FOS(Output, EC);
@@ -337,8 +313,8 @@ void writeStudy(const Study &S) {
void main() {
checkRequirements();
- auto MB = getMemfunctionBenchmark();
- writeStudy(MB->run());
+ MemfunctionBenchmark MB;
+ writeStudy(MB.run());
}
} // namespace libc_benchmarks
More information about the libc-commits
mailing list