Grand Central Dispatch - Grand Central Dispatch

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

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

GCD был впервые выпущен с Mac OS X 10.6, а также доступен с iOS 4 и выше. Название "Grand Central Dispatch" является отсылкой к Центральный вокзал.[нужна цитата ]

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

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

Дизайн

GCD работает, разрешая определенные задачи в программе, которая может выполняться параллельно для постановки в очередь на выполнение, и, в зависимости от доступности ресурсов обработки, планирование их выполнять на любом из доступных ядер процессора[12][13] (называемый Apple "маршрутизацией").[14]

Задача может быть выражена как функция или как "блокировать."[15] Блоки являются расширением синтаксиса C, C ++, и Цель-C языки программирования, которые инкапсулируют код и данные в один объект аналогично закрытие.[12] GCD все еще можно использовать в средах, где блоки недоступны.[16]

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

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

Функции

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

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

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

Примеры

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

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

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

- (IBAction)анализироватьДокумент:(NSButton *)отправитель {    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        NSDictionary *статистика = [myDoc анализировать];        dispatch_async(dispatch_get_main_queue(), ^{            [myModel setDict:статистика];            [myStatsView setNeedsDisplay:ДА];        });    });}

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

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

за (я = 0; я < считать; я++) {      полученные результаты[я] = Выполнять работу(данные, я);}общий = подвести итог(полученные результаты, считать);

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

dispatch_apply(считать, dispatch_get_global_queue(0, 0), ^(size_t я){     полученные результаты[я] = Выполнять работу(данные, я);    });общий = подвести итог(полученные результаты, считать);

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

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

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

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

dispatch_queue_t exampleQueue = dispatch_queue_create( "com.example.unique.identifier", НОЛЬ );dispatch_sync( exampleQueue, ^{  dispatch_sync( exampleQueue, ^{    printf( "Я сейчас в тупике ..." );  });});dispatch_release( exampleQueue );

Приложения

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

Внутренности

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

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

Смотрите также

Рекомендации

  1. ^ "Справка по Grand Central Dispatch (GCD)". Apple Inc.
  2. ^ Apple представляет Mac OS X Snow Leopard разработчикам В архиве 19 марта 2012 г., в WebCite, 9 июня 2008 г.
  3. ^ http://libdispatch.macosforge.org/
  4. ^ GCD libdispatch с поддержкой блоков, работающих на FreeBSD
  5. ^ Ежеквартальный отчет о состоянии FreeBSD
  6. ^ libdispatch
  7. ^ Список рассылки libdispatch: "Статус переноса Linux" 10 апреля 2011 г.
  8. ^ Список рассылки libdispatch: «Статус переноса на Solaris x86 / 64» 10 апреля 2011 г.
  9. ^ Список рассылки libdispatch: «libdispatch для Win32» 22 апреля 2011 г.
  10. ^ Список рассылки libdispatch: «Обновления, касающиеся статуса libdispatch в Windows» 5 мая 2011 г.
  11. ^ Хатчинсон, Николас (10 января 2020 г.). "libdispatch". GitHub. Получено 15 января, 2020.
  12. ^ а б c «Техническое описание Apple по Grand Central Dispatch» (PDF). Архивировано 20 сентября 2009 года.. Получено 12 сентября, 2009.CS1 maint: BOT: статус исходного URL-адреса неизвестен (связь)
  13. ^ а б Ганье, Абрахам Зильбершатц, Питер Баер Галвин, Грег (2013). Понятия операционной системы (9-е изд.). Хобокен, штат Нью-Джерси: Wiley. С. 182–183. ISBN  9781118063330.
  14. ^ «WWDC 2008: Новое в Mac OS X Snow Leopard». Архивировано из оригинал 17 октября 2008 г.. Получено 18 июня, 2008.
  15. ^ "Справка по Grand Central Dispatch (GCD)". Получено 13 сентября, 2009.
  16. ^ https://wiki.freebsd.org/GCD#The_same_program.2C_without_C_Blocks
  17. ^ Бугаев Сергей. "Уловки связывания и загрузки Mach-O". Блог разработчиков Darling. Получено 15 января, 2020.
  18. ^ Mac OS X 10.6 Snow Leopard: обзор Ars Technica (доступ 2 сентября 2009 г.)
  19. ^ libdispatch-dev GCD MPM для Apache (по состоянию на 14 мая 2010 г.)
  20. ^ apache-libdispatch (по состоянию на 14 мая 2010 г.)
  21. ^ Левин, Джонатан (15 февраля 2014 г.). "Внутреннее устройство GCD: Недокументированная сторона Grand Central Dispatcher". Получено 17 марта, 2014.

внешняя ссылка