bthread: support per-tag CPU affinity in --cpu_set#3331
Open
yanglimingcn wants to merge 1 commit into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends the --cpu_set flag in bthread::TaskControl to support per-bthread_tag CPU affinity (while preserving the legacy single CPU-list format), enabling different worker-thread tags to be pinned to different CPU sets.
Changes:
- Update
--cpu_setflag documentation and parsing to accepttag:cpu-listsegments separated by;. - Replace the single shared CPU list with a per-tag CPU list (
_tag_cpus). - Apply CPU binding per worker based on its tag’s CPU list.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/bthread/task_control.h | Updates parse_cpuset API/doc and adds _tag_cpus per-tag CPU binding storage. |
| src/bthread/task_control.cpp | Implements per-tag cpu_set parsing and applies per-tag affinity during worker thread startup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+115
to
+120
| // worker_id is global and monotonically increasing; it doubles as the | ||
| // round-robin index for CPU affinity (same counter for name and binding). | ||
| int worker_id = c->_next_worker_id.fetch_add(1, butil::memory_order_relaxed); | ||
| if (!c->_tag_cpus[tag].empty()) { | ||
| const auto& cpus = c->_tag_cpus[tag]; | ||
| bind_thread_to_cpu(pthread_self(), cpus[worker_id % cpus.size()]); |
Comment on lines
+376
to
+386
| int TaskControl::parse_cpuset(const std::string& value, | ||
| std::vector<std::vector<unsigned>>& tag_cpus, | ||
| int ntags) { | ||
| if (value.empty()) { | ||
| return -1; | ||
| } | ||
| // Detect per-tag format by the presence of ':' or ';'. | ||
| // Legacy format ("0-3,5,7") never contains these characters. | ||
| bool per_tag_format = (value.find(';') != std::string::npos || | ||
| value.find(':') != std::string::npos); | ||
|
|
Comment on lines
+402
to
+409
| std::string tag_str = segment.substr(0, colon); | ||
| std::string cpus_str = segment.substr(colon + 1); | ||
|
|
||
| unsigned tag_id = 0; | ||
| butil::StringPiece tag_sp(tag_str); | ||
| if (butil::StringSplitter(tag_sp, '\t').to_uint(&tag_id) != 0) { | ||
| LOG(ERROR) << "cpu_set invalid tag '" << tag_str << "'"; | ||
| return -1; |
Comment on lines
+100
to
+106
| // On success populates |tag_cpus| (indexed by tag) and returns 0. | ||
| // |tag_cpus| is resized to max_tag+1; tags that are not mentioned | ||
| // get an empty cpu list (= no binding). | ||
| // Returns -1 on parse error. | ||
| static int parse_cpuset(const std::string& value, | ||
| std::vector<std::vector<unsigned>>& tag_cpus, | ||
| int ntags); |
Comment on lines
+376
to
+386
| int TaskControl::parse_cpuset(const std::string& value, | ||
| std::vector<std::vector<unsigned>>& tag_cpus, | ||
| int ntags) { | ||
| if (value.empty()) { | ||
| return -1; | ||
| } | ||
| // Detect per-tag format by the presence of ':' or ';'. | ||
| // Legacy format ("0-3,5,7") never contains these characters. | ||
| bool per_tag_format = (value.find(';') != std::string::npos || | ||
| value.find(':') != std::string::npos); | ||
|
|
e29075d to
6538752
Compare
Previously --cpu_set accepted a single CPU list (e.g. "0-3,5,7") that was applied uniformly to all bthread worker threads regardless of their bthread_tag. This change extends the flag to accept a per-tag format: --cpu_set="0:0-3,5,7;1:6-9,4" where each semicolon-separated segment is "<tag>:<cpu-list>". Tags not mentioned in the string get no CPU binding. The legacy single-list format continues to work unchanged and binds all tags to the same set. Implementation: - Replace _cpus (vector<unsigned>) with _tag_cpus (vector<vector<unsigned>>), sized to FLAGS_task_group_ntags in the constructor. - Add parse_one_cpuset() (static helper) for the existing range-list parsing logic; parse_cpuset() now dispatches between legacy and per-tag formats based on the presence of ':' or ';'. - worker_thread() looks up _tag_cpus[tag] and round-robins over the per-tag CPU list using the global _next_worker_id counter.
6538752 to
41e3f24
Compare
| , _tagged_pl(FLAGS_task_group_ntags) | ||
| , _tag_cpus(FLAGS_task_group_ntags) | ||
| , _tag_next_worker_id(FLAGS_task_group_ntags) | ||
| {} |
Comment on lines
+368
to
+370
| for (auto i = first; i <= last; ++i) { | ||
| cpuset.insert(i); | ||
| } |
Comment on lines
+114
to
+117
| // tag_wid is a per-tag monotonic counter: same-tag workers get 0,1,2,... | ||
| // Used both for CPU round-robin affinity and the thread name suffix. | ||
| int tag_wid = c->_tag_next_worker_id[tag].fetch_add( | ||
| 1, butil::memory_order_relaxed); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previously --cpu_set accepted a single CPU list (e.g. "0-3,5,7") that was applied uniformly to all bthread worker threads regardless of their bthread_tag.
This change extends the flag to accept a per-tag format:
--cpu_set="0:0-3,5,7;1:6-9,4"
where each semicolon-separated segment is ":". Tags not mentioned in the string get no CPU binding. The legacy single-list format continues to work unchanged and binds all tags to the same set.
Implementation:
What problem does this PR solve?
Issue Number: resolve
Problem Summary:
What is changed and the side effects?
Changed:
Side effects:
Performance effects:
Breaking backward compatibility:
Check List: