c++ - std::thread 不会让我的 CPU 负载超过 20%?
问题描述
也许我使用 std::thread 错误?我有一个 12 线程 cpu 并构建了一个渲染引擎。更像是一个绘图仪,用于诸如 perlin 噪声等之类的东西……由于渲染速度很慢,我使用 std::thread 来充分利用我的 12 个内核。渲染速度实际上显着提高,但我的 cpu 使用率不会比仅使用一个线程时高......
这是我负责渲染的代码……让我试着解释一下……
void Renderer::Render(sf::Image * _img,
sf::Vector2f _dims,
unsigned _threadCount)
{
im = _img;
dims = _dims;
im->create(dims.x, dims.y, sf::Color(100, 0, 0, 255));
static float bar = 0.3f;
float g = 0.01f;
std::vector < std::thread > workers;
for (unsigned i = 0; i < _threadCount; ++i)
{
workers.push_back(std::thread(Renderer::RenderThread,
sf::IntRect((dims.x / _threadCount) * i,
0,
(dims.x / _threadCount) * (i + 1),
dims.y),
bar,
g,
sf::Color(0,
(255.0f / _threadCount) * i,
0)));
}
bar += 0.01f;
for (unsigned i = 0; i < workers.size(); ++i)
{
workers[i].join();
}
return;
}
void Renderer::RenderThread(sf::IntRect area, float bar, float g, sf::Color clr)
{
for (unsigned x = area.left + 1; x < area.width + 1; x++)
{
for (unsigned y = area.top + 1; y < area.height + 1; y++)
{
im->setPixel(x - 1, y - 1, ImAlg::Tiles0(x, y, bar, 5));
}
}
return;
}
所以基本上它的作用如下: 上层函数是主函数,由框架调用。它创建线程。较低的函数是在每个线程上运行的函数。我试图将要渲染的图像分成均匀的部分。就像图像是 1000 宽并且我会使用 4 个线程一样,每个线程都会渲染 250x1000 像素
解决方案
不要使用原始线程。从一个简单的线程池开始:
struct thread_pool {
std::future<void> run( std::function<void()> f ){
std::packaged_task<void()> t(std::move(f));
auto r = t.get_future();
auto l = lock();
q.push_back(std::move(t));
cv.notify_one();
return r;
}
void start(std::size_t n){
//std::cout << n << " threads starting" << std::endl;
while(n--)
threads.push_back( std::thread([this]{loop();}) );
}
~thread_pool(){
end();
for (auto&&t:threads)t.join();
}
private:
void end(){
auto n=threads.size();
auto l=lock();
for(auto count=n;count;--count)
q.emplace_back();
cv.notify_all();
//std::cout << n << " threads ended" << std::endl;
}
void loop(){
while(true){
//std::cout << "Waiting..." << std::endl;
auto t=pop();
//std::cout << "Got " << t.valid() << std::endl;
if (!t.valid()) break;
//std::cout << "Running..." << std::endl;
t();
}
}
std::packaged_task<void()> pop(){
auto l=lock();
cv.wait(l, [&]{ return !q.empty();});
auto r = std::move(q.front());
q.pop_front();
return r;
}
std::vector<std::thread> threads;
std::unique_lock<std::mutex> lock(){ return std::unique_lock<std::mutex>(m); }
std::mutex m;
std::deque<std::packaged_task<void()>> q;
std::condition_variable cv;
};
使用线程池;传入需要线程的代码,并预先启动线程(可能基于硬件并发)。 run
任务。等待从 run 方法返回的未来。
这将比按需旋转线程快得多。
推荐阅读
- sql - 将 IN 子句的所有值添加到子选择列
- r - 如何创建 ppcor 函数的循环?
- python - 如何在保持目录结构的同时提取所有 .tar.gz 文件?
- javascript - Mongoose 在按明显存在的 _id 搜索时返回 Null
- c++ - Eigen 3.3.4:创建地图的方法是什么
到二维块? - google-cloud-platform - cloud-builds pub/sub 主题似乎未列出或无法访问
- unity3d - 从 Unity 上传的 Google Play 未更新
- python - 如何在单元格中将txt文件转换为csv文件
- python - 熊猫如何根据后面的行过滤前面的行
- c# - 错误 CS1703 在构建 Enterprise Bot Framework 项目时已导入具有相同标识的多个程序集