Skip to content

Instantly share code, notes, and snippets.

@mkolod
Created August 30, 2019 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkolod/5ca633b285c78aeaa5b80bb0a49437c0 to your computer and use it in GitHub Desktop.
Save mkolod/5ca633b285c78aeaa5b80bb0a49437c0 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <mutex>
#include <pthread.h>
#include <thread>
#include <vector>
//#define _GNU_SOURCE
#include <sched.h>
class ThreadPool {
public:
ThreadPool() = delete;
ThreadPool(
int sleep_period,
int num_threads,
bool set_affinity
):
sleep_period(sleep_period),
num_threads(num_threads),
set_affinity(set_affinity),
threads(std::vector<std::thread>(num_threads))
{
std::cout << std::endl << (!set_affinity ? "no " : "") << "set affinity\n\n";
for (int i = 0; i < num_threads; ++i) {
threads[i] = createThread(i, sleep_period);
if (set_affinity) {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(i % std::thread::hardware_concurrency(), &cpu_set);
pthread_setaffinity_np(threads[i].native_handle(), sizeof(cpu_set), &cpu_set);
}
std::cout << "Creating thread " << i << std::endl;
}
}
std::thread createThread(int id, int sleep_period) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
return std::thread([this, id, sleep_period] {
while (!terminate_req) {
// Mutex to prevent print races, for a more readable output
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_period));
std::lock_guard<std::mutex> print_lock(this->print_mutex);
std::cout << "Thread " << id << " on core " << sched_getcpu() << std::endl;
}
});
}
void terminate() {
terminate_req = true;
for (auto& t : threads) {
t.join();
}
}
private:
bool terminate_req = false;
int sleep_period;
bool set_affinity;
int32_t num_threads;
std::mutex print_mutex;
std::vector<std::thread> threads;
};
int main() {
int sleep_for_ms = 200;
int num_threads = 4;
ThreadPool thread_pool0(sleep_for_ms, num_threads, false);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
thread_pool0.terminate();
ThreadPool thread_pool1(sleep_for_ms, num_threads, true);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
thread_pool1.terminate();
}
@mkolod
Copy link
Author

mkolod commented Aug 30, 2019

Note: When using more OS-specific headers (e.g. Linux headers and not just pthreads), we can not only set affinity between threads and CPU cores, but keep track of which socket a given core corresponds to. This could help us in NUMA environments, e.g. so we can avoid pulling memory local to a different socket unless absolutely necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment