Re[12]: Как оптимизировать выполнения 10000 параллельных зад
От: LWhisper  
Дата: 08.08.16 15:49
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Не работал с этой библиотекой и этим примитвом. Поверхостный просмотр github'а выдал такой комментарий для метода wait (что логично):

S>

S>Synchronously waits for this event to be set. This method may block the calling thread.


Да, для метода Task.Run().Wait(). В моём случае — Task.Run(async delegate) без Wait.
Поэтому, либо что-то не так с кодом автора (но он пишет умные книжки про асинки), либо в моей реализации, но она как раз использует его логику.
В принципе, банальная логика подсказывает, что мы не можем вызывать Monitor.Enter/Exit из разных потоков. Следовательно, они вызываются в одном потоке. Следовательно, он блокируется и висит в очереди на блокировке. Как это может работать иначе — не знаю. Но выше по треду, рекомендовали именно такой вариант. Вот я и пытаюсь разобраться — чем он лучше обыкновенного ManualResetEvent.Wait().

S>Вроде бы WhenAll (ContinueWhenAll), который появился в версии фреймворка 4.5. Я использую библиотеку ParallelExtensionsExtras, который дополняет функциональность 4.0.

WhenAll действительно запустит продолжение в новом потоке, но если текущий повиснет на блокировке, мы получим ровну ту же самую ситуацию с висящим потоком, который не возвращается в пул.
Re[12]: Как оптимизировать выполнения 10000 параллельных зад
От: LWhisper  
Дата: 08.08.16 16:01
Оценка: 44 (1) +1
Здравствуйте, Serginio1, Вы писали:

S> Ны дык все их нужно заменять на аналоги

S>Microsoft.VisualStudio.Threading

S>AsyncReaderWriterLock

S>AsyncAutoResetEvent()

S> И только там , где это невозможно использовать потоки. При этом получится гибридная система, но с минимумом ручных потоков.

Понял, как это работает! Спасибо!
Фактически, мы виси не на локе внутри метода, а возвращаем таску, помещённую в очередь. Когда же приходит Set, для таски выставляется результат выполнения.
Неверно истолковал использование лока внутри AsyncAutoResetEvent.
Re[12]: Как оптимизировать выполнения 10000 параллельных зад
От: LWhisper  
Дата: 08.08.16 16:04
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>Не работал с этой библиотекой и этим примитвом.

Ниже Serginio1 привёл AsyncAutoResetEvent из сборки VisualStudio.
На самом деле, мы виснем на локе (он нужен лишь для синхронизации очереди авайтеров), а на таске, которая конструируется, но не запускается благодаря TaskCompletionSource.
Когда кто-нибудь дёргает Set(), для каждой таски в очереди выставляется результат и срабатывает назначенное посредством await продолжение.
Re[3]: Как оптимизировать выполнения 10000 параллельных задач?
От: Sharowarsheg  
Дата: 08.08.16 16:16
Оценка:
Здравствуйте, LWhisper, Вы писали:

S>>А что тут оптимизировать и зачем? Что-то объективно медленно работает? Процессоры недогружены или перегружены? Что там вообще с CPU usage в установившемся режиме? Ну повисли они в thread.sleep, и пусть себе спят — это довольно эффективно, даже если их много.

LW>В процессе сборки мусора, GC приостанавливает все потоки. Когда их 10000, это начинает бить по производительности. Новые потоки висят в ожидании GC. Растёт очередь финализации. К сожалению, у меня недостаточно знаний о работе GC на низком уровне, чтобы обосновать происходящее. За сим и пришёл.

Ну, с этим всё просто — нужно больше повторно использовать буферы. Ну то есть, если GC жрет дофига времени, то нужно смотреть, как бы уменьшить потребность в GC, а не биться с потоками. Ну или в крайнем тяжелом случае перейти к какой-нибудь версии .NET поновее, у которой менее блокирующее GC.
Re[13]: Как оптимизировать выполнения 10000 параллельных зад
От: Sharov Россия  
Дата: 08.08.16 16:20
Оценка:
Здравствуйте, LWhisper, Вы писали:

LW>Здравствуйте, Sharov, Вы писали:


S>>Не работал с этой библиотекой и этим примитвом. Поверхостный просмотр github'а выдал такой комментарий для метода wait (что логично):

S>>

S>>Synchronously waits for this event to be set. This method may block the calling thread.


LW>Да, для метода Task.Run().Wait(). В моём случае — Task.Run(async delegate) без Wait.

LW>Поэтому, либо что-то не так с кодом автора (но он пишет умные книжки про асинки), либо в моей реализации, но она как раз использует его логику.
LW>В принципе, банальная логика подсказывает, что мы не можем вызывать Monitor.Enter/Exit из разных потоков. Следовательно, они вызываются в одном потоке. Следовательно, он блокируется и висит в очереди на блокировке. Как это может работать иначе — не знаю. Но выше по треду, рекомендовали именно такой вариант. Вот я и пытаюсь разобраться — чем он лучше обыкновенного ManualResetEvent.Wait().

Все вроде так. А лучше тем, что сдает поток обратно в пул, т.е. поток подхватывает другую задачу и т.д. Потом проверит статус event'а. Я понял это так, ибо дело с этой библиотекой и примитивами не имел.

S>>Вроде бы WhenAll (ContinueWhenAll), который появился в версии фреймворка 4.5. Я использую библиотеку ParallelExtensionsExtras, который дополняет функциональность 4.0.

LW>WhenAll действительно запустит продолжение в новом потоке, но если текущий повиснет на блокировке, мы получим ровну ту же самую ситуацию с висящим потоком, который не возвращается в пул.

Ну так переходите на async io, для всех блокирующих io вызов еще со времен второго фреймворка сущ. асинхронные аналоги. А к асинхронным callback'ам можно и task'и подвязать. Больше Вам ничего не поможет. Все эти однопоточные серверы c10k типа tornado (python) или node.js построены вокруг асинхронных io операций.
Кодом людям нужно помогать!
Отредактировано 08.08.2016 16:31 Sharov . Предыдущая версия . Еще …
Отредактировано 08.08.2016 16:31 Sharov . Предыдущая версия .
Re[13]: Как оптимизировать выполнения 10000 параллельных зад
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 09.08.16 08:33
Оценка:
Здравствуйте, LWhisper, Вы писали:

LW>Здравствуйте, Serginio1, Вы писали:


S>> Ны дык все их нужно заменять на аналоги

S>>Microsoft.VisualStudio.Threading

S>>AsyncReaderWriterLock

S>>AsyncAutoResetEvent()

S>> И только там , где это невозможно использовать потоки. При этом получится гибридная система, но с минимумом ручных потоков.

LW>Понял, как это работает! Спасибо!
LW>Фактически, мы виси не на локе внутри метода, а возвращаем таску, помещённую в очередь. Когда же приходит Set, для таски выставляется результат выполнения.
LW>Неверно истолковал использование лока внутри AsyncAutoResetEvent.

Так скажем
И задача на await если нет сигнала просто заканчивает работу в потоке и возвращает его в пул.
Когда приходит Set, код на await продолжается в новом потоке.
Там внутри метод на соновании метода создается класс, переменные метода становятся свойствами класса и метод разбивается на методы, и соответсвенно переходы по состоянию.
Я в свое время писал замену рекурсивного обходчика http://rsdn.org:8888/article/alg/tlsd.xml
Автор(ы): Сергей Смирнов (Serginio1)
Дата: 14.08.2004
Пример реализации двухуровневого массива с помощью нового средства С# — generics. Сравнение производительности различных реализаций сортированных списков.
так суть yield та же. Создать отдельный класс с сохранением состояние в свойствах метода и двигаться в зависимости от текущего состояния. КА.

Set просто вызывает ContinueWith задачи.
и солнце б утром не вставало, когда бы не было меня
Re: Как оптимизировать выполнения 10000 параллельных задач?
От: Tom Россия http://www.RSDN.ru
Дата: 10.08.16 18:25
Оценка: :)
Здравствуйте, LWhisper, Вы писали:

LW>Всем привет.


LW>В настоящий момент я запускаю на выполнение 10000 параллельных задач посредством new Thread(...).Start().

LW>Вначале они дерутся за процессорное время, но вскоре повисают на ожидании чего-либо — блокировок, ответа от сокета, просто в Thread.Sleep

LW>Существуют ли какие-либо рекомендации по оптимизации подобных сценариев? Исходим из того, что реально одновременно выполняться может не больше 128 потоков, остальное время мы вынуждены гонять контекст между ними. Но из-за вышеупомянутых задержек, 10000 потоков с постоянным переключением контекста, работают быстрее, нежели 128, которые большую часть времени жизни спят.


Запустите 10000 процессов это точно будет лучше и система e; точно будет шевелиться
Народная мудрось
всем все никому ничего(с).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.