Controlling the number of threads used by std::execution::par
in C++ can be crucial for optimizing performance and avoiding resource contention.
The C++ standard library does not provide direct control over the number of threads used by the parallel execution policy (std::execution::par
). However, you can influence thread usage indirectly through various techniques.
Here’s an example of using a custom thread pool with a parallel execution policy:
#include <condition_variable>
#include <execution>
#include <functional>
#include <future>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
class ThreadPool {
public:
ThreadPool(size_t numThreads);
~ThreadPool();
template <class F>
void enqueue(F&& f);
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queueMutex;
std::condition_variable condition;
bool stop;
};
ThreadPool::ThreadPool(size_t numThreads)
: stop(false) {
for (size_t i = 0; i < numThreads; ++i) {
workers.emplace_back([this] {
for (;;) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(
this->queueMutex);
this->condition.wait(lock, [this] {
return this->stop || !this->tasks.empty();
});
if (this->stop && this->tasks.empty())
return;
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
});
}
}
ThreadPool::~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queueMutex);
stop = true;
}
condition.notify_all();
for (std::thread& worker : workers) {
worker.join();
}
}
template <class F>
void ThreadPool::enqueue(F&& f) {
{
std::unique_lock<std::mutex> lock(queueMutex);
tasks.emplace(std::forward<F>(f));
}
condition.notify_one();
}
void Log(int number) {
std::cout << "Number: " << number << '\n';
}
int main() {
// Control the number of threads here
ThreadPool pool(4);
std::vector<int> numbers{1, 2, 3, 4, 5};
for (int number : numbers) {
pool.enqueue([number] { Log(number); });
}
}
Number: 1
Number: 5
Number: 2
Number: 4
Number: 3
In this example, a ThreadPool
class is implemented to manage a fixed number of threads. The Log
function is then enqueued into the thread pool, which controls the execution of tasks.
Key points:
std::execution::par
.By managing your thread pool, you can control the number of threads used in parallel execution, improving performance and resource management.
Answers to questions are automatically generated and may not have been reviewed.
Multithreading in C++ standard library algorithms using execution policies