3

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

#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保证(也就是它是否定义了我不会得到与 with 相同的行为Sleep

4

3 回答 3

4

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

在 Microsoft VC++2012 上,C++ 标准线程库和 PPL 是基于具有协作和工作窃取调度程序的并发运行时(ConcRT)实现的。所以 ConcRT 调度器可以巧妙地处理任务。std::this_thread::sleep_for

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

可能不。Sleep是原生的WinAPI,我猜ConRT调度器不能协同处理。

旁注:微软表示ConcRT在 Windows 7/Server 2008 R2 64 位版本上使用用户模式调度(UMS)。在这样的平台上,行为可能会改变......

于 2013-03-31T06:31:45.253 回答
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(),要弄清楚条件代码在做什么并不容易。看起来它对非默认调度程序采取了不同的操作,但我现在不明白为什么。无论如何,也许这已经说明了一些问题?

于 2013-04-03T10:04:19.577 回答
1

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

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

于 2013-04-02T12:05:51.953 回答