Подтвердить что ты не робот

Многопоточный менеджер очереди заданий

Мне нужно управлять многозадачными задачами CPU в интерактивном приложении. Так же, как и в прошлом, мое конкретное приложение - это интерфейс инженерного проектирования. Поскольку пользователь настраивает различные параметры и параметры модели, в фоновом режиме запускаются несколько симуляций, и результаты отображаются по мере их завершения, вероятно, даже когда пользователь все еще редактирует значения. Поскольку множественные симуляции занимают переменное время (некоторые миллисекунды, некоторые занимают 5 секунд, некоторые занимают 10 минут), это в основном вопрос получения обратной связи, отображаемой как можно быстрее, но часто прерывание заданий, которые начались ранее, но теперь больше не нужны, изменений пользователя уже аннулировали их. Различные пользовательские изменения могут привести к недействительности различных вычислений, поэтому в любой момент времени у меня может быть 10 различных симуляций. Somesimulations имеют несколько частей, которые имеют зависимости (моделирование A и B можно вычислить отдельно, но мне нужны их результаты для моделирования семян C, поэтому мне нужно дождаться, когда и A, и B закончите сначала до начала C.)

Я уверен, что метод уровня кода для обработки такого типа приложений - это своего рода многопоточная очередь заданий. Это будет включать в себя функции отправки заданий для выполнения, задания приоритетов задач, ожидание завершения работ, определение зависимостей (выполнить это задание, но только после завершения задания X и задания Y), отмена подмножеств заданий, которые соответствуют некоторым критериям, остаются рабочие места, устанавливаются подсчеты и приоритеты рабочих потоков и т.д. И мультиплатформенная поддержка тоже очень полезна.

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

Первая мысль - перейти в OpenMP, но я не уверен, что хочу. OpenMP отлично подходит для распараллеливания на тонком уровне, автоматически развертки и т.д. В то время как мультиплатформенный, он также вторгается в ваш код С#pragmas. Но в основном он не предназначен для управления большими задачами.. особенно отменяя ожидающие задания или определяя зависимости. Возможно, да, но это не изящно.

Я заметил, что Google Chrome использует такой менеджер заданий даже для самых тривиальных задач. Цель проекта состоит в том, чтобы сохранить пользователя поток взаимодействия как можно более легкий и проворный, так что все, что может возникнуть асинхронно, должно быть. От взгляда на источник Chrome это, похоже, не является общей библиотекой, но все же интересно посмотреть, как дизайн использует асинхронные запуска для быстрого поддержания взаимодействия. Это похоже на то, что я делаю.

Существуют и другие варианты:

Surge.Act: a Boost-подобная библиотека для определения заданий. Он основывается на OpenMP, но позволяет цепочки зависимостей, которые хороши. Кажется, он не чувствует, что у него есть менеджер, которого можно запросить, отменены задания и т.д. Это устаревший проект, поэтому страшно зависеть от него.

Очередь работы довольно близка к тому, о чем я думаю, но это 5-летняя статья, а не поддерживаемая библиотека.

Boost.threads имеет хорошую независимую от синхронизации синхронизацию, но это не менеджер заданий. POCO имеет очень чистые конструкции для запуска задачи, но опять же не полный менеджер цепочки задач. (Возможно, я недооцениваю POCO).

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

Мое сообщение здесь, чтобы спросить вас, какие существующие инструменты я пропустил, и/или как вы свернули свою собственную многопоточную очередь заданий.

4b9b3361

Ответ 1

Нам нужно было создать собственную систему очереди заданий для удовлетворения требований, подобных вашим (поток пользовательского интерфейса должен всегда отвечать в течение 33 мс, задания могут выполняться от 15 до 15 000 мс), потому что там действительно ничего не было, что вполне соответствовало нашим потребностям, пусть один был исполнен.

К сожалению, наш код примерно так же проприетарен, как и собственность, но я могу дать вам некоторые наиболее важные функции:

  • Мы запускаем один поток на ядро ​​в начале программы. Каждый из них выполняет работу из глобальной очереди заданий. Задания состоят из объекта функции и глобуса связанных данных (на самом деле это разработка на func_ptr и void *). Thread 0, быстрый цикл клиента, не разрешается работать над заданиями, но остальные захватывают, как только могут.
  • Сама очередь заданий должна быть блокированной структурой данных, такой как заблокированный отдельно связанный список (Visual Studio поставляется с одним). Избегайте использования мьютекса; Конкуренция для очереди удивительно высока, и захват мьютексов является дорогостоящим.
  • Упакуйте все необходимые данные для задания в сам объект задания - избегайте указания указателя из задания обратно в основную кучу, где вам придется иметь дело с конфликтом между заданиями и блокировками, и все это другие медленные, раздражающие вещи. Например, все параметры моделирования должны входить в локальную базу данных заданий. Структура результатов, очевидно, должна быть чем-то, что переживает работу: вы можете справиться с этим либо: а) зависанием на объектах задания даже после того, как они закончили работать (чтобы вы могли использовать их содержимое из основного потока), или b) выделяя структуру результатов специально для каждого задания и набирая указатель на объект данных задания. Несмотря на то, что сами результаты не будут жить в работе, это фактически дает задание исключительный доступ к его выходной памяти, поэтому вам не нужно разбираться с блокировками.

  • На самом деле я немного упрощаю, так как нам нужно хореографировать точно, какие задания запускаются на каких ядрах, поэтому каждое ядро ​​получает свою собственную очередь заданий, но это, вероятно, не нужно для вас.

Ответ 2

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

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

Ответ 3

Microsoft работает над набором технологий для следующей версии Visual Studio 2010, называемой Concurrency Runtime, библиотекой параллельных шаблонов и библиотекой асинхронных агентов, которая, вероятно, поможет. Concurrency Runtime предложит планирование на основе политик, то есть позволит вам управлять и составлять несколько экземпляров планировщика (подобно пулам потоков, но с аффинитизацией и балансировкой нагрузки между экземплярами), библиотека параллельных шаблонов будет предлагать программирование на основе задач и параллельные циклы с помощью STL как модель программирования. Библиотека Агентов предлагает модель программирования на основе актера и поддерживает создание параллельных потоков данных, т.е. Управление этими зависимостями, описанными выше. К сожалению, это еще не выпущено, поэтому вы можете прочитать об этом в нашем блоге команды или посмотреть некоторые видеоролики на канале9 есть также очень большой CTP, который также доступен для скачивания.

Если вы ищете решение сегодня, блокирование потоков Intel и создание библиотеки потоковой передачи являются хорошими библиотеками и доступны сейчас. JustSoftwareSolutions выпустила реализацию std:: thread, которая соответствует проекту С++ 0x, и, конечно же, OpenMP широко доступен, re глядя на мелкозернистую петлю на основе parallelism.

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

-Rick

Ответ 4

Может быть полезно для вас? threadpool? Он основан на boost:: threads и в основном реализует простую очередь задач потока, которая передает рабочие функции в объединенные потоки.

Ответ 5

Возможно, вам стоит взглянуть на Flow-Based Programming - он основан на потоках данных, передаваемых между асинхронными компонентами. Существуют версии Java и С# драйвера, а также ряд предварительно кодированных компонентов. Он по сути является многопоточным - на самом деле единственный однопоточный код находится внутри компонентов, хотя вы можете добавить ограничения времени для стандартных правил планирования. Хотя это может быть слишком мелкозернистый уровень для того, что вам нужно, здесь могут быть вещи, которые вы можете использовать.

Ответ 6

Взгляните на boost:: future (но см. также этот обсуждение и предложение), который выглядит как действительно хорошая основа для parallelism (в частности, он предлагает отличную поддержку для ситуаций типа C-зависит от A-и-B).

Я немного посмотрел на OpenMP, но (как вы) не был убежден, что это будет хорошо работать для чего угодно, кроме форматированного кода Fortran/C. Intel Threading Building Blocks выглядел более интересным для меня.

Если дело доходит до него, не слишком сложно перевернуть свой собственный поверх boost:: thread. [Объяснение: поток farm (большинство людей называют его пулом) рисует работу из поточно-безопасного queue функторов (задач или заданий). См. тесты и критерий для примеров использования. У меня есть дополнительное усложнение (необязательно) поддержки задач с приоритетами, и случай, когда выполнение задач может порождать больше задач в рабочей очереди (это делает знание, когда вся работа на самом деле завершена немного более проблематично, ссылки на "ожидающие рассмотрения", это те, которые могут иметь дело с этим случаем). Можете дать вам некоторые идеи в любом случае.]

Ответ 7

Вам может понравиться Блоки Intel Thread Building Blocks. Я хочу, чтобы он делал то, что вам нужно, и с версией 2 Open Source.

Ответ 8

Там много распределенных менеджеров ресурсов. Программное обеспечение, отвечающее почти всем вашим требованиям, Sun Grid Engine. SGE используется на некоторых крупнейших суперкомпьютерах в мире и находится в активной разработке.

Там также похожие решения в Torque, Платформа LSF и Condor.

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

Ответ 9

Я не знаю, ищете ли вы библиотеку С++ (что я думаю, что вы есть), но Doug Lea Fork/Join framework для Java 7 довольно изящна и делает именно то, что вы хотите. Вероятно, вы сможете реализовать его на С++ или найти предварительно реализованную библиотеку.

Подробнее здесь: http://artisans-serverintellect-com.si-eioswww6.com/default.asp?W1