WedX - журнал о программировании и компьютерных науках

самый быстрый способ разбудить поток без использования условной переменной

Я пытаюсь ускорить часть кода, уже настроив фоновые потоки для решения одной конкретной задачи. Когда пришло время решить мою задачу, я хотел бы разбудить эти потоки, выполнить задание и снова заблокировать их в ожидании следующей задачи. Задача всегда одна.

Я пытался использовать условные переменные (и мьютекс, который должен идти с ними), но в итоге я замедлил свой код, а не ускорил его; в основном это произошло из-за того, что вызовы всех необходимых функций очень дороги (pthread_cond_wait/pthread_cond_signal/pthread_mutex_lock/pthread_mutex_unlock).

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

Есть ли у вас какие-либо предложения для быстрого пробуждения без использования mutex или con_var?

Я думал о потоках настройки, таких как таймеры, читающие atomic variable; если переменная установлена ​​в 1, потоки будут выполнять работу; если установлено значение 0, они перейдут в спящий режим на несколько микросекунд (я бы начал с микросекундного сна, так как хотел бы избежать использования spinlocks, который может быть слишком дорогим для процессора). Что вы думаете об этом? Любое предложение очень ценится.

Я использую Linux, gcc, C и C++.


  • Если ваши требования к производительности слишком велики для существующего подхода с мьютексом/переменной-условием, то вы уже находитесь на той стадии, когда вы хотите сжечь немного процессорного времени для дополнительной работы, прежде чем вернуться к мьютексу/переменной-условию. Микросекундный сон может работать не так, как вы ожидаете: если ваш процесс не распланирован, то процессор все равно не получает другой работы, и если это так, ваши задержки могут резко возрасти. 08.04.2011
  • Привет Тони. У меня многоядерная машина NUMA. Правда ли, что в этом случае у меня не должно быть никакого переключения контекста? Я создаю поток без какой-либо конкретной настройки или конфигурации... как вы думаете, требуются ли какие-либо специальные настройки, чтобы избежать переключения контекста? 08.04.2011
  • @Abruzzo: есть много факторов, доминирующим из которых является то, что логика планирования изменилась с версиями ядра Linux. Но, в общем, если вы скажете планировщику, что вам нечего делать и что-то ждет, я бы не стал делать ставку на то, что он вас удержит (больше шансов, если ваш период задержки в любом случае явно находится внутри временного среза). При любой серьезной настройке разумные деньги уходят на реализацию альтернатив и сравнительный анализ с вашим реальным оборудованием, компиляторами, размерами задач, частотой конфликтов, потоками данных, версией ядра и т. д. 08.04.2011
  • Я бы предложил lock-free алгоритм с использованием внутреннего конечного автомата, если задача его устраивает. 08.04.2011
  • @Blagovest, можешь подробнее? Вы имеете в виду цикл while вокруг переменной, сохраняющей состояние? Я не понимаю, как использовать их для моей проблемы, то есть сделать мои потоки действительно реактивными на некоторые события и сказать им, чтобы они приступили к выполнению моих задач, как только они смогут. 08.04.2011
  • @Blagovest: другими словами, чистое вращение в ожидании событий ... если у вас есть процессор, который нужно сжигать, и вам нужна минимальная задержка, вы не сможете победить его. 08.04.2011
  • Я упал, как будто мне начинает нравиться эта идея ... всего 1 ядро ​​​​выделено для этой задачи; если я установлю сходство потоков, это не повредит другим процессам, работающим на других процессорах (при условии, что сходство для них установлено правильно). 08.04.2011
  • @Tony @Blagovest большое спасибо за ваши ответы. Хорошего дня. С наилучшими пожеланиями AFG 08.04.2011
  • @Abruzzo: не беспокойтесь - оставьте заметку, чтобы сказать, как это работает для вас. Ваше здоровье. 08.04.2011
  • Эти задачи должны перекрываться во времени на разных ядрах? Если нет, многопоточность ничего вам не даст. 09.04.2011
  • @Mike Я думал создать по одному дополнительному потоку на ядро. Почему вы говорите, что ничего не платит? Я думал, что, будучи многоядерным, каждое ядро ​​​​действительно независимо, имея свои часы. Можете ли вы уточнить немного? 11.04.2011
  • Да, каждое ядро ​​может работать параллельно с другими. Но каков характер выполняемых задач? Можете ли вы на самом деле получить 2 или более ядер, выполняющих задачи одновременно, или вы можете запускать только одну задачу за раз, следовательно, только одно ядро ​​за раз? Вот к чему я веду. Если работа в основном последовательная, а не параллельная, многопоточность на нескольких ядрах не ускорит ее. 11.04.2011
  • Характер задачи параллельный. 11.04.2011

Ответы:


1

Эти функции должны быть быстрыми. Если они занимают большую часть вашего времени, вполне возможно, что вы слишком часто пытаетесь переключаться между темами.

Попробуйте буферизовать рабочую очередь и отправить сигнал после накопления значительного объема работы.

Если это невозможно из-за зависимостей между задачами, то ваше приложение вообще не поддается многопоточности.

08.04.2011
  • Это фактически происходит в любом случае... т. е. если обработка исходных событий недостаточно быстрая, следующие несколько буферизируются. Итак, кажется, проблема заключается в улучшении задержки на передних кромках.... 08.04.2011
  • @Tony: Следующие несколько не буферизуются и даже не создаются, потому что основной поток блокируется. Это стратегия уменьшения общего количества вызовов библиотеки потоков для данного рабочего набора. 08.04.2011
  • @Potatoswatter: я просто говорю, что потребляющий поток уже должен очищать очередь всех доступных запросов, прежде чем ждать уведомлений о дальнейших событиях (т. Е. Не потреблять их по одному); Я согласен, что это проблема, если приложение не было разработано таким образом. Я не уверен, но я думаю, что вопрос больше в том, чтобы получить стабильную низкую задержку для частых, но тривиально обрабатываемых событий, например. микросекунды для обработки, микросекунды друг от друга. Абруццо...? 08.04.2011
  • @Тони. Вот так. Я даже не использую очереди, так как моя задача идеально разделена на что-то частое, но тривиальное, и я хотел бы, чтобы ее быстро обрабатывали 3 или 4 потока. Итак, моя задача может быть разделена на 4 задачи для 4 потоков; если они быстро запускаются / просыпаются при выполнении задачи, то у меня низкая задержка. 08.04.2011
  • @Tony: на задержку не должно влиять время lock, потому что оно вызывается главным потоком после signal. Остается unlock, который является быстрым, и cond_signal, и последовательность возврата из cond_wait, которая должна быть примерно такой же быстрой, как любой путь пробуждения в pthreads. Это не значит, что нет более быстрого способа, но если конечной целью не является определенная задержка, то этого вполне достаточно. Что касается по очереди, то, по моему опыту, очередь может идти по одной, если вы не установите минимальный размер, что приводит к избыточному времени в lock/unlock/signal/cond_wait. 08.04.2011
  • @Abruzzo: Насколько тривиальна задача? Является ли задержка важной для приложения, или вы бы предпочли пожертвовать ею ради пропускной способности? 08.04.2011

  • 2

    Чтобы повысить производительность многопоточного приложения, создавайте столько потоков, сколько есть процессоров, а не отдельный поток для каждой задачи. В противном случае вы получите много накладных расходов из-за переключения контекста.

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

    08.04.2011
  • Количество потоков уже равно количеству процессоров. Знаете ли вы какие-либо настройки или принудительные настройки / атрибуты, ЧТОБЫ УБЕДИТЬСЯ на 100%, что у меня нет переключения контекста? У меня есть многоядерный компьютер, который также является машиной NUMA. 08.04.2011
  • Отсутствие переключения контекста означает прекращение использования потоков :-) Подумайте о том, чтобы ваш алгоритм не блокировался. Например, посмотрите, как серверы Nginx и Lighttpd сделаны без потоков для каждого входящего соединения. 08.04.2011
  • @Abruzzo Forte e Gentile Вам нужна операционная система реального времени, чтобы дать такие гарантии. Вы можете подойти довольно близко, если используете планировщик реального времени SCHED_FIFO в linux, в дополнение к закреплению ваших потоков на конкретном процессоре (через сходство процессов), см. справочную страницу для sched_setscheduler. Однако, если ваша логика может себе это позволить, вы можете ставить элементы в очередь и отправлять их пакетами рабочим процессам. Прирост пропускной способности, который я получил от постановки в очередь 10 элементов и запуска переменной pthread_cond по сравнению с запуском ее для каждого элемента, значителен 08.04.2011
  • Моя задача имеет некоторую степень параллелизма, которую я хочу использовать с дополнительными потоками. Я могу использовать концепции без блокировки, но мне нужно, чтобы мои потоки уже были созданы в фоновом режиме и быстро ожидали запуска. 08.04.2011
  • Подумайте о том, чтобы ваши потоки выполняли одно и то же с разными данными, а не отдельный поток, предназначенный для задачи. Что касается самих задач, подумайте о том, чтобы разделить их на небольшие части, чтобы вы могли обрабатывать их асинхронно и сохранять их состояние внутри. 08.04.2011
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    © 2024 wedx.ru, WedX - журнал о программировании и компьютерных науках
    Для любых предложений по сайту: [email protected]