Skip to content
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

RFC proposal for thread affinity #1480

Closed
wants to merge 2 commits into from

Conversation

Projects
None yet
8 participants
@jamperry
Copy link

jamperry commented Jan 26, 2016

No description provided.

@alexcrichton alexcrichton added the T-libs label Jan 26, 2016

// locks thread to cpu core 2
let t = thread::spawn(move || {
let cpu_no = 2;
let cpu_lock = CpuLock::lock_on(cpu_no).unwrap(); // the current thread is now locked to an arbitrary free CPU core

This comment has been minimized.

@durka

durka Jan 28, 2016

Contributor

this comment seems wrong

// locks thread to cpu core 2
let cpu_no = 2;
let t = thread::lock_on(2,move || {
let cpu_lock = CpuLock::lock_on(cpu_no).unwrap(); // the current thread is now locked to an arbitrary free CPU core

This comment has been minimized.

@durka

durka Jan 28, 2016

Contributor

if lock_on is analogous to lock, this line and the one after it shouldn't be here

# Alternatives
[alternatives]: #alternatives

Calling unsafe OS-specific system calls to create threads and changing the affinity mask because `std::thread::Thread` do not expose the underling OS-specific thread id (AFIAW).

This comment has been minimized.

@retep998

retep998 Feb 2, 2016

Member

JoinHandle is what actually contains the OS-specific thread handle. On Windows JoinHandle implements AsRawHandle and IntoRawHandle and on non-windows it implements JoinHandleExt. Also getting the handle to the current thread is pretty simple (GetCurrentThread or pthread_self depending on your platform).

rust-lang/rust#30177


I split it into two parts: *User API* and *Implementation*.

### Locking to an arbitrary free CPU core

This comment has been minimized.

@retep998

retep998 Feb 2, 2016

Member

There's a lot of room for detail on how exactly it locks to an arbitrary free CPU core. Does it determine what CPU core the thread is currently executing on and then lock to that? Does it pick a random CPU core?

@retep998

This comment has been minimized.

Copy link
Member

retep998 commented Feb 2, 2016


* Is it possible for consistent & symmetric semantics across all supported operating systems?

* Is it better to be an external library rather than in std?

This comment has been minimized.

@retep998

retep998 Feb 2, 2016

Member

I personally think this should start as an external library.

@peterhj

This comment has been minimized.

Copy link

peterhj commented Feb 5, 2016

Thread affinity is something I'm sorely needing in Rust today as well. Some immediate comments on the RFC:

  1. Rather than have just a lock, probably want a set, which maps better to the underlying thread affinity implementations (e.g., cpu_set_t), and which better reflects some real cases of "don't care" among threads on the same physical processor/socket.
  2. At least for the pthread implementation of threads, there is a builder that initializes its pthread_attr_t before the thread is even spawned. For example, that is how the thread stack size is set (see libstd/sys/unix/thread.rs). Logically, it would make sense to allow setting the affinity through the thread builder as well, using pthread_attr_setaffinity_np under the hood. This could be in addition to a guard-based mechanism as you described.

There are also general comments which I think concern the affinity implementations for any language's standard library. Dumping some here off the top of my head:

  • How are processors/sockets, cores, and threads numbered by the "system"? Typically the "system" numbering convention can be arbitrary or insane.
  • How to query for all threads belonging to a particular physical core or processor? In practice, this is often the key feature one really wants. I'm aware of the C libraries libnuma and hwloc which address this, neither of which are particularly standard.
  • What numbering convention to accept through your affinity interface? My feeling is that one should just interpret thread indices by the "system" numbering scheme (which is what you do already), and leave the finessing of CPU/core topology to another library.

It could be interesting if libstd received a standard way of querying CPU topology. But more likely it'll start off as just another library, which is just fine if it just works.

@alexcrichton alexcrichton self-assigned this Mar 2, 2016

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Mar 3, 2016

Thanks for the RFC @jamperry! The discussion here and on the internals forum leads me to think that this may best be served by starting as an external library? It sounds like there's a lot of competing possible strategies and there's a lot of concerns to take into account. Taking some time to flesh out the library externally, get some experience, and toy with an API may be the best step forward here?

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Apr 15, 2016

🔔 This RFC is now entering its week-long final comment period 🔔

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Apr 19, 2016

I agree with @retep998, @alexcrichton and others that this work should start in an external library and be considered for addition to std at a later time, after we've gained practical experience with it.

@diwic

This comment has been minimized.

Copy link

diwic commented Apr 25, 2016

If implemented, how about using the thread Builder like this: thread::Builder::new().affinity(0x3).spawn(move || { /* ... */ }) ...where 0x3 is a bitmask of allowed cores.

@Florob

This comment has been minimized.

Copy link

Florob commented May 2, 2016

Like others I think this should (at least initially) live in an external library.
Apart from that I think the term "lock(ing)" is unfortunate in this context, as it is already used with different meaning(s) (cf. mutexes, and x86's lock prefix). I would prefer pinning, binding, or affinity.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented May 4, 2016

The libs team discussed this RFC at triage today and the decision was to close for now. There doesn't appear to be a fundamental reason why this needs to be in the standard library right now, and otherwise it seems like this can be developed externally on crates.io

Thanks again though for the RFC @jamperry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.