微软VC ++ PEOPLE和睡觉

时间:2013-03-30 17:38:12

标签: c++ visual-c++ c++11 task ppl

以下程序根据使用的睡眠机制运行不同。

#include <ppltasks.h>
#include <chrono>
#include <thread>
#include <iostream>
#include <atomic>
#include <windows.h>
using namespace std;
#define MODERN_MAN
int main()
{
    atomic<int> cnt;
    concurrency::task_group tg;
    for (int i =0; i<1000; ++i )
    {
        tg.run([&cnt](){cout << "."; cnt++; 
        #ifdef MODERN_MAN
        this_thread::sleep_for(chrono::seconds(5));
        #else
        Sleep(5000);
        #endif
        });
    }
    tg.wait();
    cout << cnt;
    return 0;
}

sleep_for的区别在于我看到的任务以1睡眠不会阻止其他人运行的方式进行安排。

根据我看到的Sleep,他们阻止了进一步的任务。

我的问题是:
a)PPL线程池如何能够使巧妙的技巧使其能够解决sleep_for(我认为这是一个告诉操作系统的系统调用(将此线程放在非活动线程列表中x秒)

b)我在这里看到的行为是否有sleep_for保证(也就是定义我不会得到与Sleep相同的行为)

3 个答案:

答案 0 :(得分:4)

  

a)PPL线程池如何能够实现巧妙的技巧,使其能够解决sleep_for(我认为这是一个告诉操作系统的系统调用(将此线程放入非活动线程列表中x秒)< / p>

在Microsoft VC ++ 2012上,C ++标准线程库和PPL基于具有Concurrency Runtime(ConcRT)cooperative and work-stealing scheduler实现。 因此,ConcRT调度程序可以处理任务包括std::this_thread::sleep_for聪明的方式。

  

b)我在这里看到的行为是否保证sleep_for(也就是定义我不会得到与Sleep相同的行为)

也许不。 Sleep是原生的WinAPI,我猜ConRT调度程序不能合作对待它。

附注:Microsoft在Windows 7 / Server 2008 R2 64位版本上说ConcRT use User-mode scueduling(UMS)。可以在这样的平台上改变行为......

答案 1 :(得分:2)

查看相关标题(即#include <thread>)可能会提供信息,并了解它的不同之处。例如,这是sleep_for()定义:

template<class _Rep, class _Period> inline
void sleep_for(const chrono::duration<_Rep, _Period>& _Rel_time)
{
    // sleep for duration
    stdext::threads::xtime _Tgt = _To_xtime(_Rel_time);
    sleep_until(&_Tgt);
}

使用sleep_until()的“绝对时间”重载:

inline void sleep_until(const stdext::threads::xtime *_Abs_time)
{   
    // sleep until _Abs_time
    if (::Concurrency::details::_CurrentScheduler::_Id() != -1)
    {
        stdext::threads::xtime _Now;
        stdext::threads::xtime_get(&_Now, stdext::threads::TIME_UTC);
        ::Concurrency::wait(_Xtime_diff_to_millis2(_Abs_time, &_Now));
        return;
    }
    _Thrd_sleep(_Abs_time);
}

在CRT调用_Thrd_sleep()时,路径停止,并且要弄清楚条件代码的作用并不容易。看起来它对非默认调度程序采取不同的操作,但我现在看不清楚原因。在任何情况下,也许这已经消除了一些光?

答案 2 :(得分:1)

一个原因可能是两种睡眠方法的准确性不同。要找出你应该测试 - 在你的平台上 - 通过测量两个相邻Sleep(0)和两个相邻Sleep(1)之间的时间和sleep_for()

之间的时间来测试准确度

请注意,定时器值的精度与实际精度之间可能存在显着差异。例如。 clock()提供毫秒精度,但是 - 在我的机器上 - 精度为15ms(平均)。