Как ядро взаимодействует с данными в OS X OpenCL

Существует две части каждой программы OpenCL. Часть, работающую на устройстве, вызывают ядром; часть, создающая объекты памяти, затем конфигурирует и вызывает ядро, вызывается узлом и обычно работает на CPU. Ядро является по существу функцией, записанной на языке OpenCL, позволяющем ему быть скомпилированным для выполнения на любом устройстве, поддерживающем OpenCL. Ядро является единственным способом, которым узел может вызвать функцию, которая будет работать на устройстве. Когда узел вызывает ядро, много единиц работы начинают работать на устройстве. Каждая единица работы выполняет код ядра, но работает над другой частью набора данных. Ядро управляет единицами работы путем доступа к ним использующий их IDs с помощью функций такой как get_global_id(…) и get_local_id(…). Несмотря на то, что ядра ставятся в очередь для выполнения хост-приложениями, записанными в C, C++ или Objective C, ядро должно быть скомпилировано отдельно, чтобы быть настроенным для устройства, на котором это собирается работать.

Взаимодействие с ядрами является более простыми инструментами использования, предоставленными OS X, чем это использует стандартный OpenCL. С OS X v10.7, можно включать ядра OpenCL как ресурсы в проектах XCode и скомпилировать их вместе с остальной частью приложения. Также с OS X v10.7, узел может вызвать ядра путем передачи их параметры так же, как если бы они были типичными функциями (см. Передающие Данные К Ядру); больше не необходимо явно установить параметры ядра с помощью специального OpenCL APIs.

Доступ к объектам от ядра

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

Передать данные от узла до вычислить ядра:

Указание, как разделить набор данных

Когда Вы пишете ядро в OpenCL, Вы пишете код, что каждая единица работы будет выполнять-инструкции о том, как обработать одну часть Вашего полного набора данных. Путем запуска многих единиц работы, каждая из которых воздействует на просто небольшую часть данных, Вы заканчиваете тем, что обработали целый набор данных. ndrange структура используется, чтобы указать, как данные присваиваются единицам работы.

N-мерный диапазон (cl_ndrange) структура, которую Вы передаете ядру, состоит из следующих полей:

Передача данных к ядру

XCode использует Ваш код ядра для автоматической генерации прототипа функции ядра в заголовочном файле ядра. Для передачи данных ядру передайте объекты памяти как параметры (как Вы передали бы параметры любой другой функции) при вызове ядра от кода узла. Параметры ядра OpenCL могут быть ограничены по объему с локальным или глобальным спецификатором, определяя хранение памяти для этих параметров. Это означает, что, с OS X v10.7, параметры ядра объявили с local или __local спецификатор адреса объявляется как size_t в блочном объявлении ядра.

Например, если ядру объявили параметр с local спецификатор адреса:

kernel void foo(
                global float *a,
                local float *shared);  // This kernel parameter is of type
                                       // local float; will be size_t in the
                                       // kernel block

Компилятор генерирует следующее объявление экстерна этого блока ядра:

extern void (^foo_kernel)(
                  const cl_ndrange *ndrange,
                  float *a,
                  size_t shared       // In the generated declaration,
                                      // local float is declared as size_t
             );

Путем соединения буфера возражает с определенными параметрами ядра, Вы позволяете обработать свои данные с помощью функции ядра. Например, в Примере: Выделение, Используя, и Выпуск Буферных Объектов, замечает, как пример кода обрабатывает входной указатель данных очень, как Вы обработали бы указатель в C. В этом примере входные данные являются массивом float значения, и можно обработать каждый элемент float массив путем индексации в указатель.

Получение результатов ядра

Если ядро будет возвращать результаты в буфере, вызовите функцию такой как gcl_memcpy(…) в то время как в блоке на данной очереди.

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

Если ядро будет возвращать результаты в буфере, вызовите dispatch_sync функционируйте как это:

dispatch_sync(queue,
              ^{
                 gcl_memcpy(ptr_c,
                            device_c,
                            num_floats * sizeof(float));
               });

Если ядро будет возвращать результаты в изображении, вызовите dispatch_sync функционируйте как это:

dispatch_sync(queue,^{
                         size_t origin = {0,0,0};
                         size_t region = {512, 512, 1};
                         gcl_copy_image_to_ptr(
                                             results_ptr,
                                             image,
                                             origin,
                                             region);
                       });

Это скопирует байты для 512 x 512 пикселей с изображения на буфер, указанный results_ptr параметр.