Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost条件互斥的性能较差_C++_Boost Thread - Fatal编程技术网

C++ boost条件互斥的性能较差

C++ boost条件互斥的性能较差,c++,boost-thread,C++,Boost Thread,我不熟悉使用条件变量,所以我很容易在这里做一些愚蠢的事情,但是当我使用boost线程时,与直接调用函数相比,我得到了一些奇怪的性能。如果我将在func上创建boost线程的行更改为直接调用func,那么代码的运行速度会更快。我已经尝试过使用SourceForge的boost threadpool软件,但没有任何区别 代码如下: #include <boost/thread.hpp> using namespace boost; condition_variable cond;

我不熟悉使用条件变量,所以我很容易在这里做一些愚蠢的事情,但是当我使用boost线程时,与直接调用函数相比,我得到了一些奇怪的性能。如果我将在func上创建boost线程的行更改为直接调用func,那么代码的运行速度会更快。我已经尝试过使用SourceForge的boost threadpool软件,但没有任何区别

代码如下:

#include <boost/thread.hpp>


using namespace boost;

condition_variable cond;
mutex conditionalMutex;
int numThreadsCompleted = 0;
int numActiveThreads = 0;

void func()
{
  {
    lock_guard<mutex> lock(conditionalMutex);
    --numActiveThreads;
    numThreadsCompleted++;
  }
  cond.notify_one();
};


int main()
{
  int i=0;
  while (i < 100000)
    {
      if (numActiveThreads == 0)
        {
          ++numActiveThreads;
          thread thd(func);
          //Replace above with a direct call to func for several orders of magnitude
          //performance increase...
          ++i;
        }
      else
        {
          unique_lock<mutex> lock(conditionalMutex);
          while (numThreadsCompleted == 0)
            {
              cond.wait(lock);
            }
          numThreadsCompleted--;
        }
    }
  return 0;
}
#包括
使用名称空间boost;
条件变量cond;
互斥条件mutex;
int numThreadsCompleted=0;
int numativethreads=0;
void func()
{
{
锁和防护锁(条件Mutex);
--纽曼提维思;
numThreadsCompleted++;
}
第二,通知某人;
};
int main()
{
int i=0;
而(i<100000)
{
if(numativethreads==0)
{
++纽曼提维思;
螺纹thd(func);
//将上述内容替换为直接调用func几个数量级
//性能提高。。。
++一,;
}
其他的
{
唯一锁(conditionalMutex);
while(numThreadsCompleted==0)
{
等待(锁定);
}
numthreads已完成--;
}
}
返回0;
}

您正在创建和销毁线程,这些线程通常作为一些较低级别的操作系统结构实现,通常是某种轻量级进程。这种创造和毁灭可能代价高昂

最后,你基本上做到了

  • 创建线程
  • 等待线程退出

  • 一遍又一遍。这意味着创建/销毁线程,而您每次都在这样做,因此成本将不断增加。

    除了创建和销毁线程的开销之外,还可能导致性能的差异

    如果没有线程,if语句始终为true,因为在每个循环迭代的开始和结束时,
    numativethreads
    将为
    0

    while (i < 100000)
    {
      if (numActiveThreads == 0) // branch always taken
      {
        ++numActiveThreads; // numActiveThreads = 1
        func();             // when this returns, numActiveThreads = 0
        ++i;                
      }
    }
    
    while(i<100000)
    {
    if(numativethreads==0)//始终执行分支
    {
    ++numativethreads;//numativethreads=1
    func();//返回时,numativethreads=0
    ++一,;
    }
    }
    
    这导致:

    • 分支预测永远不会失败
    • 没有线程创建/销毁的开销
    • 等待获取
      conditionalMutex
      的时间没有被阻塞
    使用线程时,
    numativethreads
    在连续迭代中可能是
    0
    。在我测试的大多数机器上,观察到了短的可预测模式,在每次迭代中if语句和else语句之间交替出现分支。但是,有时在连续迭代中选择if语句。因此,时间可能浪费在以下方面:

    • 分支预测失败
    • 线程的创建和销毁。如果创建和销毁是并发的,那么同步可能发生在底层线程库中
    • 阻止等待获取
      条件互斥
      或等待
      条件

    性能必须比直接调用函数差得多。您启动一个线程,然后等待该线程结束。即使您将启动线程的开销减少到零,您也可以与该线程通信。您将至少有一个上下文切换,由于func()基本上什么都不做,因此开销成为一个重要因素。在func()中再添加一些有效负载,比率就会改变。如果需要做的事情很少,就在发现这个东西的线程上做

    顺便说一句:您有一个竞态条件,因为您在没有锁定互斥锁的情况下写入numativethreads。以上代码归结为:

    int main()
    {
        int i=0;
        while (i < 100000)
        {
            thread thd(func);
            thd.join();
            ++i;
        }
    
        return 0;
    }
    
    intmain()
    {
    int i=0;
    而(i<100000)
    {
    螺纹thd(func);
    thd.join();
    ++一,;
    }
    返回0;
    }
    
    没有理由认为这比:

    int main()
    {
        int i=0;
        while (i < 100000)
        {
            func();
            ++i;
        }
    
        return 0;
    }
    
    intmain()
    {
    int i=0;
    而(i<100000)
    {
    func();
    ++一,;
    }
    返回0;
    }
    
    我认为创建和销毁线程的开销也是个问题,所以我尝试了线程池:使用boost::thread时34秒,使用ThreadPool时7秒,使用函数调用时0.16秒。这是在增加循环长度以给出更大的数字之后……理论上,分支预测惩罚不应该是导致性能下降的一个大因素。一个分支上的一次未命中预测通常花费不到100个周期,而线程创建和销毁可能会消耗更多的cpu。