Дове, Жиль
- 1 year ago
- 0
- 0
OpenCL ( англ. Open C omputing L anguage — открытый язык вычислений) — фреймворк для написания компьютерных программ , связанных с параллельными вычислениями на различных графических и центральных процессорах , а также FPGA . В OpenCL входят язык программирования , который основан на стандарте языка программирования Си C99 , и API . OpenCL обеспечивает параллелизм на уровне инструкций и на уровне данных и является осуществлением техники GPGPU . OpenCL является полностью открытым стандартом , его использование не облагается лицензионными отчислениями.
Цель OpenCL состоит в том, чтобы дополнить открытые отраслевые стандарты для трёхмерной компьютерной графики и звука — OpenGL и OpenAL , соответственно, — возможностями GPU для высокопроизводительных вычислений. OpenCL разрабатывается и поддерживается некоммерческим консорциумом Khronos Group , в который входят много крупных компаний, включая AMD , Apple , ARM , Intel , Nvidia , Sony Computer Entertainment и другие.
OpenCL первоначально был разработан в компании Apple Inc. Apple внесла предложения по разработке спецификации в комитет Khronos. Вскоре компания AMD решила поддержать разработку OpenCL (и DirectX 11 ), который должен заменить фреймворк Close to Metal .
16 июня 2008 года была образована рабочая группа Khronos Compute для разработки спецификаций OpenCL. В неё вошли Apple , nVidia , AMD , IBM , Intel , ARM , Motorola и другие компании, в том числе специализирующиеся на создании компьютерных игр. Работа велась в течение пяти месяцев, по истечении которых 9 декабря 2008 года организация Khronos Group представила первую версию стандарта.
OpenCL 1.0 был впервые показан общественности 9 июня 2008, а выпущен вместе с Mac OS X 10.6 , 28 августа 2009 года.
5 апреля 2009 года компания AMD анонсировала доступность для загрузки бета-версии набора разработчика ATI Stream SDK v2.0, в который входит язык мультипроцессорного программирования OpenCL.
20 апреля 2009 года nVidia представила бета-драйвер и набор для разработки программного обеспечения ( SDK ) с поддержкой открытого GPGPU-стандарта OpenCL. Этот бета-драйвер предназначен для разработчиков, участвующих в программе «OpenCL Early Access», которые уже с 20 апреля могут принять участие в испытании бета-версии. Для участников программы «GPU Computing Registered Developers» бета-версия драйвера OpenCL будет доступна позже.
26 ноября 2009 года компания nVidia выпустила драйвер с поддержкой OpenCL 1.0 (rev 48).
Для получения наглядного представления, как технология OpenCL использует возможности 24-ядерной системы для отрисовки видеоэффектов, рекомендуется посмотреть следующий демо-ролик: от 9 марта 2017 на Wayback Machine .
OpenCL 1.1 был представлен организацией Khronos Group 14 июня 2010 года . В новой версии значительно расширены функциональные возможности для параллельного программирования, гибкость и производительность, а также добавлены новые возможности.
OpenCL 1.2 был представлен 15 ноября 2011 года . В новой версии отмечено множество небольших улучшений, связанных с увеличением гибкости языка и оптимизацией производительности. В OpenCL 1.2 был добавлен ряд значительных новшеств.
OpenCL 2.0 был представлен 22 июля 2013 года и стандартизирован 18 ноября того же года .
OpenCL 2.1 был представлен 3 марта 2015 года и стандартизирован 16 ноября того же года. В нём было переписано ядро с языка C на C++14 .
OpenCL 3.0 был представлен 27 апреля 2020 года и стандартизирован 30 сентября того же года . Среди заметных изменений можно отметить то, что API OpenCL 3.0 теперь охватывает все версии OpenCL (1.2, 2.x), без предоставления отдельных спецификаций для каждой версии.
Ключевыми отличиями используемого языка от Си (стандарт ISO 1999 года) являются:
Пример вычисления БПФ :
// создание вычислительного контекста для GPU (видеокарты)
context = clCreateContextFromType(NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, NULL);
// создание очереди команд
queue = clCreateCommandQueue(context, NULL, 0, NULL);
// выделение памяти в виде буферов
memobjs[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float)*2*num_entries, srcA, NULL);
memobjs[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float)*2*num_entries, NULL, NULL);
// создание программы из исходных текстов
program = clCreateProgramWithSource(context, 1, &fft1D_1024_kernel_src, NULL, NULL);
// компиляция программы
clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
// создание объекта kernel из скомпилированной программы
kernel = clCreateKernel(program, "fft1D_1024", NULL);
// подготовка аргументов
clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobjs[0]);
clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&memobjs[1]);
clSetKernelArg(kernel, 2, sizeof(float)*(local_work_size[0]+1)*16, NULL);
clSetKernelArg(kernel, 3, sizeof(float)*(local_work_size[0]+1)*16, NULL);
// задание N-D диапазона с размерностями work-item и отправка в очередь исполнения
global_work_size[0] = num_entries;
local_work_size[0] = 64;
clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_work_size, local_work_size, 0, NULL, NULL);
Непосредственные вычисления (основаны на отчете «Fitting FFT onto the G80 Architecture») :
// Данный код вычисляет FFT длины 1024, путём разбиения на 16, 16 и 4
__kernel void fft1D_1024 (__global float2 *in, __global float2 *out,
__local float *sMemx, __local float *sMemy) {
int tid = get_local_id(0);
int blockIdx = get_group_id(0) * 1024 + tid;
float2 data[16];
// адрес начала обрабатываемых данных в глобальной памяти
in = in + blockIdx; out = out + blockIdx;
globalLoads(data, in, 64); // coalesced global reads
fftRadix16Pass(data); // in-place radix-16 pass
twiddleFactorMul(data, tid, 1024, 0);
// локальная перестановка с использованием локальной памяти
localShuffle(data, sMemx, sMemy, tid, (((tid & 15) * 65) + (tid >> 4)));
fftRadix16Pass(data); // in-place radix-16 pass
twiddleFactorMul(data, tid, 64, 4); // twiddle factor multiplication
localShuffle(data, sMemx, sMemy, tid, (((tid >> 4) * 64) + (tid & 15)));
// 4 вызова БПФ порядка 4
fftRadix4Pass(data); // radix-4 function number 1
fftRadix4Pass(data + 4); // radix-4 function number 2
fftRadix4Pass(data + 8); // radix-4 function number 3
fftRadix4Pass(data + 12); // radix-4 function number 4
// coalesced global writes
globalStores(data, out, 64);
}
Полноценная реализация БПФ на OpenCL доступна на сайте Apple .
OpenCL находит применение, как одна из реализаций концепции GPU общего назначения , в различном ПО.