|
|
|
std::async
|
|||
|---|---|---|---|
|
#18+
featureDima TТут все оптимально, но можно словить тормоз почти на порядок на ровном месте А какое отношение false sharing, размерность cache line и обеспечение cache coherence в родимой ccNUMA имеет к простаивающим тредам, удерживающих память под стэк и thread local storage? Нифига не понял, пиши по-русски ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 20:42 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
semen.s.semenDima TКак устроен std::async я не в курсе Вопрос был по экспертизе в работе std::async без троллинга и с документированным и аргументированным обоснованием. Однозначно отказаться от использования и вводить запрет на использование. Аспекты работы std::async недетерминированы, из-за чего использование такового в продакшене потребует постоянного контроля и излишних проверок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 20:52 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
featureАспекты работы std::async недетерминированы А если я вместо std::async создам вектор std::thread и дождусь их выполнения ? Это тру подход для прода ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 20:56 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
p.s.: процедура многопоточного выполнения запускается разово и нечасто ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 20:59 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
semen.s.semenp.s.: процедура многопоточного выполнения запускается разово и нечасто Оцени затраты. На калькуляторе дорого отдельный поток держать, холодильник - не знаю, а для обычного проца, даже телефона, это незаметно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 21:09 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
semen.s.semenА если я вместо std::async создам вектор std::thread и дождусь их выполнения ? Это тру подход для прода? Быстренько и по простому — это когда по одному треду на задачу, из-за того, что задач планируется максимум на сотню штук? Это всё равно «технический долг». Завтра коллега отдаст этой подсистеме 100500 задач, в голову ему не могло прийти, что там создаётся по треду на задачу. Вроде и ничего страшного, ну сожрут сорок Гб виртуальной памяти. Косяк будет в накладных расходах на переключении контекста, когда шетдулер ОС пытается всем поровну выделить кванты процессорного времени. А начав активно писать по выделенным адресам памяти, эти треду вызовут в ОС лавину soft page fault'ов. Самый простой и трушный подход для прода — это вектор тредов размерности (мощности множества) в N+1, где N = количество реальных ЦПУ в системе, без гипертрединга. Когда задачами эти треды кормяться из общего котла (очередь, стек, кольцевая очередь) с замком на крышке в виде std::shared_mutex — множество читателей и один писатель. Хоть миллион задач придёт в эту подсистему, а весь солюшен в целом останется жизнеспособен. Напишет в лог с соответствующим северити (info/warning), что как-то шибко много задач, но будет их спокойно лопатить, не провоцируя ОС на аварийное завершение всего солюшена. P.S. Если уж ну совсем, с-о-в-с-е-м у-с-ё л-е-н-и-в-о и нормальным путём ну никак идти не получится, то хотя бы кидать эксепшен увидев слишком большое число задач перед тем, как создавать треды. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 21:56 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
featuresemen.s.semenА если я вместо std::async создам вектор std::thread и дождусь их выполнения ? Это тру подход для прода? Быстренько и по простому — это когда по одному треду на задачу, из-за того, что задач планируется максимум на сотню штук? Это всё равно «технический долг». Завтра коллега отдаст этой подсистеме 100500 задач, в голову ему не могло прийти, что там создаётся по треду на задачу. Вроде и ничего страшного, ну сожрут сорок Гб виртуальной памяти. Косяк будет в накладных расходах на переключении контекста, когда шетдулер ОС пытается всем поровну выделить кванты процессорного времени. А начав активно писать по выделенным адресам памяти, эти треду вызовут в ОС лавину soft page fault'ов. Самый простой и трушный подход для прода — это вектор тредов размерности (мощности множества) в N+1, где N = количество реальных ЦПУ в системе, без гипертрединга. Когда задачами эти треды кормяться из общего котла (очередь, стек, кольцевая очередь) с замком на крышке в виде std::shared_mutex — множество читателей и один писатель. Хоть миллион задач придёт в эту подсистему, а весь солюшен в целом останется жизнеспособен. Напишет в лог с соответствующим северити (info/warning), что как-то шибко много задач, но будет их спокойно лопатить, не провоцируя ОС на аварийное завершение всего солюшена. P.S. Если уж ну совсем, с-о-в-с-е-м у-с-ё л-е-н-и-в-о и нормальным путём ну никак идти не получится, то хотя бы кидать эксепшен увидев слишком большое число задач перед тем, как создавать треды. Нет тут никакого параллелизма Процедура запускается разово под жестким локом и никто в параллель ничего не делает. То что число тредов = числу ядер это и обидчевому семену понятно. Вопрос по С++ std::vector<std::thread> bla bla bla for () thread.join(); После выхода из метода ВСЕ созданные треды реально подохнут без всяких зомби и незакрытых хендлов ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 22:01 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
semen.s.semen, Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. т.е. за пределами local | function scope, если про объекты std::thread созданные на стэке. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 22:18 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
featuresemen.s.semen, Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. т.е. за пределами local | function scope, если про объекты std::thread созданные на стэке. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Понял спасибо И последний вопрос Как правильно передавать исключения из созданных потоков в исходный тред ? Я читал про std::promise, std:future, что будет самым верным решением ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 22:26 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
semen.s.semen, скорее выбор должен быть между std::promise и std::packaged_task, в обоих случаях std:future служит средством доступа к создаваемому шаренному состоянию. вполне грамотно делать так: Код: plaintext 1. 2. 3. 4. 5. 6. и да, кстати, платой за использование std::thread является хорошо известная неприятность — делать join() явно на каждый тред можно лишь когда гарантирована exception safety между вызовом join() и моментом создания треда. В остальных случаях следует использовать простенький самописный thread_guard, который при выбрасывания исключения (размотке стэка) сделает или join или detach для треда. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 23:42 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
Раз уж тут ведется такая познавательная беседа может и меня просвятят... featureвектор тредов размерности (мощности множества) в N+1, где N = количество реальных ЦПУ в системе, без гипертрединга Понимаю, что это правильно с теоритеческой точки зрения, но никогда не понимал как этого можно достичь на практике? Этот совет во всех книжках идет, но либо я - дурак, либо авторы этих советов живут в каком-то розово-плюшевом королевстве. В современной ОС помимо тебя крутятся еще десятки приложений, поэтому процессор пусть и по чуть-чуть но загружен потоками в количествах измеряемых тысячами. Откройте свой менеджер задач и посмотрите сами, сколько там дескрипторов потоков открыто. Да, большинство из них спят, но чисто технически даже на 16 ядерном компе, удовлетворить условию "одно ядро - один поток" тысячеголовую араву потоков mission impossible, поэтому переключения контекстов неизбежно будут. Возможно это правило относится к каждому из процессов и ОС, как-то по своему разруливает это на макроуровне процессов, но я нигде про это не встречал инфы. ОК, тогда один процесс - N+1 количество потоков - и так ДОЛЖНО БЫТЬ у каждого процесса, но опять же, как можно удовлетворить данному требованию в современной ОС? И речь даже не о том, что кто-то криворук или неграмотен и не следует "золотому' правилу. Возьмем к примеру Windows. Современные программы уже никто не пишет с С++ библиотеками рассчитанными на однопоток, следовательно мультитред у нас уже заложен на уровне самой библиотеки компилятором. А это сильно развязывает ОС и прочим прилипалам к процессам руки. Современные ОСи по умолчанию включают в вашу программу собственный пул потоков процесса, не считая того, что программист к этому пулу может создавать свои собственные до кучу. Кроме того, вот я запускаю свою службу. Служба по умолчанию должна работать в отдельном потоке управляемом SCM (то есть минус один поток из моей программы). Служба наверное не на святой воде работает и не для простоя предназначена, значит нужно проинициализировать ряд вспомогательных подсистем. Проинициализировал COM - хоп! и в твоем процессе еще один вспомогательный поток, который ты в явном виде не создавал (большинство пишущих формочки для форточек вообще про это не знают даже). Проинициализировал терминальный API - хоп! и еще один - Event ловушка. Кто-то решил кинуть глобальный хук - хоп! и к твоему процессу присосалось несколько DLL, который тоже могут жить в собственных потоках. Система постоянно что-то там тоже мониторит, счетчики считает PerfMon, Event'ы. И вот у тебя в потоке уже куча соседей, которых ты не приглашал (в явном виде)! Поэтому вместо 10 открытых дескрипторов ты стартуешь с нуля уже со 100-150 объектами ядра (не обязательно потоков) в твоем процессе, а потом сидишь и башку ломаешь, где же я столько ресурсов разлил!? И т.д. поэтому когда я запускаю свое ПО и потом смотрю в Process Explorer'e на свои и чужие потоки, то я просто охреневаю , сколько желающих посидеть за мой счет! Ну и что же у нас в таком случае остается от этой волшебной формулы. Да ничего! Если у тебя не Ryzen Threadripper какой-нибудь, а желательно 2-3 таких же. Вот я и не понимаю, как я могу обеспечить это красивое N+1! Это либо какой сферический конь в вакууме, либо я просто не умею его готовить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2019, 23:52 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
Cerebrum, А как же внимательность при потреблении информации с книжек и остальных мест? Упоминаемое N+1 актуально лишь для активно работающих потоков, т.е. когда надо получить максимальное количество выполненной работы за единицу времени от машины с несколькими ЦПУ (физическими ядрами). Все остальные треды в ОС или не участвуют в попытках получения квантов времени ЦПУ или же их потребности в вычислительных ресурсах незначительны и для них хватает побочных/второстипенных мощностей гипертрейдинговых потоков. Современный ЦПУ x86 уже давно не CISC, а множество RISC-устройств в рамках каждого ядра. Отсюда и возможность выполнения более чем одного потока на одном ядре одновременно (гипертрединг). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 00:02 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
feature, да, я полностью согласен. Я это понимаю, что фактически их потребности ничтожны, как правило, пока никто не укладывает 1-2 ядра на лопатки. У меня есть парк из нескольких сотен хостов, с которых при одном запросе я должен получить сведения. Например, это терминальники или веб серверы и программа по запросу от пользователя должна опросить их на предмет того, на каком из них сидит сейчас пользователь с ником ИванИваныч. Если я эти сотни буду опрашивать через пул потоков максимальной емкостью = кол-ву ядер, я просто могу сразу тогда идти заваривать кофе и советовать делать тоже самое тетям-менеджерам в саппорте. А параллельно с этим к программе прилетает еще десяток аналогичных запросов, требующих интенсивного общения с удаленными хостами и тогда они станут в очередь. Поэтому, где могу я стараюсь придерживаться правильного подхода, но где-то он тупо неприменим. И как показывает моя практика не применим практически нигде. Я лучше организую десятка 3-4 медленно живущих потоков, чем буду постоянно надрючивать 8 завязанных по самое небалуйся. В каком-нибудь десктопном 1С, подход N+1 еще может взлететь, но в серверном сегменте, когда у тебя огромный парк техники - нужен какой-то другой подход. Поэтому у меня все свое - пулы, потоки, планировщики и пр. С std не связываюсь, потому что нужен за всем контроль. За пренебрежение правилами приходится платить перекосом кода в сторону его проживания в режиме ядра, переключениями контекстов и лавин soft page fault'ов , с чем я пытаюсь по мере сил бороться, но все равно выходит так себе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 00:23 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
Cerebrum, серверный сегмент с огромным парком техники — это когда число машин на несколько порядков больше, чем несколько сотен. Из своего личного, субъективного опыта, в таких системах прекрасно работают стандартные подходы и решения/паттерны. Для примера, зачем плодить множество тредов в пуле, когда дело упирается в создание подсистемы асинхронных вызовов удалённых хостов, поверх пула tcp-коннекций, реализованных посредством неблокирующихся беркли-сокетов? Если такая система постоянно нагруженна обращениями, распределяя, отправляя и собирая их с удалённых хостов, то на кой лад в ней три десятка тредов на 16 ядрах? Потому если проблему и искать, то именно в том человеке, что стоит у руля. По ряду причин с ним не хотят работать даже мало мальски приличные специалисты. Такое случается, когда человек самоучка прошедший некоторый путь, но в сфере фриланса, среди доморощенных специалистов «от сохи». Потому никогда не видел работы профессионалов и неспособен опознать, оценить предлагаемые ими решения. А профи не любят работать с теми, кто неспособен оценить их собственные уровень и вклад в проект. В любом случае, это всё надо выводить в отдельный тред и обсуждать исходя из контекста отдельной предметной специфики. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 01:48 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
feature, Только все же наверно join, а не wait... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 02:32 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
CerebrumРаз уж тут ведется такая познавательная беседа может и меня просвятят... featureвектор тредов размерности (мощности множества) в N+1, где N = количество реальных ЦПУ в системе, без гипертрединга Понимаю, что это правильно с теоритеческой точки зрения, но никогда не понимал как этого можно достичь на практике? Этот совет во всех книжках идет, но либо я - дурак, либо авторы этих советов живут в каком-то розово-плюшевом королевстве. В современной ОС помимо тебя крутятся еще десятки приложений, поэтому процессор пусть и по чуть-чуть но загружен потоками в количествах измеряемых тысячами. Откройте свой менеджер задач и посмотрите сами, сколько там дескрипторов потоков открыто. Да, большинство из них спят, но чисто технически даже на 16 ядерном компе, удовлетворить условию "одно ядро - один поток" тысячеголовую араву потоков mission impossible, поэтому переключения контекстов неизбежно будут. Возможно это правило относится к каждому из процессов и ОС, как-то по своему разруливает это на макроуровне процессов, но я нигде про это не встречал инфы. ОК, тогда один процесс - N+1 количество потоков - и так ДОЛЖНО БЫТЬ у каждого процесса, но опять же, как можно удовлетворить данному требованию в современной ОС? И речь даже не о том, что кто-то криворук или неграмотен и не следует "золотому' правилу. Возьмем к примеру Windows. Современные программы уже никто не пишет с С++ библиотеками рассчитанными на однопоток, следовательно мультитред у нас уже заложен на уровне самой библиотеки компилятором. А это сильно развязывает ОС и прочим прилипалам к процессам руки. Современные ОСи по умолчанию включают в вашу программу собственный пул потоков процесса, не считая того, что программист к этому пулу может создавать свои собственные до кучу. Кроме того, вот я запускаю свою службу. Служба по умолчанию должна работать в отдельном потоке управляемом SCM (то есть минус один поток из моей программы). Служба наверное не на святой воде работает и не для простоя предназначена, значит нужно проинициализировать ряд вспомогательных подсистем. Проинициализировал COM - хоп! и в твоем процессе еще один вспомогательный поток, который ты в явном виде не создавал (большинство пишущих формочки для форточек вообще про это не знают даже). Проинициализировал терминальный API - хоп! и еще один - Event ловушка. Кто-то решил кинуть глобальный хук - хоп! и к твоему процессу присосалось несколько DLL, который тоже могут жить в собственных потоках. Система постоянно что-то там тоже мониторит, счетчики считает PerfMon, Event'ы. И вот у тебя в потоке уже куча соседей, которых ты не приглашал (в явном виде)! Поэтому вместо 10 открытых дескрипторов ты стартуешь с нуля уже со 100-150 объектами ядра (не обязательно потоков) в твоем процессе, а потом сидишь и башку ломаешь, где же я столько ресурсов разлил!? И т.д. поэтому когда я запускаю свое ПО и потом смотрю в Process Explorer'e на свои и чужие потоки, то я просто охреневаю , сколько желающих посидеть за мой счет! Ну и что же у нас в таком случае остается от этой волшебной формулы. Да ничего! Если у тебя не Ryzen Threadripper какой-нибудь, а желательно 2-3 таких же. Вот я и не понимаю, как я могу обеспечить это красивое N+1! Это либо какой сферический конь в вакууме, либо я просто не умею его готовить. Ты вазе умеешь отличать работающий поток от простающего? Это формула - для реально работающих. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 02:42 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
MasterZivfeature, Только все же наверно join, а не wait... Чего-чего? Слово wait в треде ещё не встречалось. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 02:56 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
MasterZiv, Прекрасно знаю, но предпочитаю оперировать понятиями: поток есть, потока нет. Все эти якобы спящие потоки, моментально становятся планируемыми, как только твои потоки начинают свою деятельность. Ведь для этого они туда и подсосались. Самый быстрый код - это тот, который ты не стал писать. Самый быстрый многопоток - в котором 1 или 0 потоков. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 09:41 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
полудух, спасибо, ознакомлюсь ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 09:42 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
Cerebrum, вы правильно заметили, правильно заданый вопрос это половина ответа кто лучше всего знает о состоянии загруженности ядер системы и нагрузке потоков? ответ довольно очевиден: - ОС что даёт ОС для решения этого вопроса - автопул что должен делать рантайм для оптимальной реализации выполнения? - переложить неясные вопросы на ОС отсюда первый вывод: в падавляющем большинстве случаев юзай согласно интерфейса и не парься до возникновения проблем обнаружил затыки - оптимизируем дальше считашь что планировщик ОС не справляется, нити в руки и сам менеджерь, написать свою точечную реализацию async хоть и напряжно, но вполне по силам среднему разрабу ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 10:06 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
Зачем всё это теоретизирование? Достаточно взять нечто из вычислительных задач. Распараллелить расчёт на несколько тредов и посмотреть, при каком раскладе задача быстрее всего посчитается. Когда она распределена между 10 потоками на 8-ми ядерном ЦПУ или же, когда этих самых потоков 30 штук на той же самой системе. Чтобы уж совсем научно было, то повторить эксперимент не один раз и посмотреть какому распределению соответствует разница производительности между этими двумя подходами. Это всё, в итоге, будет ответом про эффективность подходов многопоточности применимо к parallel computing. Однако, есть ещё и concurrent computing , говорить о котором имеет смысл, лишь проведя такие же эксперименты. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2019, 23:54 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
как сказал Ульрих: не надо запускать 20 процессов с сотней потоков в каждом на машине с 16ю ядрами, это overpower. Не нужна такая крутая машина. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2019, 04:44 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
featureЗачем всё это теоретизирование? Достаточно взять нечто из вычислительных задач. Распараллелить расчёт на несколько тредов и посмотреть, при каком раскладе задача быстрее всего посчитается. Когда она распределена между 10 потоками на 8-ми ядерном ЦПУ или же, когда этих самых потоков 30 штук на той же самой системе. Чтобы уж совсем научно было, то повторить эксперимент не один раз и посмотреть какому распределению соответствует разница производительности между этими двумя подходами. Это всё, в итоге, будет ответом про эффективность подходов многопоточности применимо к parallel computing. Однако, есть ещё и concurrent computing , говорить о котором имеет смысл, лишь проведя такие же эксперименты.конечно, и сразу с железом и своей ОС прогу поставлять ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2019, 09:47 |
|
||
|
std::async
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)конечно, и сразу с железом и своей ОС прогу поставлять Пора привыкнуть к необходимости проверять, без жевания соплей и диванных теоретизирований. Продукт либо может эффективно работать в заявленной ОС и на заявленном железе, либо теоретиков гонят ссаными тряпками на улицу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2019, 12:55 |
|
||
|
|

start [/forum/topic.php?fid=57&gotonew=1&tid=2017684]: |
0ms |
get settings: |
10ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
178ms |
get topic data: |
13ms |
get first new msg: |
8ms |
get forum data: |
3ms |
get page messages: |
88ms |
get tp. blocked users: |
2ms |
| others: | 213ms |
| total: | 539ms |

| 0 / 0 |
