Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

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] MidnightBSD. 0.3+, [6] Linux и Solaris. [7] [8] Попытки заставить libdispatch работать в Windows в 2011 году не были объединены в восходящий поток. [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]

Примеры [ править ]

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

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

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

-  ( IBAction ) analyzeDocument: ( 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 analyze]помещается в блок , который затем помещается в одну из глобальных параллельных очередей. После завершения работы [myDoc analyze]новый блок помещается в основную очередь (в которой выполняется основной поток приложения), который обновляет графический интерфейс (это необходимо, поскольку графический интерфейс может быть обновлен только основным потоком). Внеся эти два небольших изменения, разработчик избежал потенциальной остановки приложения, которую видит пользователь, и позволил своему приложению лучше использовать аппаратные ресурсы.

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

для  ( я  =  0 ;  я  <  количество ;  я ++ )  {  результаты [ я ]  =  делать_работа ( данные ,  я ); } total  =  summarize ( результаты ,  количество );

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

dispatch_apply ( количество ,  dispatch_get_global_queue ( 0 ,  0 ),  ^ ( size_t  i ) {  results [ i ]  =  do_work ( data ,  i );  }); итог  =  суммировать ( результаты ,  количество );

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

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

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 (модуль многопроцессорной обработки) 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 используется с рабочей очередью ядра.

См. Также [ править ]

  • Библиотека параллельных задач
  • Параллелизм Java
  • OpenMP
  • Строительные блоки Threading (TBB)

Ссылки [ править ]

  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 for Win32" 22 апреля 2011 г.
  10. Список рассылки ^ libdispatch: «Обновления, касающиеся статуса libdispatch в Windows» 5 мая 2011 г.
  11. Хатчинсон, Николас (10 января 2020 г.). "libdispatch" . GitHub . Проверено 15 января 2020 года .
  12. ^ a b c «Техническая записка Apple по Grand Central Dispatch» (PDF) . Архивировано 20 сентября 2009 года . Проверено 12 сентября 2009 года . CS1 maint: bot: исходный статус URL неизвестен ( ссылка )
  13. ^ a b Gagne, Abraham Silberschatz, Peter Baer Galvin, Greg (2013). Понятия операционной системы (9-е изд.). Хобокен, Нью-Джерси: Уайли. С. 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» . Любимый блог разработчиков . Проверено 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 года .

Внешние ссылки [ править ]

  • Проект GCD на GitHub
  • Справочник по GCD из библиотеки разработчиков Mac
  • Вводя Блоки и Grand Central Dispatch статья из библиотеки для разработчиков Mac