Skip to content

[llvm-exegesis] Add support for pinning benchmarking process to a CPU #85168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

boomanaiden154
Copy link
Contributor

This patch adds in support for pinning a benchmarking process to a specific CPU (in the subprocess benchmarking mode on Linux). This is intended to be used in environments where a certain set of CPUs is isolated from the scheduler using something like cgroups and thus should present less potential for noise than normal. This also opens up the door for doing multithreaded benchmarking as we can now pin benchmarking processes to specific CPUs that we know won't interfere with each other.

This patch adds in support for pinning a benchmarking process to a
specific CPU (in the subprocess benchmarking mode on Linux). This is
intended to be used in environments where a certain set of CPUs is
isolated from the scheduler using something like cgroups and thus should
present less potential for noise than normal. This also opens up the
door for doing multithreaded benchmarking as we can now pin benchmarking
processes to specific CPUs that we know won't interfere with each other.
@llvmbot
Copy link
Member

llvmbot commented Mar 14, 2024

@llvm/pr-subscribers-tools-llvm-exegesis

Author: Aiden Grossman (boomanaiden154)

Changes

This patch adds in support for pinning a benchmarking process to a specific CPU (in the subprocess benchmarking mode on Linux). This is intended to be used in environments where a certain set of CPUs is isolated from the scheduler using something like cgroups and thus should present less potential for noise than normal. This also opens up the door for doing multithreaded benchmarking as we can now pin benchmarking processes to specific CPUs that we know won't interfere with each other.


Full diff: https://github.com/llvm/llvm-project/pull/85168.diff

5 Files Affected:

  • (added) llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning-execution-mode.s (+5)
  • (added) llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning.s (+5)
  • (modified) llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (+51-15)
  • (modified) llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h (+4-2)
  • (modified) llvm/tools/llvm-exegesis/llvm-exegesis.cpp (+13-1)
diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning-execution-mode.s b/llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning-execution-mode.s
new file mode 100644
index 00000000000000..62a7b1d1e486e1
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning-execution-mode.s
@@ -0,0 +1,5 @@
+# REQUIRES: exegesis-can-measure-latency, x86_64-linux
+
+# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -opcode-name=ADD64rr -execution-mode=inprocess --benchmark-process-cpu=0 2>&1 | FileCheck %s
+
+# CHECK: llvm-exegesis error: --benchmark-process-cpu is only supported in the subprocess execution mode
diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning.s b/llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning.s
new file mode 100644
index 00000000000000..0ea3752fc3bb95
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/cpu-pinning.s
@@ -0,0 +1,5 @@
+# REQUIRES: exegesis-can-measure-latency, x86_64-linux
+
+# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -opcode-name=ADD64rr -execution-mode=subprocess | FileCheck %s
+
+# CHECK: - { key: latency, value: {{[0-9.]*}}, per_snippet_value: {{[0-9.]*}}
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 4e97d188d17259..9c5a037ee2e67d 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -97,7 +97,8 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
 public:
   static Expected<std::unique_ptr<InProcessFunctionExecutorImpl>>
   create(const LLVMState &State, object::OwningBinary<object::ObjectFile> Obj,
-         BenchmarkRunner::ScratchSpace *Scratch) {
+         BenchmarkRunner::ScratchSpace *Scratch,
+         std::optional<int> BenchmarkProcessCPU) {
     Expected<ExecutableFunction> EF =
         ExecutableFunction::create(State.createTargetMachine(), std::move(Obj));
 
@@ -105,14 +106,17 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
       return EF.takeError();
 
     return std::unique_ptr<InProcessFunctionExecutorImpl>(
-        new InProcessFunctionExecutorImpl(State, std::move(*EF), Scratch));
+        new InProcessFunctionExecutorImpl(State, std::move(*EF), Scratch,
+                                          BenchmarkProcessCPU));
   }
 
 private:
   InProcessFunctionExecutorImpl(const LLVMState &State,
                                 ExecutableFunction Function,
-                                BenchmarkRunner::ScratchSpace *Scratch)
-      : State(State), Function(std::move(Function)), Scratch(Scratch) {}
+                                BenchmarkRunner::ScratchSpace *Scratch,
+                                std::optional<int> BenchmarkCPU)
+      : State(State), Function(std::move(Function)), Scratch(Scratch),
+        BenchmarkProcessCPU(BenchmarkCPU) {}
 
   static void accumulateCounterValues(const SmallVector<int64_t, 4> &NewValues,
                                       SmallVector<int64_t, 4> *Result) {
@@ -175,6 +179,7 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
   const LLVMState &State;
   const ExecutableFunction Function;
   BenchmarkRunner::ScratchSpace *const Scratch;
+  const std::optional<int> BenchmarkProcessCPU;
 };
 
 #ifdef __linux__
@@ -189,27 +194,31 @@ class SubProcessFunctionExecutorImpl
 public:
   static Expected<std::unique_ptr<SubProcessFunctionExecutorImpl>>
   create(const LLVMState &State, object::OwningBinary<object::ObjectFile> Obj,
-         const BenchmarkKey &Key) {
+         const BenchmarkKey &Key, std::optional<int> BenchmarkProcessCPU) {
     Expected<ExecutableFunction> EF =
         ExecutableFunction::create(State.createTargetMachine(), std::move(Obj));
     if (!EF)
       return EF.takeError();
 
     return std::unique_ptr<SubProcessFunctionExecutorImpl>(
-        new SubProcessFunctionExecutorImpl(State, std::move(*EF), Key));
+        new SubProcessFunctionExecutorImpl(State, std::move(*EF), Key,
+                                           BenchmarkProcessCPU));
   }
 
 private:
   SubProcessFunctionExecutorImpl(const LLVMState &State,
                                  ExecutableFunction Function,
-                                 const BenchmarkKey &Key)
-      : State(State), Function(std::move(Function)), Key(Key) {}
+                                 const BenchmarkKey &Key,
+                                 std::optional<int> BenchmarkCPU)
+      : State(State), Function(std::move(Function)), Key(Key),
+        BenchmarkProcessCPU(BenchmarkCPU) {}
 
   enum ChildProcessExitCodeE {
     CounterFDReadFailed = 1,
     RSeqDisableFailed,
     FunctionDataMappingFailed,
-    AuxiliaryMemorySetupFailed
+    AuxiliaryMemorySetupFailed,
+    SetCPUAffinityFailed
   };
 
   StringRef childProcessExitCodeToString(int ExitCode) const {
@@ -222,6 +231,8 @@ class SubProcessFunctionExecutorImpl
       return "Failed to map memory for assembled snippet";
     case ChildProcessExitCodeE::AuxiliaryMemorySetupFailed:
       return "Failed to setup auxiliary memory";
+    case ChildProcessExitCodeE::SetCPUAffinityFailed:
+      return "Failed to set CPU affinity of the benchmarking process";
     default:
       return "Child process returned with unknown exit code";
     }
@@ -310,6 +321,29 @@ class SubProcessFunctionExecutorImpl
     }
 
     if (ParentOrChildPID == 0) {
+      if (BenchmarkProcessCPU) {
+        // Set the CPU affinity for the child process, so that we ensure that if
+        // the user specified a CPU the process should run on, the benchmarking
+        // process is running on that CPU.
+        cpu_set_t CPUMask;
+        CPU_ZERO(&CPUMask);
+        CPU_SET(*BenchmarkProcessCPU, &CPUMask);
+        // TODO(boomanaiden154): Rewrite this to use LLVM primitives once they
+        // are available.
+        int SetAffinityReturn = sched_setaffinity(0, sizeof(CPUMask), &CPUMask);
+        if (SetAffinityReturn == -1) {
+          exit(ChildProcessExitCodeE::SetCPUAffinityFailed);
+        }
+
+        // Check (if assertions are enabled) that we are actually running on the
+        // CPU that was specified by the user.
+        unsigned int CurrentCPU;
+        assert(getcpu(&CurrentCPU, nullptr) == 0 &&
+               "Expected getcpu call to succeed.");
+        assert(static_cast<int>(CurrentCPU) == *BenchmarkProcessCPU &&
+               "Expected current CPU to equal the CPU requested by the user");
+      }
+
       // We are in the child process, close the write end of the pipe.
       close(PipeFiles[1]);
       // Unregister handlers, signal handling is now handled through ptrace in
@@ -500,6 +534,7 @@ class SubProcessFunctionExecutorImpl
   const LLVMState &State;
   const ExecutableFunction Function;
   const BenchmarkKey &Key;
+  const std::optional<int> BenchmarkProcessCPU;
 };
 #endif // __linux__
 } // namespace
@@ -577,11 +612,11 @@ BenchmarkRunner::getRunnableConfiguration(
 Expected<std::unique_ptr<BenchmarkRunner::FunctionExecutor>>
 BenchmarkRunner::createFunctionExecutor(
     object::OwningBinary<object::ObjectFile> ObjectFile,
-    const BenchmarkKey &Key) const {
+    const BenchmarkKey &Key, std::optional<int> BenchmarkProcessCPU) const {
   switch (ExecutionMode) {
   case ExecutionModeE::InProcess: {
     auto InProcessExecutorOrErr = InProcessFunctionExecutorImpl::create(
-        State, std::move(ObjectFile), Scratch.get());
+        State, std::move(ObjectFile), Scratch.get(), BenchmarkProcessCPU);
     if (!InProcessExecutorOrErr)
       return InProcessExecutorOrErr.takeError();
 
@@ -590,7 +625,7 @@ BenchmarkRunner::createFunctionExecutor(
   case ExecutionModeE::SubProcess: {
 #ifdef __linux__
     auto SubProcessExecutorOrErr = SubProcessFunctionExecutorImpl::create(
-        State, std::move(ObjectFile), Key);
+        State, std::move(ObjectFile), Key, BenchmarkProcessCPU);
     if (!SubProcessExecutorOrErr)
       return SubProcessExecutorOrErr.takeError();
 
@@ -605,8 +640,8 @@ BenchmarkRunner::createFunctionExecutor(
 }
 
 std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
-    RunnableConfiguration &&RC,
-    const std::optional<StringRef> &DumpFile) const {
+    RunnableConfiguration &&RC, const std::optional<StringRef> &DumpFile,
+    std::optional<int> BenchmarkProcessCPU) const {
   Benchmark &BenchmarkResult = RC.BenchmarkResult;
   object::OwningBinary<object::ObjectFile> &ObjectFile = RC.ObjectFile;
 
@@ -627,7 +662,8 @@ std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
   }
 
   Expected<std::unique_ptr<BenchmarkRunner::FunctionExecutor>> Executor =
-      createFunctionExecutor(std::move(ObjectFile), RC.BenchmarkResult.Key);
+      createFunctionExecutor(std::move(ObjectFile), RC.BenchmarkResult.Key,
+                             BenchmarkProcessCPU);
   if (!Executor)
     return {Executor.takeError(), std::move(BenchmarkResult)};
   auto NewMeasurements = runMeasurements(**Executor);
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
index 9b4bb1d41149fe..e688b814d1c83d 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
@@ -68,7 +68,8 @@ class BenchmarkRunner {
 
   std::pair<Error, Benchmark>
   runConfiguration(RunnableConfiguration &&RC,
-                   const std::optional<StringRef> &DumpFile) const;
+                   const std::optional<StringRef> &DumpFile,
+                   std::optional<int> BenchmarkProcessCPU) const;
 
   // Scratch space to run instructions that touch memory.
   struct ScratchSpace {
@@ -135,7 +136,8 @@ class BenchmarkRunner {
 
   Expected<std::unique_ptr<FunctionExecutor>>
   createFunctionExecutor(object::OwningBinary<object::ObjectFile> Obj,
-                         const BenchmarkKey &Key) const;
+                         const BenchmarkKey &Key,
+                         std::optional<int> BenchmarkProcessCPU) const;
 };
 
 } // namespace exegesis
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 1ae2565e894c69..3e0d75faaeb341 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -269,6 +269,11 @@ static cl::list<ValidationEvent> ValidationCounters(
         "counter to validate benchmarking assumptions"),
     cl::CommaSeparated, cl::cat(BenchmarkOptions), ValidationEventOptions());
 
+static cl::opt<int> BenchmarkProcessCPU(
+    "benchmark-process-cpu",
+    cl::desc("The CPU number that the benchmarking process should executon on"),
+    cl::cat(BenchmarkOptions), cl::init(-1));
+
 static ExitOnError ExitOnErr("llvm-exegesis error: ");
 
 // Helper function that logs the error(s) and exits.
@@ -418,8 +423,15 @@ static void runBenchmarkConfigurations(
         std::optional<StringRef> DumpFile;
         if (DumpObjectToDisk.getNumOccurrences())
           DumpFile = DumpObjectToDisk;
+        std::optional<int> BenchmarkCPU = std::nullopt;
+        if (BenchmarkProcessCPU != -1) {
+          if (ExecutionMode != BenchmarkRunner::ExecutionModeE::SubProcess)
+            ExitWithError("--benchmark-process-cpu is only supported in the "
+                          "subprocess execution mode");
+          BenchmarkCPU = BenchmarkProcessCPU;
+        }
         auto [Err, BenchmarkResult] =
-            Runner.runConfiguration(std::move(RC), DumpFile);
+            Runner.runConfiguration(std::move(RC), DumpFile, BenchmarkCPU);
         if (Err) {
           // Errors from executing the snippets are fine.
           // All other errors are a framework issue and should fail.

@boomanaiden154
Copy link
Contributor Author

@legrosbuffle bump on this when you get a chance. Thanks!

@legrosbuffle
Copy link
Contributor

Why can't we use taskset llvm-exegesis ... ? On linux I think chidren inherit the affinity of the parent.

@boomanaiden154
Copy link
Contributor Author

Right, the child will inherit the affinity of the parent, but we don't want the child to have the same affinity as the parent. The main llvm-exegesis process isn't sensitive to the core at all, just running things like the assembler, so doesn't need special affinity. When pinning to a single core that has been set aside using something like isolcpu or cgroups, pinning both the main llvm-exegesis process and the benchmarking process to the same core will require the scheduler to swap them in and out a couple times, which isn't what is desired. This approach only puts the benchmarking subprocess on a specific core to prevent this issue, at the cost of some complexity.

@legrosbuffle
Copy link
Contributor

both the main llvm-exegesis process and the benchmarking process to the same core will require the scheduler to swap them in and out a couple times, which isn't what is desired.

Is this happening in practice, and does it make a significant difference on the output ?

@boomanaiden154
Copy link
Contributor Author

Is this happening in practice, and does it make a significant difference on the output ?

Yes, at least if the system is doing other things/isn't quiet. The source of #80957 from what I can tell is that the benchmarking process gets swapped in and out, changing the values enough that there is a reasonable probability the reported result is negative. This patch won't fix that issue, but does prevent any potential interference from other processes.

@boomanaiden154 boomanaiden154 merged commit 9886788 into llvm:main Sep 19, 2024
5 of 7 checks passed
@boomanaiden154 boomanaiden154 deleted the exegesis-benchmarking-set-cpu branch September 19, 2024 13:34
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 19, 2024

LLVM Buildbot has detected a new failure on builder ppc64le-flang-rhel-clang running on ppc64le-flang-rhel-test while building llvm at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/157/builds/8166

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
80.614 [215/35/6310] Linking CXX static library lib/libLLVMOrcDebugging.a
80.627 [214/35/6311] Linking CXX static library lib/libclangToolingInclusions.a
80.633 [213/35/6312] Linking CXX executable bin/f18-parse-demo
80.905 [213/34/6313] Linking CXX static library lib/libclangAnalysis.a
80.946 [211/35/6314] Linking CXX executable bin/apinotes-test
80.949 [211/34/6315] Linking CXX static library lib/libclangFormat.a
80.956 [210/34/6316] Linking CXX static library lib/libMLIRNVVMTarget.a
80.958 [210/33/6317] Linking CXX static library lib/libclangDynamicASTMatchers.a
80.980 [210/32/6318] Linking CXX static library lib/libMLIRROCDLTarget.a
81.071 [209/32/6319] Building CXX object tools/llvm-exegesis/lib/CMakeFiles/LLVMExegesis.dir/BenchmarkRunner.cpp.o
FAILED: tools/llvm-exegesis/lib/CMakeFiles/LLVMExegesis.dir/BenchmarkRunner.cpp.o 
ccache /home/buildbots/llvm-external-buildbots/clang.16.0.1/bin/clang++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/build/tools/llvm-exegesis/lib -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/llvm-project/llvm/tools/llvm-exegesis/lib -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/build/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/llvm-project/llvm/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/llvm-exegesis/lib/CMakeFiles/LLVMExegesis.dir/BenchmarkRunner.cpp.o -MF tools/llvm-exegesis/lib/CMakeFiles/LLVMExegesis.dir/BenchmarkRunner.cpp.o.d -o tools/llvm-exegesis/lib/CMakeFiles/LLVMExegesis.dir/BenchmarkRunner.cpp.o -c /home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
/home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp:411:12: error: use of undeclared identifier 'getcpu'; did you mean 'getcwd'?
    assert(getcpu(&CurrentCPU, nullptr) == 0 &&
           ^~~~~~
           getcwd
/usr/include/assert.h:90:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^
/usr/include/unistd.h:511:14: note: 'getcwd' declared here
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
             ^
/home/buildbots/llvm-external-buildbots/workers/ppc64le-flang-rhel-test/ppc64le-flang-rhel-clang-build/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp:411:19: error: cannot initialize a parameter of type 'char *' with an rvalue of type 'unsigned int *'
    assert(getcpu(&CurrentCPU, nullptr) == 0 &&
                  ^~~~~~~~~~~
/usr/include/assert.h:90:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^~~~
/usr/include/unistd.h:511:28: note: passing argument to parameter '__buf' here
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
                           ^
2 errors generated.
81.174 [209/31/6320] Linking CXX executable bin/llvm-cgdata
81.213 [209/30/6321] Linking CXX static library lib/libclangAnalysisFlowSensitive.a
81.364 [209/29/6322] Linking CXX static library lib/libMLIRGPUTransforms.a
81.438 [209/28/6323] Linking CXX executable tools/flang/unittests/Evaluate/integer.test
81.474 [209/27/6324] Linking CXX static library lib/libclangSema.a
81.557 [209/26/6325] Linking CXX executable tools/flang/unittests/Evaluate/logical.test
81.861 [209/25/6326] Linking CXX executable bin/lli-child-target
81.907 [209/24/6327] Linking CXX executable tools/flang/unittests/Evaluate/real.test
82.271 [209/23/6328] Building CXX object tools/llvm-exegesis/lib/PowerPC/CMakeFiles/LLVMExegesisPowerPC.dir/Target.cpp.o
82.402 [209/22/6329] Linking CXX executable bin/llvm-link
82.421 [209/21/6330] Linking CXX executable bin/clang-offload-bundler
82.635 [209/20/6331] Linking CXX executable bin/clang-format
82.772 [209/19/6332] Linking CXX executable bin/llvm-profgen
82.858 [209/18/6333] Linking CXX executable tools/flang/unittests/Evaluate/expression.test
82.995 [209/17/6334] Linking CXX executable tools/flang/unittests/Evaluate/folding.test
83.499 [209/16/6335] Building CXX object tools/llvm-exegesis/lib/CMakeFiles/LLVMExegesis.dir/ParallelSnippetGenerator.cpp.o
83.719 [209/15/6336] Linking CXX executable bin/llvm-jitlink

boomanaiden154 added a commit that referenced this pull request Sep 19, 2024
…to a CPU (#85168)"

This reverts commit 9886788.

This was breaking builds on ppc64 and AIX. Pulling so I have time to
investigate.
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
…llvm#85168)

This patch adds in support for pinning a benchmarking process to a
specific CPU (in the subprocess benchmarking mode on Linux). This is
intended to be used in environments where a certain set of CPUs is
isolated from the scheduler using something like cgroups and thus should
present less potential for noise than normal. This also opens up the
door for doing multithreaded benchmarking as we can now pin benchmarking
processes to specific CPUs that we know won't interfere with each other.
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
…to a CPU (llvm#85168)"

This reverts commit 9886788.

This was breaking builds on ppc64 and AIX. Pulling so I have time to
investigate.
boomanaiden154 added a commit that referenced this pull request Sep 23, 2024
…to a CPU (#85168)"

This reverts commit 5e3d48a.

This relands commit 9886788.

This was originally causing build failures on more esoteric platforms
that have different definitions of getcpu. This is only intended to be
supported on x86-64 currently, so just use preprocessor definitions to
special case the function.
@jplehr
Copy link
Contributor

jplehr commented Sep 23, 2024

I believe this broke on of our buildbots: https://lab.llvm.org/staging/#/builders/130/builds/4873

edit: If you need help in looking more into this, please let me know.

@mikaelholmen
Copy link
Collaborator

This patch broke trunk for me.
I compile on a RHEL8 machine with clang 15.0.5 and I get

../tools/llvm-exegesis/lib/BenchmarkRunner.cpp:416:12: error: use of undeclared identifier 'getcpu'; did you mean 'getcwd'?
    assert(getcpu(&CurrentCPU, nullptr) == 0 &&
           ^~~~~~
           getcwd
/usr/include/assert.h:90:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^
/usr/include/unistd.h:511:14: note: 'getcwd' declared here
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
             ^
../tools/llvm-exegesis/lib/BenchmarkRunner.cpp:416:19: error: cannot initialize a parameter of type 'char *' with an rvalue of type 'unsigned int *'
    assert(getcpu(&CurrentCPU, nullptr) == 0 &&
                  ^~~~~~~~~~~
/usr/include/assert.h:90:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^~~~
/usr/include/unistd.h:511:28: note: passing argument to parameter '__buf' here
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
                           ^
2 errors generated.

Similar to the buildbot failure in the previous comment.

@steelannelida
Copy link

steelannelida commented Sep 23, 2024

This patch broke trunk for me. I compile on a RHEL8 machine with clang 15.0.5 and I get

../tools/llvm-exegesis/lib/BenchmarkRunner.cpp:416:12: error: use of undeclared identifier 'getcpu'; did you mean 'getcwd'?
    assert(getcpu(&CurrentCPU, nullptr) == 0 &&
           ^~~~~~
           getcwd
/usr/include/assert.h:90:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^
/usr/include/unistd.h:511:14: note: 'getcwd' declared here
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
             ^
../tools/llvm-exegesis/lib/BenchmarkRunner.cpp:416:19: error: cannot initialize a parameter of type 'char *' with an rvalue of type 'unsigned int *'
    assert(getcpu(&CurrentCPU, nullptr) == 0 &&
                  ^~~~~~~~~~~
/usr/include/assert.h:90:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^~~~
/usr/include/unistd.h:511:28: note: passing argument to parameter '__buf' here
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
                           ^
2 errors generated.

Similar to the buildbot failure in the previous comment.

We get the same error in our setup; Would you mind if we revert the change?

boomanaiden154 added a commit that referenced this pull request Sep 23, 2024
…to a CPU (#85168)"

This reverts commit 6fc2451.

This broke some more buildbots.
@boomanaiden154
Copy link
Contributor Author

I've reverted this for now.

@boomanaiden154
Copy link
Contributor Author

Looks like getcpu support was only added in glibc >=2.29.

boomanaiden154 added a commit to boomanaiden154/llvm-project that referenced this pull request Sep 23, 2024
…to a CPU (llvm#85168)"

This reverts commit 2cd20c2.

This relands commit 9886788.

This was causing more buildbot failures due to getcpu not being
available with glibc <=2.29. This patch fixes that by directly making
the syscall, assuming the syscall number macro is available.
boomanaiden154 added a commit that referenced this pull request Sep 23, 2024
…to a CPU (#85168)" (#109688)

This reverts commit 2cd20c2.

This relands commit 9886788.

This was causing more buildbot failures due to getcpu not being
available with glibc <=2.29. This patch fixes that by directly making
the syscall, assuming the syscall number macro is available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants