Skip to content

Commit 3775e64

Browse files
committed
Cap pytest-xdist's auto worker count to the container CPU limit
`auto` prefers psutil.cpu_count(), which reports the machine's cores and sees neither a cpuset nor a CFS quota, so on an 8 vCPU OSDC pod it created 64 workers and got test-arm-backend-no-driver OOMKilled. pytest-parallelism.sh exports PYTEST_XDIST_AUTO_NUM_WORKERS, which xdist checks ahead of psutil, set to the smaller of the cgroup CPU quota and nproc. nproc is what pytorch relies on for OMP_NUM_THREADS on the same fleet (.ci/pytorch/test.sh, USE_ARC block), whose comment says ARC pods carry a real cpuset; the quota covers the case where the limit is expressed that way instead, as pytorch documents for their nested-container ROCm fleet. Taking the smaller needs no assumption about which is in play, and both fall back to the machine count off OSDC, so this is a no-op elsewhere. Sourced from the three scripts that run pytest with `auto`. pytorch avoids the problem differently, by never using `auto` -- NUM_PROCS in tools/testing/test_selections.py is a hardcoded 1-3. Authored with Claude Code.
1 parent 6706cc5 commit 3775e64

4 files changed

Lines changed: 49 additions & 0 deletions

File tree

.ci/scripts/pytest-parallelism.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
# Pin pytest-xdist's `auto` worker count. `auto` prefers psutil.cpu_count(),
9+
# which reports the machine's cores and sees neither a cpuset nor a CFS quota,
10+
# so on a container it fans out far past the CPU limit and the workers exhaust
11+
# the memory limit. Take the smaller of the cgroup quota and nproc, so it holds
12+
# whichever way the limit is expressed.
13+
14+
pytest_num_workers() {
15+
local affinity quota period
16+
affinity=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1)
17+
18+
quota=""
19+
if [[ -r /sys/fs/cgroup/cpu.max ]]; then # cgroup v2
20+
read -r quota period < /sys/fs/cgroup/cpu.max
21+
[[ "${quota}" == "max" ]] && quota=""
22+
elif [[ -r /sys/fs/cgroup/cpu/cpu.cfs_quota_us ]]; then # cgroup v1
23+
quota=$(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)
24+
period=$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us)
25+
(( quota <= 0 )) && quota=""
26+
fi
27+
28+
if [[ -n "${quota}" ]] && (( period > 0 )); then
29+
local from_quota=$(( quota / period ))
30+
(( from_quota > 0 && from_quota < affinity )) && affinity="${from_quota}"
31+
fi
32+
33+
(( affinity < 1 )) && affinity=1
34+
echo "${affinity}"
35+
}
36+
37+
if [[ -z "${PYTEST_XDIST_AUTO_NUM_WORKERS:-}" ]]; then
38+
export PYTEST_XDIST_AUTO_NUM_WORKERS="$(pytest_num_workers)"
39+
echo "PYTEST_XDIST_AUTO_NUM_WORKERS=${PYTEST_XDIST_AUTO_NUM_WORKERS}"
40+
fi

.ci/scripts/test_backend.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# LICENSE file in the root directory of this source tree.
88
set -eux
99

10+
# Cap pytest-xdist's `auto` workers to the container's CPU quota.
11+
source .ci/scripts/pytest-parallelism.sh
12+
1013
SUITE=$1
1114
FLOW=$2
1215
ARTIFACT_DIR=$3

.ci/scripts/unittest-linux-cmake.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# LICENSE file in the root directory of this source tree.
88
set -eux
99

10+
# Cap pytest-xdist's `auto` workers to the container's CPU quota.
11+
source .ci/scripts/pytest-parallelism.sh
12+
1013
# Some ARM/TOSA-adjacent tests import modules that require tosa_serializer.
1114
# Install from a local tosa-tools checkout when available. If absent in this
1215
# checkout layout, clone the pinned upstream tag and install from there.

backends/arm/test/test_arm_backend.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd)
1212
et_root_dir=$(cd ${script_dir}/../../.. && pwd)
1313
cd "${et_root_dir}"
1414
pwd
15+
16+
# Cap pytest-xdist's `auto` workers to the container's CPU quota.
17+
source .ci/scripts/pytest-parallelism.sh
1518
scratch_dir=${et_root_dir}/examples/arm/arm-scratch
1619
setup_path_script=${scratch_dir}/setup_path.sh
1720
_setup_msg="please refer to ${et_root_dir}/examples/arm/setup.sh to properly install necessary tools."

0 commit comments

Comments
 (0)