none
Parallel.For RRS feed

  • Вопрос

  • Всем привет! Проблема - XP,VS-2010 Express Пытаюсь запустить приведенную программу на 2х-ядерном компе с использованием Parallel.For. Иногда проскакивает нормально, а иногда ругается на new group(g) в 12 строке "Object reference not set to an instance of an object." Почему? Извиняюсь за недостойное форматирование - не моя вина, сайт глючит. using System.Threading.Tasks; ... class group ... List<string> GroupLst = new List<>(); GroupLst.Add (A); ... Dictionary<string, group> GroupDct=new Dictionary<string, group>(); try{ Parallel.For ( 0,GroupLst.Count,delegate (int i) { string g=GroupLst.ElementAt(i); if ( !GroupDct.ContainsKey(g)) { GroupDct.Add (g, new group(g)); } } ); }
    22 января 2011 г. 14:28

Ответы

Все ответы

  • не совсем понятно, где же здесь 12-я строка, но одновременное чтение и запись в один Dictionary из разных потоков - это верный способ получить бесконечный цикл. Dictionary очень непотокобезопасен, я лично в этом убедился :(

    http://blogs.msdn.com/b/tess/archive/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary.aspx


    My blog
    • Предложено в качестве ответа Abolmasov Dmitry 24 января 2011 г. 10:03
    • Помечено в качестве ответа QazRdx 24 января 2011 г. 10:28
    22 января 2011 г. 21:48
  • Спасибо, буду разбираться.
    22 января 2011 г. 23:46
  • Помогло блокирование записи в Dictionary, lock. Спасибо!
    23 января 2011 г. 0:30
  • Только смысла в таком "распараллеливании" нет. Для получения бонуса от многопоточности не должно быть хотя бы явных глобальных локов. Например, код выше можно переписать как var result = GroupLst.AsParallel().Distinct().ToDictionary(g => g, g => new group(g));
    My blog
    • Помечено в качестве ответа QazRdx 24 января 2011 г. 10:56
    23 января 2011 г. 0:52
  • Я поставил lock в таком месте, где он практически не влияет на ход вычислений, поскольку if пропускает управление очень редко - 1 на 1000, поэтому смысл есть - полутора-кратное ускорение. 

    if ( !GroupDct.ContainsKey(g)) {  lock (GroupDct) {GroupDct.Add (g, new group(g)); }

    Но Ваш вариант попробую проработать - это для меня новое. Спасибо.

    23 января 2011 г. 4:54
  • Опять автоматическое форматирование . я не имею к нему никакого отношения.
    23 января 2011 г. 5:04
  • lock должен быть и на Contains и на Add. иначе есть вероятность, что add вызовет перестройку dictionary, и contains сорвется в бесконечный цикл. Посмотри статью по ссылке - нам поток как раз на Contains завис :)

    А для форматирования - тут есть кнопка "вставить код". крайняя правая на тулбаре.


    My blog
    • Предложено в качестве ответа Abolmasov Dmitry 24 января 2011 г. 10:03
    23 января 2011 г. 8:57
  • На самом деле у меня сложнее - если словарь не содержит нужной группы, то он блокируется для добавления этой отсутствующей группы, в одну из групп словаря на каждой итерации добавляется запись. Т.е. словарь на каждой итерации работает на запись в каждом потоке, но блокируется только для добавления отсутствующей группы. По идее, должны быть коллизии, но пока не вижу - время счета соответствует ожидаемому. Спасибо.
    23 января 2011 г. 14:31
  • Я прекрасно вижу что у тебя, и где стоит блокировка.  :) это неправильная блокировка. Мало запретить две одновременных операции записи в Dictionary. Нужно запретить одновременное чтение и запись. Неправильная блокировка при работе Dictionary - в top 10 самых распространенных проблем при многопоточности.

    Будут не коллизии в смысле "будет чуть притормаживать". С некоторой вероятностью поток, вызывающий Contains, будет намертво зависать, отъедая 100% процессора. Не "зависать на секунду", а зависать пока процесс не убьешь, Из-за того, что другой поток в тот же самый момент вставил запись.

    Да, на тестовых данных на твоей машине не подвисает, но кто-нибудь через пол года запустит софт на 4-х процессорной машине с 8 ядрами - и на 8 потоках вероятность подвисания очень сильно подрастет.


    My blog
    23 января 2011 г. 15:18
  • ПалПалыч, спасибо за информацию! Буду рыть. Пока плотно не занимался Linq-ом, который ты посоветовал, все обмозговываю, но додумаю. Тем не менее сейчас у меня идет полноценный счет, 3-5 часов на один вариант, и все путем. Это тоже настораживает - должно глючить, а не глючит. Стоит присмотреться.
    23 января 2011 г. 17:45
  • Да, ПалПалыч, снимаю шляпу! Мой параллель работает дольше, чем не параллель, да еще и с ошибками. На тестовых примерах все было хорошо, а тут совсем не хорошо. Буду разбираться.
    24 января 2011 г. 5:40
  • Что-то топик плавно переходит в оффтоп, QazRdx, отметьте пожалуйста ответы, которые помогли решить первоначальную проблему.


    Для связи [mail]
    24 января 2011 г. 10:03
  • Да, ребята! Далеко Вам до GotDotNet-а! Там я единственный раз был свидетелем того, как модератор удалил сообщения одного чудака, который откровенно начал говорить со всеми матом... А здесь Вы удаляете наиболее важную информацию из темы только потому, что она сообщена не совсем в том формате, который Вам нравится. Не правильно это!
    31 января 2011 г. 9:28
  • Ничего не удалялось, топик был разделен на 2, вот ваши сообщения - Потокобезопасный Dictionary

     


    Для связи [mail]
    31 января 2011 г. 9:38
  • Если Вы что-то правите, то Вы должны 1.Сохранить первичный документ в том месте, где он появился; 2. Дать линк на точку, куда Вы отослали его копию. Это - основополагающие принципы сохранения и поддержания документооборота.
    31 января 2011 г. 10:04
  • Форум - не sharepoint :) он позволяет только разрезать темы, но не копировать часть сообщений.

    По поводу ссылки - лично я получил письмо "Модератор отделил обсуждение, на которое вы подписаны.", со ссылкой на новую тему. IMHO, этого более чем достаточно.


    My blog
    31 января 2011 г. 10:10
  • А я ничего не получил, также как и все остальные, интересующиеся этой темой. В этом-то и проблема - тема где-то продолжается по чьему-то хотению, а никого об этом не уведомили.
    31 января 2011 г. 10:40
  • Должны были получить все, кто подписан на нотификации в теме, и у кого в профиле включены нотификации. Раз уж я получил, хотя не я разрезал тему. (которой грозит еще одно разрезание)

    Обычные письма о новых ответах приходят?


    My blog
    31 января 2011 г. 11:18
  • Для того, чтобы получать уведомления у вас в профиле должны быть включены оповещения и указана почта, на которую и будут приходить эти самые оповещения. По умолчанию, если у вас задана почта для уведомлений и вы задали вопрос или ответили в существующей теме, то вы автоматически подписываетесь на все изменения данной темы и получаете на почту уведомления о произошедших изменениях. Это достаточно удобный механизм, рекомендую настроить и пользоваться им.

    По поводу вопросов-ответов - следует стараться придерживаться правила: один топик - один вопрос, так чтобы в итоге было удобно другим пользователям находить ответы, на решенные проблемы. Т.е. пользователь, нашедший данный топик будет видеть проблему,а сразу после нее - решение. Если же обсуждать в теме много и разное, то и ответов будет много и они не будут связаны между собой. Пользователю будет сложно понять, как все таки решается проблема. Ему придется прочитать и вникнуть во всю ветку обсуждения.


    Для связи [mail]
    31 января 2011 г. 12:00
  • Как я уже неоднократно говорил, Ваш сайт глючит! Я до сих пор не имею возможности полноценно загружать Ваши страницы, со всеми вытекающими отсюда "удобствами", о которых Вы говорите, и которых я не вижу. В любом случае, было бы правильней и надежней делать то, о чем я говорил в предыдущем сообщении - ведь темы просматривают не только те, кто подписан на них, но и те, кто не подписан.
    31 января 2011 г. 13:47