Skip to content

Commit 4474299

Browse files
committed
Honor CPU affinity in ThreadPool::getNumCores
This reports that number of CPUs that are actually usable by the current process. This means that I can do something like `taskset -c 0 emcc hello.c -O2` and the internal call to `wasm-opt` within emcc will only use a single core. Ideally this would work on macOS and windows too, but I'm not even sure how easy it is to control affinity on those OSes.
1 parent 36366d2 commit 4474299

File tree

5 files changed

+43
-2
lines changed

5 files changed

+43
-2
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ jobs:
239239
- name: install packages
240240
run: |
241241
./alpine.sh apk update
242-
./alpine.sh apk add build-base cmake git python3 py3-pip clang ninja
242+
./alpine.sh apk add build-base cmake git python3 py3-pip clang ninja util-linux
243243
244244
- name: avoid d8 tests (jsvu is not compatible with alpine)
245245
run: |

.github/workflows/create_release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ jobs:
135135
- name: install packages
136136
run: |
137137
./alpine.sh apk update
138-
./alpine.sh apk add build-base cmake git python3 clang ninja py3-pip
138+
./alpine.sh apk add build-base cmake git python3 py3-pip clang ninja util-linux
139139
140140
- name: avoid d8 tests (jsvu is not compatible with alpine)
141141
run: |

src/support/threads.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,21 @@
2020
#include <iostream>
2121
#include <string>
2222

23+
#ifdef __linux__
24+
#include <sched.h> // For sched_getaffinity
25+
#endif
26+
2327
#include "compiler-support.h"
28+
#include "support/debug.h"
2429
#include "threads.h"
2530
#include "utilities.h"
2631

2732
// debugging tools
2833

34+
// DEBUG_TYPE is for BYN_TRACE macro. This tracing can be enabled at runtime
35+
#define DEBUG_TYPE "threads"
36+
37+
// BINARYEN_THREAD_DEBUG is a build-time setting for detailed thread tracing
2938
#ifdef BINARYEN_THREAD_DEBUG
3039
static std::mutex debug;
3140
#define DEBUG_THREAD(x) \
@@ -145,9 +154,24 @@ size_t ThreadPool::getNumCores() {
145154
return 1;
146155
#else
147156
size_t num = std::max(1U, std::thread::hardware_concurrency());
157+
#ifdef __linux__
158+
// On linux we can do better since we can get the number of CPU that are
159+
// actually usable by the current process.
160+
cpu_set_t cpu_set;
161+
CPU_ZERO(&cpu_set);
162+
if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0) {
163+
num = 0;
164+
for (int i = 0; i < CPU_SETSIZE; i++) {
165+
if (CPU_ISSET(i, &cpu_set)) {
166+
num++;
167+
}
168+
}
169+
}
170+
#endif
148171
if (getenv("BINARYEN_CORES")) {
149172
num = std::stoi(getenv("BINARYEN_CORES"));
150173
}
174+
BYN_TRACE("getNumCores: " << num << "\n");
151175
return num;
152176
#endif
153177
}

test/lit/lit.cfg.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import sys
23
import lit.formats
34

45
config.name = "Binaryen lit tests"
@@ -26,6 +27,9 @@
2627
python = sys.executable.replace('\\', '/')
2728
config.substitutions.append((tool, python + ' ' + tool_file))
2829

30+
if 'linux' in sys.platform:
31+
config.available_features.add('linux')
32+
2933
# Finds the given executable 'program' in PATH.
3034
# Operates like the Unix tool 'which'.
3135
# This is similar to script/test/shared.py, but does not use binaryen_root, and

test/lit/num_cores.wast

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
;; REQUIRES: linux
2+
;; Test that getNumCores honors thread affinity on linux
3+
4+
(module
5+
(func $a)
6+
)
7+
8+
;; RUN: taskset -c 0 wasm-opt -O1 --debug=threads %s 2>&1 | filecheck %s
9+
;; RUN: taskset -c 0,2 wasm-opt -O1 --debug=threads %s 2>&1 | filecheck %s --check-prefix=TWO
10+
11+
;; CHECK: getNumCores: 1
12+
13+
;; TWO: getNumCores: 2

0 commit comments

Comments
 (0)