2013-03-30 3 views
3

Следующая программа работает по-разному в зависимости от используемого механизма сна.Microsoft VC++ 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 из того, что я вижу, они блокируют выполнение дальнейших задач.

Мои вопросы:
а) как можно PPL пул потоков сделать умный трюк, который позволяет ему обойти sleep_for (я думал, что это системный вызов, который говорит ОС (поместить эту тему в список неактивных потоков для х секунды)

б) является ли поведение Im видит здесь с sleep_for гарантированными (иначе это определенно, что я не буду получать такое же поведение, как с Sleep)

ответ

4

а) как можно PPL пул потоков сделать умный трюк, позволяет ему обходить sleep_for (я думал, что это системный вызов, который говорит ОС (поместить эту тему в список неактивных потоков для х секунд)

В Microsoft VC++ 2012, C++ Стандартная библиотека резьб и PPL реализуются на основе Concurrency Runtime(ConcRT), который имеет cooperative and work-stealing scheduler. Так что планировщик ConcRT может обрабатывать задачи, включая std::this_thread::sleep_for умный способ.

б) Является ли поведение Im видит здесь с sleep_for гарантированной (иначе это определенно, что я не буду получать такое же поведение, как с Sleep)

Может НЕТ. Sleep является родным WinAPI, я думаю, что планировщик ConRT не может относиться к нему совместно.

Сторона примечания: Microsoft говорит ConcRT use User-mode scueduling(UMS) на Windows 7/Server 2008 R2 64-разрядная версия. Поведение может быть изменено на такой платформе ...

+1

См. Также раздел «Координация задач с совместной блокировкой». http://msdn.microsoft.com/en-us/library/gg663529.aspx –

1

Одной из причин может быть то, что точность двух методов сна различна. Для того, чтобы выяснить, следует проверить - на вашей платформе - для accurady путем измерения времени между двумя соседними Sleep(0) и двумя соседними Sleep(1) и то же самое для sleep_for()

Пожалуйста, обратите внимание, что там может быть существенная разница между точностью значения таймера и их фактическая точность. Например. clock() обеспечивает миллисекундную точность, но - на моей машине - имеет точность 15 мс (в среднем).

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(), и это не так просто чтобы выяснить, что делает условный код. Похоже, что он принимает разные меры для планировщика, не использующего по умолчанию, но я не могу понять, почему на данный момент. В любом случае, возможно, что пролить свет?

Смежные вопросы