Гранд Центральная диспетчерская
![]() | |
Оригинальный автор(ы) | Дэйв Зажицки |
---|---|
Разработчик(и) | Apple Инк. |
Написано в | С |
Операционная система | Mac OS X 10.6 (2009 г.) и новее, iOS 4.0 и новее, [ 1 ] watchOS, tvOS, FreeBSD |
Тип | Системная утилита |
Лицензия | Апач 2.0 |
Веб-сайт | https://apple.github.io/swift-corelibs-libdispatch/ |
Grand Central Dispatch ( GCD или libdispatch ) — технология, разработанная Apple Inc. для оптимизации поддержки приложений для систем с многоядерными процессорами и других симметричных многопроцессорных систем. [ 2 ] Это реализация параллелизма задач, основанная на шаблоне пула потоков . Фундаментальная идея состоит в том, чтобы передать управление пулом потоков из рук разработчика ближе к операционной системе. Разработчик внедряет в пул «рабочие пакеты», не обращая внимания на его архитектуру. Эта модель отличается простотой, портативностью и производительностью.
GCD был впервые выпущен в Mac OS X 10.6 , а также доступен в iOS 4 и выше. Название «Grand Central Dispatch» является отсылкой к Центральному вокзалу . [ нужна ссылка ]
Исходный код библиотеки libdispatch , обеспечивающей реализацию сервисов GCD , был выпущен Apple под лицензией Apache 10 сентября 2009 года. [ 3 ] Он был портирован [ 4 ] на FreeBSD 8.1+, [ 5 ] ПолночьBSD 0.3+, [ 6 ] Линукс и Солярис. [ 7 ] [ 8 ] Попытки 2011 года заставить libdispatch работать в Windows не были объединены с основной веткой разработки. [ 9 ] [ 10 ] У Apple есть собственный порт libdispatch.dll для Windows, поставляемый с Safari и iTunes, но SDK не предоставляется.
Примерно с 2017 года исходный репозиторий libdispatch, размещенный Ником Хатчинсоном. [ 11 ] был признан устаревшим в пользу версии, которая является частью базовой библиотеки Swift , созданной в июне 2016 года. Новая версия поддерживает больше платформ, в частности, включая Windows.
Дизайн
[ редактировать ]GCD работает, позволяя ставить определенные задачи в очередь на выполнение в программе, которую можно запускать параллельно, и, в зависимости от доступности вычислительных ресурсов, планируя их выполнение на любом из доступных ядер процессора. [ 12 ] [ 13 ] (называемый Apple «маршрутизацией»). [ 14 ]
Задача может быть выражена либо как функция , либо как « блок ». [ 15 ] Блоки — это расширение синтаксиса языков программирования C , C++ и Objective-C , которое инкапсулирует код и данные в один объект аналогично замыканию . [ 12 ] GCD по-прежнему можно использовать в средах, где блоки недоступны. [ 16 ]
Grand Central Dispatch по-прежнему использует потоки на низком уровне, но абстрагирует их от программиста, которому не нужно будет беспокоиться о стольких деталях. Задачи в GCD легко создавать и ставить в очередь; Apple заявляет, что для постановки рабочей единицы в очередь в GCD требуется 15 инструкций, тогда как для создания традиционного потока может легко потребоваться несколько сотен инструкций. [ 12 ]
Задачу в Grand Central Dispatch можно использовать либо для создания рабочего элемента, который помещается в очередь, либо для назначения его источнику событий. Если задача назначена источнику события, то рабочая единица создается из блока или функции при срабатывании события, и рабочая единица помещается в соответствующую очередь. Apple описывает это как более эффективное, чем создание потока, единственной целью которого является ожидание запуска одного события.
Функции
[ редактировать ]Платформа диспетчеризации объявляет несколько типов данных и функций для их создания и управления ими:
- Очереди отправки — это объекты, которые поддерживают очередь задач (либо анонимных блоков кода, либо функций) и выполняют эти задачи по очереди. Библиотека автоматически создает несколько очередей с разными уровнями приоритета, которые одновременно выполняют несколько задач, выбирая оптимальное количество задач для запуска исходя из операционной среды. Клиент библиотеки также может создавать любое количество последовательных очередей, которые выполняют задачи в том порядке, в котором они были отправлены, по одной. [ 13 ] Поскольку последовательная очередь может одновременно запускать только одну задачу, каждая задача, отправленная в очередь, имеет решающее значение по отношению к другим задачам в очереди, и, таким образом, последовательную очередь можно использовать вместо блокировки конкурирующего ресурса.
- Источники отправки — это объекты, которые позволяют клиенту регистрировать блоки или функции для асинхронного выполнения при системных событиях, таких как дескриптора сокета или файла готовность к чтению или записи или сигнал POSIX .
- Группы диспетчеризации — это объекты, которые позволяют группировать несколько задач для последующего объединения. Задачи можно добавлять в очередь как члена группы, а затем клиент может использовать объект группы, чтобы дождаться завершения всех задач в этой группе.
- Семафоры диспетчеризации — это объекты, которые позволяют клиенту разрешать одновременное выполнение только определенного количества задач.
Libdispatch поставляется с собственной объектной моделью OS Object , частично совместимой с моделью Objective-C. В результате его объекты можно бесплатно соединить с объектами ObjC. [ 17 ]
Примеры
[ редактировать ]![]() | Эта статья написана как руководство или руководство . ( июнь 2010 г. ) |
Два примера, демонстрирующие использование Grand Central Dispatch, можно найти в обзоре Ars Technica Snow Leopard Джона Сиракузы. [ 18 ] Изначально приложение на основе документов имеет метод под названием analyzeDocument
который может делать что-то вроде подсчета количества слов и абзацев в документе. Обычно это быстрый процесс, который может выполняться в основном потоке, при этом пользователь не замечает задержки между нажатием кнопки и отображением результатов.
- (IBAction)analyzeDocument:(NSButton *)sender {
NSDictionary *stats = [myDoc analyze];
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
}
Если документ большой и выполнение анализа занимает много времени, основной поток будет ждать завершения функции. Если это займет достаточно много времени, пользователь это заметит, и приложение может даже " играть в пляжный мяч ". Решение можно увидеть здесь:
- (IBAction)analyzeDocument:(NSButton *)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDictionary *stats = [myDoc analyze];
dispatch_async(dispatch_get_main_queue(), ^{
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
});
});
}
Здесь вызов [myDoc analyze]
помещается внутри Block , который затем помещается в одну из глобальных одновременных очередей. После завершения работы [myDoc analyze]
, в основную очередь (в которой выполняется основной поток приложения) помещается новый блок, который обновляет графический интерфейс (это необходимо, поскольку графический интерфейс может обновляться только основным потоком). Внеся эти два небольших изменения, разработчик избежал потенциального зависания приложения, как это видит пользователь, и позволил своему приложению лучше использовать аппаратные ресурсы.
Второй пример — распараллеливание цикла for:
for (i = 0; i < count; i++) {
results[i] = do_work(data, i);
}
total = summarize(results, count);
Этот код запускает do_work
функция count
раз, присваивая i- й результат i -му элементу массива results
, а затем вызывает sum для массива после завершения цикла. К сожалению, работа вычисляется последовательно, хотя в этом, возможно, и нет необходимости. Если предположить, что 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. Это позволит ОС распределять работу по своему усмотрению, выбирая оптимальное количество потоков для текущей нагрузки на оборудование и систему. dispatch_apply
не возвращает результат до тех пор, пока все блоки, которые он помещает в данную очередь, не завершат выполнение, так что можно гарантировать, что вся работа внутри исходного цикла будет завершена до вызова summarize
.
Программисты могут создавать свои собственные последовательные очереди для задач, которые, как они знают, должны выполняться последовательно, но могут выполняться в отдельном потоке. Новая очередь будет создана следующим образом:
dispatch_queue_t exampleQueue;
exampleQueue = dispatch_queue_create( "com.example.unique.identifier", NULL );
// exampleQueue may be used here.
dispatch_release( exampleQueue );
Необходимо соблюдать осторожность, чтобы избежать синхронного размещения отправленного блока в очереди другого блока в той же очереди, поскольку это гарантированно приведет к взаимоблокировке. Такой код может делать следующее:
dispatch_queue_t exampleQueue = dispatch_queue_create( "com.example.unique.identifier", NULL );
dispatch_sync( exampleQueue, ^{
dispatch_sync( exampleQueue, ^{
printf( "I am now deadlocked...\n" );
});
});
dispatch_release( exampleQueue );
Приложения
[ редактировать ]GCD используется во всей macOS (начиная с версии 10.6 Snow Leopard), и Apple поощряет его внедрение разработчиками приложений macOS. FreeBSD Разработчик Роберт Уотсон объявил о первой адаптации основного приложения с открытым исходным кодом, Apache HTTP Server , для использования GCD через Apache GCD MPM (модуль многопроцессорной обработки) 11 мая 2010 года, чтобы проиллюстрировать модель программирования и способы ее реализации. интегрировать GCD в существующие крупномасштабные многопоточные приложения. В его объявлении отмечалось, что GCD MPM имеет от трети до половины меньше строк, чем другие многопоточные MPM. [ 19 ] [ 20 ]
Внутренности
[ редактировать ]GCD реализуется libdispatch с поддержкой не-POSIX-расширений pthreads , разработанных Apple. Apple изменила интерфейс с момента его создания (в OS X 10.5) посредством официального запуска GCD (10.6), Mountain Lion (10.8) и Mavericks (10.9). Последние изменения заключаются в том, чтобы сделать код, поддерживающий pthreads, как в пользовательском режиме, так и в ядре, частным (при этом поддержка pthread в ядре сведена только к прокладкам, а фактическая реализация рабочей очереди перенесена в отдельное расширение ядра). [ 21 ]
В других системах libdispatch реализует собственную рабочую очередь, используя собственные средства обработки событий системы ( epoll , kevent или Windows NT). В macOS kevent используется с рабочей очередью ядра.
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ «Справочник Grand Central Dispatch (GCD)» . Apple Инк.
- ↑ Apple представляет разработчикам Mac OS X Snow Leopard. Архивировано 18 марта 2012 г., в Wayback Machine , 9 июня 2008 г.
- ^ «Гранд Централ Диспетчер» . apple.github.io .
- ^ «GCD libdispatch с поддержкой блоков работает на FreeBSD» . Архивировано из оригинала 27 июля 2011 года . Проверено 28 сентября 2009 г.
- ^ «Ежеквартальный отчет о состоянии FreeBSD» . www.freebsd.org .
- ^ «либдиспетч» . Просто журнал .
- ^ Список рассылки libdispatch: «Состояние портирования Linux». Архивировано 11 июля 2011 г., в Wayback Machine , 10 апреля 2011 г.
- ^ Список рассылки libdispatch: «Состояние переноса Solaris x86/64». Архивировано 4 октября 2011 г., на Wayback Machine, 10 апреля 2011 г.
- ^ Список рассылки libdispatch: «libdispatch для Win32». Архивировано 20 августа 2011 г., в Wayback Machine, 22 апреля 2011 г.
- ^ Список рассылки libdispatch: «Обновления о статусе libdispatch в Windows». Архивировано 20 августа 2011 г., на Wayback Machine , 5 мая 2011 г.
- ^ Хатчинсон, Николас (10 января 2020 г.). «либдиспетч» . Гитхаб . Проверено 15 января 2020 г.
- ^ Jump up to: а б с «Техническое описание Apple по Grand Central Dispatch» (PDF) . Архивировано из оригинала 20 сентября 2009 года . Проверено 12 сентября 2009 г.
{{cite web}}
: CS1 maint: bot: исходный статус URL неизвестен ( ссылка ) - ^ Jump up to: а б Ганье, Авраам Зильбершац, Питер Баер Гэлвин, Грег (2013). Концепции операционной системы (9-е изд.). Хобокен, Нью-Джерси: Уайли. стр. 182–183. ISBN 9781118063330 .
{{cite book}}
: CS1 maint: несколько имен: список авторов ( ссылка ) - ^ «WWDC 2008: Новое в Mac OS X Snow Leopard» . Архивировано из оригинала 17 октября 2008 года . Проверено 18 июня 2008 г.
- ^ «Справочник Grand Central Dispatch (GCD)» . Проверено 13 сентября 2009 г.
- ^ «GrandCentralDispatch — FreeBSD Wiki» .
- ^ Бугаев Сергей (24 июля 2018 г.). «Трюки с соединением и загрузкой Mach-O» . Дорогой блог разработчиков . Проверено 15 января 2020 г.
- ^ Mac OS X 10.6 Snow Leopard: обзор Ars Technica (по состоянию на 2 сентября 2009 г.)
- ^ libdispatch-dev GCD MPM для Apache. Архивировано 7 августа 2020 г. на Wayback Machine (по состоянию на 14 мая 2010 г.).
- ^ apache-libdispatch (по состоянию на 14 мая 2010 г.)
- ^ Левин, Джонатан (15 февраля 2014 г.). «Внутреннее устройство GCD: недокументированная сторона Центрального диспетчера» . Проверено 17 марта 2014 г.