2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-01-19 16:22:11 +00:00

NUMA: pin thread to CPU via std::thread::native_handle()

- in context of #148
This commit is contained in:
Oliver Kowalke
2017-12-29 04:39:01 +01:00
parent 53eddf651f
commit 7ff5a3564b
11 changed files with 81 additions and 16 deletions

View File

@@ -173,6 +173,7 @@ memory access).
std::vector< node > topology();
void pin_thread( std::uint32_t);
void pin_thread( std::uint32_t, std::thread::native_handle_type);
}}}
@@ -275,14 +276,15 @@ system (each element represents a NUMA-node).]]
namespace fibers {
namespace numa {
void pin_thread( std::uint32_t);
void pin_thread( std::uint32_t cpu_id);
void pin_thread( std::uint32_t cpu_id, std::thread::native_handle_type h);
}}}
[variablelist
[[Effects:] [Pins `this thread` to the logical cpu with ID `cpu_id`, e.g.
the operating system scheduler will not migrate the thread to another
logical cpu.]]
[[Effects:] [First version pins `this thread` to the logical cpu with ID `cpu_id`, e.g.
the operating system scheduler will not migrate the thread to another logical cpu.
The second variant pins the thread with the native ID `h` to logical cpu with ID `cpu_id`.]]
[[Throws:] [`system_error`]]
]

View File

@@ -8,6 +8,7 @@
#define BOOST_FIBERS_NUMA_PIN_THREAD_H
#include <cstdint>
#include <thread>
#include <boost/config.hpp>
@@ -22,7 +23,10 @@ namespace fibers {
namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t);
void pin_thread( std::uint32_t, std::thread::native_handle_type);
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid);
}}}

View File

@@ -24,7 +24,12 @@ namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid) {
if ( BOOST_UNLIKELY( -1 == ::bindprocessor( BINDTHREAD, ::thread_self(), static_cast< cpu_t >( cpuid) ) ) ) {
pin_thread( cpuid, ::thread_self() );
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
if ( BOOST_UNLIKELY( -1 == ::bindprocessor( BINDTHREAD, h, static_cast< cpu_t >( cpuid) ) ) ) {
throw std::system_error(
std::error_code( errno, std::system_category() ),
"bindprocessor() failed");

View File

@@ -10,6 +10,7 @@ extern "C" {
#include <errno.h>
#include <sys/param.h>
#include <sys/cpuset.h>
#include <sys/thread.h>
}
#include <system_error>
@@ -23,11 +24,16 @@ namespace fibers {
namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpu_id) {
void pin_thread( std::uint32_t cpuid) {
pin_thread( cpuid, ::thr_self() );
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
cpuset_t mask;
CPU_ZERO( & mask);
CPU_SET( cpu_id, & mask);
if ( BOOST_UNLIKELY( 0 != ::cpuset_setaffinity( CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof( mask), & mask) ) ) {
CPU_SET( cpuid, & mask);
if ( BOOST_UNLIKELY( 0 != ::cpuset_setaffinity( CPU_LEVEL_WHICH, CPU_WHICH_TID, h, sizeof( mask), & mask) ) ) {
throw std::system_error(
std::error_code( errno, std::system_category() ),
"::cpuset_setaffinity() failed");

View File

@@ -22,11 +22,16 @@ namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid) {
pin_thread( cpuid, PTHREAD_SELFTID_NP);
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
pthread_spu_t spu;
int err = ::pthread_processor_bind_np( PTHREAD_BIND_FORCED_NP,
& spu,
static_cast< pthread_spu_t >( cpuid),
PTHREAD_SELFTID_NP);
h);
if ( BOOST_UNLIKELY( 0 != err) )
throw std::system_error(
std::error_code( err, std::system_category() ),

View File

@@ -23,11 +23,16 @@ namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid) {
pin_thread( cpuid, ::pthread_self() );
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
cpu_set_t set;
CPU_ZERO( & set);
CPU_SET( cpuid, & set);
int err = 0;
if ( BOOST_UNLIKELY( 0 != ( err = ::pthread_setaffinity_np( ::pthread_self(), sizeof( set), & set) ) ) ) {
if ( BOOST_UNLIKELY( 0 != ( err = ::pthread_setaffinity_np( h, sizeof( set), & set) ) ) ) {
throw std::system_error(
std::error_code( err, std::system_category() ),
"pthread_setaffinity_np() failed");

View File

@@ -32,6 +32,13 @@ void pin_thread( std::uint32_t) {
"boost fiber: pin_thread() not supported" };
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
throw fiber_error{
std::make_error_code( std::errc::function_not_supported),
"boost fiber: pin_thread() not supported" };
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS

View File

@@ -25,8 +25,13 @@ namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid) {
pin_thread( cpuid, P_MYID);
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
if ( BOOST_UNLIKELY( -1 == ::processor_bind( P_LWPID,
P_MYID,
h,
static_cast< processorid_t >( cpuid),
0) ) ) {
throw std::system_error(

View File

@@ -23,6 +23,11 @@ namespace numa {
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid) {
pin_thread( cpuid, ::GetCurrentThread() );
}
BOOST_FIBERS_DECL
void pin_thread( std::uint32_t cpuid, std::thread::native_handle_type h) {
GROUP_AFFINITY affinity;
std::memset( & affinity, 0, sizeof( affinity) );
// compute processor group
@@ -32,7 +37,7 @@ void pin_thread( std::uint32_t cpuid) {
uint32_t id = cpuid % 64;
// set the bit mask of the logical CPU
affinity.Mask = static_cast< KAFFINITY >( 1) << id;
if ( BOOST_UNLIKELY( 0 == ::SetThreadGroupAffinity( ::GetCurrentThread(), & affinity, nullptr) ) ) {
if ( BOOST_UNLIKELY( 0 == ::SetThreadGroupAffinity( h, & affinity, nullptr) ) ) {
throw std::system_error(
std::error_code( ::GetLastError(), std::system_category() ),
"::SetThreadiGroupAffinity() failed");

View File

@@ -34,7 +34,7 @@ project boost/fiber/test
;
rule topology-impl ( properties * )
rule numa-impl ( properties * )
{
local result ;
if ( <target-os>darwin in $(properties) )
@@ -64,9 +64,9 @@ rule native-impl ( properties * )
# NUMA tests
test-suite numa :
[ run test_topology.cpp :
[ run test_numa.cpp :
: :
<conditional>@topology-impl
<conditional>@numa-impl
[ requires cxx11_auto_declarations
cxx11_constexpr
cxx11_defaulted_functions

View File

@@ -4,10 +4,12 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <chrono>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>
#include <utility>
#include <boost/array.hpp>
@@ -15,6 +17,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/numa/pin_thread.hpp>
#include <boost/fiber/numa/topology.hpp>
void test_topology() {
@@ -22,11 +25,29 @@ void test_topology() {
BOOST_CHECK( ! empty);
}
void test_pin_self() {
auto topo = boost::fibers::numa::topology();
BOOST_CHECK( ! topo.empty() );
BOOST_CHECK( ! topo[0].logical_cpus.empty() );
boost::fibers::numa::pin_thread( * topo[0].logical_cpus.begin() );
}
void test_pin() {
auto topo = boost::fibers::numa::topology();
BOOST_CHECK( ! topo.empty() );
BOOST_CHECK( ! topo[0].logical_cpus.empty() );
std::thread t{ []{ std::this_thread::sleep_for( std::chrono::seconds( 1) ); } };
boost::fibers::numa::pin_thread( * topo[0].logical_cpus.begin(), t.native_handle() );
t.join();
}
boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
boost::unit_test::test_suite * test =
BOOST_TEST_SUITE("Boost.Fiber: numa topology test suite");
test->add( BOOST_TEST_CASE( & test_topology) );
test->add( BOOST_TEST_CASE( & test_pin_self) );
test->add( BOOST_TEST_CASE( & test_pin) );
return test;
}