Property PROCESSOR_AFFINITY has no effect

I’m running a large test suite for a project that gets a significant performance benefit from CPU pinning. Currently we disable this feature in our test suite, since otherwise parallel tests would try to pin to the same CPUs.

I recently came across the PROCESSOR_AFFINITY property, which seems like it should solve this problem for us (our software checks its starting affinity and only pins to CPUs in that set). However, when I use it, it appears to have no effect.

Here is a small test I wrote that just uses the taskset command-line utility to report its own CPU affinity. Below I’d expect the two versions with PROCESSOR_AFFINITY set to get distinct affinity masks with 1 bit set in each, and the one without it set to get 0xfff. Instead, they all get 0xfff.

add_test(NAME taskset-affinity1 COMMAND sh -c "taskset -p $$")
set_property(TEST taskset-affinity1 PROPERTY PROCESSOR_AFFINITY True)

add_test(NAME taskset-affinity2 COMMAND sh -c "taskset -p $$")
set_property(TEST taskset-affinity2 PROPERTY PROCESSOR_AFFINITY True)

add_test(NAME taskset-noaffinity COMMAND sh -c "taskset -p $$")

Output:

$ ctest -j12 --verbose -R taskset
UpdateCTestConfiguration  from :/home/jnewsome/projects/shadow/dev/build/DartConfiguration.tcl
UpdateCTestConfiguration  from :/home/jnewsome/projects/shadow/dev/build/DartConfiguration.tcl
Test project /home/jnewsome/projects/shadow/dev/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 103
    Start 103: taskset-noaffinity

103: Test command: /usr/bin/sh "-c" "taskset -p $$"
103: Test timeout computed to be: 10000000
test 101
    Start 101: taskset-affinity1

101: Test command: /usr/bin/sh "-c" "taskset -p $$"
101: Test timeout computed to be: 10000000
test 102
    Start 102: taskset-affinity2

102: Test command: /usr/bin/sh "-c" "taskset -p $$"
102: Test timeout computed to be: 10000000
103: pid 370645's current affinity mask: fff
101: pid 370647's current affinity mask: fff
1/3 Test #103: taskset-noaffinity ...............   Passed    0.00 sec
2/3 Test #101: taskset-affinity1 ................   Passed    0.00 sec
102: pid 370649's current affinity mask: fff
3/3 Test #102: taskset-affinity2 ................   Passed    0.00 sec

The following tests passed:
	taskset-noaffinity
	taskset-affinity1
	taskset-affinity2

100% tests passed, 0 tests failed out of 3

I’m using CMake version 3.16.3 on Ubuntu 20.04.3

on Ubuntu 20.04.3

The package is likely built against their libuv package, which is an upstream libuv 1.x version. That doesn’t have the extensions to libuv needed to set processor affinity. We’ve contributed the changes to libuv, but they preferred to accept them only in the development branch that will eventually be libuv 2.x.

The PROCESSOR_AFFINITY documentation could be clearer about this, but it does say:

If enabled and supported for the current platform, …

If you use one of the official binaries from cmake.org, they are built with the patched libuv needed to support PROCESSOR_AFFINITY.

Is there a way to test from within CMake whether PROCESSOR_AFFINITY is supported in the current build of CMake? That’d at least let us enable cpu pinning in our tests on platforms that support it.

Not currently. I’d welcome a merge request to add this information to the output of cmake -E capabilities.

Ok, I’ll see if I can take a look. Thanks for the help!