gpt4 book ai didi

c++ - 使用 std::lock (c++11) 的大量 CPU 负载

转载 作者:IT老高 更新时间:2023-10-28 12:41:38 27 4
gpt4 key购买 nike

我最近实现线程/互斥锁管理器的努力以 75% 的 CPU 负载(4 核)告终,而所有四个正在运行的线程要么处于 sleep 状态,要么等待互斥锁被解锁。

具体的类太大了,无法在这里完整发布,但我可以将原因缩小到死锁安全地获取两个互斥锁

std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );

该类的另一部分使用 std::condition_variablewait()notify_one()mutex1 用于有选择地同时执行的某些代码。

简单的改变

std::unique_lock<std::mutex> lock1( mutex1 );
std::unique_lock<std::mutex> lock2( mutex2 );

将 CPU 使用率降至正常的 1-2%。

我不敢相信,std::lock() 函数效率这么低。这可能是 g++ 4.6.3 中的错误吗?

编辑:(示例)

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

std::mutex mutex1, mutex2;
std::condition_variable cond_var;

bool cond = false;
std::atomic<bool>done{false};

using namespace std::chrono_literals;

void Take_Locks()
{
while( !done )
{
std::this_thread::sleep_for( 1s );

std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );

std::this_thread::sleep_for( 1s );
lock1.unlock();
lock2.unlock();
}
}

void Conditional_Code()
{
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );

std::lock( lock1, lock2 );
std::cout << "t4: waiting \n";

while( !cond )
cond_var.wait( lock1 );

std::cout << "t4: condition met \n";
}

int main()
{
std::thread t1( Take_Locks ), t2( Take_Locks ), t3( Take_Locks );
std::thread t4( Conditional_Code );

std::cout << "threads started \n";
std::this_thread::sleep_for( 10s );

std::unique_lock<std::mutex> lock1( mutex1 );
std::cout << "mutex1 locked \n" ;
std::this_thread::sleep_for( 5s );

std::cout << "setting condition/notify \n";
cond = true;
cond_var.notify_one();
std::this_thread::sleep_for( 5s );

lock1.unlock();
std::cout << "mutex1 unlocked \n";
std::this_thread::sleep_for( 6s );

done = true;
t4.join(); t3.join(); t2.join(); t1.join();
}

最佳答案

在我的机器上,以下代码每秒打印 10 次并消耗几乎 0 cpu,因为大部分时间线程要么处于休眠状态,要么被锁定的互斥锁阻塞:

#include <chrono>
#include <thread>
#include <mutex>
#include <iostream>

using namespace std::chrono_literals;

std::mutex m1;
std::mutex m2;

void
f1()
{
while (true)
{
std::unique_lock<std::mutex> l1(m1, std::defer_lock);
std::unique_lock<std::mutex> l2(m2, std::defer_lock);
std::lock(l1, l2);
std::cout << "f1 has the two locks\n";
std::this_thread::sleep_for(100ms);
}
}

void
f2()
{
while (true)
{
std::unique_lock<std::mutex> l2(m2, std::defer_lock);
std::unique_lock<std::mutex> l1(m1, std::defer_lock);
std::lock(l2, l1);
std::cout << "f2 has the two locks\n";
std::this_thread::sleep_for(100ms);
}
}

int main()
{
std::thread t1(f1);
std::thread t2(f2);
t1.join();
t2.join();
}

样本输出:

f1 has the two locks
f2 has the two locks
f1 has the two locks
...

我在 OS X 上运行此程序,事件监视器应用程序显示此进程正在使用 0.1% 的 cpu。该机器是 Intel Core i5(4 核)。

我很乐意以任何方式调整此实验以尝试创建活锁或过度使用 CPU。

更新

如果此程序在您的平台上使用过多的 CPU,请尝试将其更改为调用 ::lock(),其中定义为:

template <class L0, class L1>
void
lock(L0& l0, L1& l1)
{
while (true)
{
{
std::unique_lock<L0> u0(l0);
if (l1.try_lock())
{
u0.release();
break;
}
}
std::this_thread::yield();
{
std::unique_lock<L1> u1(l1);
if (l0.try_lock())
{
u1.release();
break;
}
}
std::this_thread::yield();
}
}

我很想知道这是否对您有任何影响,谢谢。

更新 2

经过长时间的拖延,我写了一篇关于这个主题的论文初稿。该论文比较了完成这项工作的 4 种不同方法。它包含您可以复制并粘贴到您自己的代码中并自己测试的软件(请报告您的发现!):

http://howardhinnant.github.io/dining_philosophers.html

关于c++ - 使用 std::lock (c++11) 的大量 CPU 负载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13667810/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com