PPL critical_section / parallel_for сбой в Visual Studio 2010?

Я сделал эту простую тестовую программу, и она иногда вызывает прерывание отладки или просто дает сбой (в Debug / Win32 / VS2010SP1) - и, конечно же, иногда она даже работает. Я что-то делаю неправильно или где-то есть ошибка в PPL (VS2010)?

#include "stdafx.h"
#include <ppl.h>
#include <vector>

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> vi;
    Concurrency::critical_section cs;
    Concurrency::parallel_for(0, 10000, [&](int i)
    {
        Concurrency::critical_section::scoped_lock l(cs);
        vi.push_back(i);
    });
    return 0;
}

Стек вызовов Debug Break выглядит следующим образом:

Один сбой, который у меня только что появился, похоже, что блокировка не была удержана (cs: not_locked)

Lockable.exe! Std :: vector> :: _ Orphan_range (int * _First = 0x0000c5db, int * _Last = 0x0000c5db) Строка 1442 + 0x5 байт C ++ Lockable.exe! Std :: vector> :: push_back (const int & _Val = 4177 ) Строка 995 C ++

Lockable.exe! anonymous namespace'::<lambda0>::operator()(int i=4177) Line 16 C++ Lockable.exe!Concurrency::_Parallel_chunk_helper_invoke<int,unsigned int,anonymous namespace '::, 0> :: _ Invoke (const int & _First = 0, unsigned int & _Index = 4177, const anonymous-namespace'::<lambda0> & _Func={...}) Line 1445 C++ Lockable.exe!Concurrency::_Parallel_chunk_helper<int,unsigned int,anonymous namespace' ::, 0> :: operator () () Строка 1833 + 0x16 байт C ++ Lockable.exe! Concurrency :: task_handle, 0>>> (Concurrency :: task_handle, 0>> * _PChore = 0x7cbffc24 {_M_first = 0 _M_step = 1 _M_function = {...} ...}) Строка 3495 C ++ msvcr100d.dll! Concurrency :: details :: _ UnrealizedChore :: _ StructuredChoreWrapper (Concurrency :: details :: _ UnrealizedChore * pChore = 0x7cbffc24 {_M_first = 0 _M_step = 1 _M_function = {...} ...}) Строка 99 + 0xc байтов C ++ msvcr100d.dll! Параллелизм :: подробности :: _ UnrealizedChore :: _ Invoke () Строка 3454 + 0xc байтов C ++ msvcr100d.dll! Параллелизм :: подробности :: WorkItem :: Invoke () Строка 75 C ++ msvcr100d.dll! Параллелизм :: подробности :: InternalContextBase :: ExecuteChoreInline (Concurrency :: details :: WorkItem * pWork = 0x7bc0fab4) Строка 1385 C ++ msvcr100d.dll! Concurrency :: details :: InternalContextBase :: Dispatch (Concurrency :: DispatchState * pDispatchState = 0x7bc0 fad4) Строка 1478 C ++ msvcr100d.dll! Concurrency :: details :: FreeThreadProxy :: Dispatch () Строка 157 C ++ msvcr100d.dll! Concurrency :: details :: ThreadProxy :: ThreadProxyMain (void * lpParameter = 0x2dcf6200) Строка 162 C ++ kernel32. dll! 763c33aa ()
[Фреймы ниже могут быть неправильными и / или отсутствующими, символы для kernel32.dll не загружены]
ntdll.dll! 771a9ef2 ()
ntdll.dll! 771a9ec5 ()

И могут быть другие нарушения произвольного доступа даже внутри внутренней реализации PPL, которые, я думаю, вы могли бы воспроизвести. (с надеждой)

Я запустил ту же программу в Visual Studio 2012 Express для настольных ПК, и после многих тестовых запусков, похоже, все работает правильно.

Мне интересно, если PPL под VS2010 глючит для использования в производственной среде?

Спасибо за любой вклад!

Итак, наконец, после публикации вопроса в Microsoft Connect (или в социальных сетях?) Проблема была подробно объяснена.


person Lin    schedule 23.01.2013    source источник
comment
Насколько я могу судить, parallel_for [_each] специально разработан для объединения всех параллельных задач в конце алгоритма. Простая проверка - поставить точку останова в операторе return в конце main, он вылетает до достижения точки останова. Более того, PPL просто не предоставляет такой явной функции блокировки, что, безусловно, нарушает цель его разработки - заставить вещи выполняться параллельно с минимальной блокировкой [b] (с использованием объектов синхронизации)!   -  person ildjarn    schedule 24.01.2013


Ответы (2)


http://social.msdn.microsoft.com/Forums/en-US/parallelcppnative/thread/9601a2d0-b1ef-4d81-8743-73c3965a7b63.

http://social.msdn.microsoft.com/Forums/eu/parallelcppnative/thread/38d2e8c8-e863-4da0-a45a-9776ab27feed.

На мой взгляд, стоит дождаться окончания программы. Подпрограмма _1_ создала поток (ы) для параллельного выполнения и будет работать сама по себе. Но _2_ завершается, что приведет к остановке всех запущенных потоков (или сделает их недействительными).

person Lin    schedule 28.01.2013

Попробуйте поставить какой-нибудь блокирующий вызов (такой же простой, как ввод пользователя) и посмотрите, работает ли он.

Код выглядит нормально и отлично работает для меня с VC ++ 2012 RTM. Вы можете попробовать сообщить об ошибке в MS Connect (если его еще нет), но если что-то было исправлено в VC ++ 2012, я сомневаюсь, что они сделают что-нибудь, чтобы исправить это в VC ++ 2010 на данном этапе.

person Ajay    schedule 24.01.2013
comment
Правда правда! Я упустил тот факт, что _1_ сам будет ждать казни. Перепутано с задачами, которые выполняются асинхронно. - person Lin; 24.01.2013
comment
msvcr100d.dll! _CrtDbgBreak () Строка 85 C msvcr100d.dll! _VCrtDbgReportW (int nRptType = 2, const wchar_t * szFile = 0x0f45d230, int nLine = 728, const wchar_t * szModule = 0xModule * szModule = 0x000000, szModulez = 0x7d92f7c4) Строка 502 C msvcr100d.dll! _CrtDbgReportWV (int nRptType = 2, const wchar_t * szFile = 0x0f45d230, int nLine = 728, const wchar_t * szModule = 0x00000000, const wormfatglist = * sz 241 + 0x1d байтов C ++ msvcr100d.dll! _CrtDbgReportW (int nRptType = 2, const wchar_t * szFile = 0x0f45d230, int nLine = 728, const wchar_t * szModule = 0x00000000, const wchar_t * 0x0d400 + Linear_t * szFormat = 25 байт C ++ msvcr100d.dll! Параллелизм :: подробности :: LockQueueNode :: Copy (Параллелизм :: подробности :: LockQueueNode * pCopyFromNode = 0x7d92f908) Строка 728 + 0x27 байт C ++ msvcr100d.dll! Параллелизм :: критический_ сегмент :: _ Acquire __PLocking (void = 0x7d92f908, bool _FHasExternalNode = true) Строка 1019 C ++ msvcr100d.dll! Concurrency :: critical_section :: scoped_lock :: scoped_lock (Concurrency :: critical_section & _Critical_section = locked) Строка 1083 C ++ Lockable.exe! _2_anonymous namespace '::, 0> :: _ Invoke (const int & _First = 0, unsigned int & _Index = 1418, const _3_anonymous namespace '::, 0> :: operator () () Строка 1781 + 0x16 байт C ++ Lockable.exe! Concurrency :: task_handle, 0>>> (Concurrency :: task_handle, 0> > * _PChore = 0x7c13fba8 {_M_first = 0 _M_step = 1 _M_function = {...} ...}) Строка 3495 C ++ msvcr100d.dll! Concurrency :: details :: _ UnrealizedChore :: _ StructuredChoreWrapper (Concurrency :: details :: _ UnrealizedChore * pChore = 0x7c13fba8 {_M_first = 0 _M_step = 1 _M_function = {...} ...}) Строка 99 + 0xc байтов C ++ msvcr100d.dll! Concurrency :: details :: _ UnrealizedChore :: _ Invoke () Строка 3454 + 0xc байтов C ++ msvcr100d.dll! Параллелизм :: подробности :: WorkItem :: Invoke () Строка 75 C ++ msvcr100d.dll! Параллелизм :: подробности :: InternalContextBase :: ExecuteChoreInline (Параллелизм :: подробности :: WorkItem * pWork = 0 x7d92fe7c) Строка 1385 C ++ msvcr100d.dll! Параллелизм :: детали :: InternalContextBase :: Dispatch (Concurrency :: DispatchState * pDispatchState = 0x7d92fe9c) Строка 1478 C ++ msvcr100d.dll! Параллелизм :: подробности :: FreeThreadProxy :: Dispatch () Строка () C ++ msvcr100d.dll! Параллелизм :: подробности :: ThreadProxy :: ThreadProxyMain (void * lpParameter = 0x2ed5b4f0) Строка 162 C ++ kernel32.dll! 763c33aa ()
[Фреймы ниже могут быть неправильными и / или отсутствовать, символы для kernel32.dll]
ntdll.dll! 771a9ef2 ()
ntdll.dll! 771a9ec5 () - person Ajay; 24.01.2013