Grand Central Dispatch

редактировать

Grand Central Dispatch
GCD
Автор (ы) Дэйв Заржицки
Разработчик (и) Apple Inc.
Операционная система Mac OS X 10.6 (2009) и новее, iOS 4.0 и новее, watchOS, tvOS, FreeBSD
Тип Системная утилита
Лицензия Apache 2.0
Веб-сайтhttps://apple.github.io/swift-corelibs-libdispatch/

Grand Central Dispatch (GCD или libdispatch ) - это технология, разработанная Apple Inc. для оптимизации поддержки приложений для систем с многоядерными процессорами и другими симметричной многопроцессорной обработкой системы. Это реализация параллелизма задач на основе шаблона пула потоков . Основная идея состоит в том, чтобы перенести управление пулом потоков из рук разработчика в сторону операционной системы. Разработчик вводит в пул «рабочие пакеты», не обращая внимания на архитектуру пула. Эта модель улучшает простоту, портативность и производительность.

GCD впервые был выпущен с Mac OS X 10.6, а также доступен с iOS 4 и выше. Название «Grand Central Dispatch» является отсылкой к Grand Central Terminal.

. Исходный код библиотеки libdispatch, обеспечивающей реализацию служб GCD, был выпущен Apple по лицензии Apache License 10 сентября 2009 г. Он был перенесен на FreeBSD 8.1+, MidnightBSD 0.3+, Linux и Solaris. Попытки в 2011 году заставить libdispatch работать в Windows не были объединены в апстрим. У Apple есть собственный порт libdispatch.dll для Windows, поставляемый с Safari и iTunes, но SDK не предоставляется.

Примерно с 2017 года исходный репозиторий libdispatch, размещенный Ником Хатчинсоном, устарел в пользу версии, которая является частью основной библиотеки Swift, созданной в июне 2016 года. Новая версия поддерживает больше платформ., особенно в том числе Windows.

Содержание
  • 1 Дизайн
  • 2 Особенности
  • 3 Примеры
  • 4 Приложения
  • 5 Внутреннее устройство
  • 6 См. Также
  • 7 Ссылки
  • 8 Внешние ссылки
Дизайн

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

Задача может быть выражена либо как функция, либо как «блок. " Блоки являются расширением синтаксиса языков программирования C, C ++ и Objective-C, которые инкапсулируют код и данные в единый объект аналогично закрытию . GCD по-прежнему можно использовать в средах, где блоки недоступны.

Grand Central Dispatch по-прежнему использует потоки на низком уровне, но отвлекает их от программиста, которому не нужно беспокоиться о стольких деталях. Задачи в GCD легко создавать и ставить в очередь; Apple заявляет, что для постановки рабочего блока в очередь в GCD требуется 15 инструкций, в то время как для создания традиционного потока может потребоваться несколько сотен инструкций.

Задача в Grand Central Dispatch может использоваться либо для создания рабочего элемента, который помещается в очередь или назначается источнику события. Если задача назначена источнику события, то при срабатывании события из блока или функции создается рабочая единица, и эта единица работы помещается в соответствующую очередь. Apple описывает это как более эффективное, чем создание потока, единственной целью которого является ожидание срабатывания одного события.

Возможности

Среда диспетчеризации объявляет несколько типов данных и функций для их создания и управления ими:

  • Очереди диспетчеризации - это объекты, которые поддерживают очередь задач, либо анонимных блоков кода, либо функций, и выполнять эти задачи в свою очередь. Библиотека автоматически создает несколько очередей с разными уровнями приоритета, которые выполняют несколько задач одновременно, выбирая оптимальное количество задач для запуска в зависимости от операционной среды. Клиент библиотеки может также создать любое количество последовательных очередей, которые выполняют задачи в том порядке, в котором они были отправлены, по одной за раз. Поскольку последовательная очередь может запускать только одну задачу за раз, каждая задача, отправленная в очередь, является критической по отношению к другим задачам в очереди, и, следовательно, последовательная очередь может использоваться вместо блокировки на конкурирующий ресурс.
  • Источники диспетчеризации - это объекты, которые позволяют клиенту регистрировать блоки или функции для асинхронного выполнения при системных событиях, таких как socket или файловый дескриптор, готовы для чтения или записи, или POSIX signal.
  • Dispatch Groups - это объекты, которые позволяют группировать несколько задач для последующего объединения. Задачи могут быть добавлены в очередь в качестве члена группы, а затем клиент может использовать объект группы, чтобы дождаться завершения всех задач в этой группе.
  • Семафоры отправки - это объекты, которые позволяют клиенту чтобы разрешить одновременное выполнение только определенного количества задач.

Libdispatch поставляется с собственной объектной моделью OS Object, которая частично совместима с моделью Objective-C. В результате его объекты могут быть бесплатно связаны с объектами ObjC.

Примеры

Два примера, демонстрирующие использование Grand Central Dispatch, можно найти в Ars Technica Джона Сиракузы. Обзор снежного барса. Первоначально приложение на основе документа имеет метод под названием analysisDocument, который может делать что-то вроде подсчета количества слов и абзацев в документе. Обычно это быстрый процесс, который может выполняться в основном потоке, и пользователь не замечает задержки между нажатием кнопки и отображением результатов.

- (IBAction) analysisDocument: (NSButton *) отправитель {NSDictionary * stats = [myDoc analysis]; [myModel setDict: статистика]; [myStatsView setNeedsDisplay: ДА]; }

Если документ большой и для выполнения анализа требуется много времени, тогда основной поток будет ждать завершения функции. Если это займет достаточно времени, пользователь заметит, и приложение может даже «beachball ». Решение можно увидеть здесь:

- (IBAction) analyseDocument: (NSButton *) sender {dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {NSDictionary * stats = [myDoc analysis]; ^ dispatch_asqueget_mainc [myModel setDict: stats]; [myStatsView setNeedsDisplay: YES];});}); }

Здесь вызов [myDoc analysis]помещается в блок , который затем помещается в одну из глобальных параллельных очередей. После завершения выполнения [myDoc analysis]новый блок помещается в основную очередь (в которой выполняется основной поток приложения), который обновляет GUI (это необходимо, потому что графический интерфейс может обновляться только основным потоком). Внеся эти два небольших изменения, разработчик избежал потенциальной остановки приложения, которую видит пользователь, и позволил своему приложению лучше использовать аппаратные ресурсы.

Второй пример - это пример распараллеливания цикла for:

for (i = 0; i < count; i++) { results[i] = do_work(data, i); } total = summarize(results, count);

Этот код запускает функцию do_workcountраз, присваивая результат i th элементу i th в массиве results, а затем вызывает summarize в массиве после завершения цикла. К сожалению, работа вычисляется последовательно там, где это может не быть. Предполагая, что do_work не полагается на результаты каких-либо других обращений к нему, нет причин, по которым эти вызовы не могут выполняться одновременно. Вот как это будет сделано в GCD:

dispatch_apply (count, dispatch_get_global_queue (0, 0), ^ (size_t i) {results [i] = do_work (data, i);}); total = summarize (results, count);

Здесь dispatch_applyзапускает переданный ему блок, countраз, помещая каждый вызов в глобальную очередь и передавая каждому вызову блока другое число от 0 до count-1. Это позволит ОС распределять работу по своему усмотрению, выбирая opti малое количество потоков для выполнения при текущей загрузке оборудования и системы. dispatch_applyне возвращается до тех пор, пока все блоки, которые он помещает в данную очередь, не завершат выполнение, так что можно гарантировать, что вся работа внутри исходного цикла завершена до вызова суммировать.

Программисты могут создавать свои собственные последовательные очереди для задач, которые, как они знают, должны выполняться последовательно, но которые могут выполняться в отдельном потоке. Новая очередь будет создана следующим образом:

dispatch_queue_t exampleQueue; exampleQueue = dispatch_queue_create ("com.example.unique.identifier", NULL); // Здесь можно использовать exampleQueue. dispatch_release (exampleQueue);

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

dispatch_queue_t exampleQueue = dispatch_queue_create ("com.example.unique.identifier", NULL); dispatch_sync (exampleQueue, ^ {dispatch_sync (exampleQueue, ^ {printf ("Теперь я зашел в тупик... \ n");});}); dispatch_release (exampleQueue);
Приложения

GCD используется во всей macOS (начиная с 10.6 Snow Leopard), и Apple поощряет его внедрение разработчиками приложений для macOS. FreeBSD разработчик Роберт Уотсон объявил о первой адаптации крупного приложения с открытым исходным кодом, Apache HTTP Server, для использования GCD через Apache GCD MPM (Multi-Processing Module) 11 мая 2010 г., чтобы проиллюстрировать модель программирования и способы интеграции GCD в существующие крупномасштабные многопоточные приложения. В его заявлении было отмечено, что GCD MPM имеет от одной трети до половины количества строк, чем другие многопоточные MPM.

Внутреннее

GCD реализуется libdispatch с поддержкой расширений pthreads, не относящихся к POSIX, разработанных Яблоко. Apple изменила интерфейс с момента своего создания (в OS X 10.5) посредством официального запуска GCD (10.6), Mountain Lion (10.8) и недавно Mavericks (10.9). Последние изменения заключаются в том, чтобы сделать код, поддерживающий потоки pthread, как в пользовательском режиме, так и в ядре, частным (при этом поддержка pthread в ядре ограничена только оболочками, а фактическая реализация очереди перемещена в отдельное расширение ядра).

В других системах, libdispatch реализует свою собственную очередь работ, используя собственные средства обработки событий системы (epoll, kevent или Windows NT). В macOS kevent используется с рабочей очередью ядра.

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-05-22 04:34:01
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте