Nvidia opencl

Как ускорить вычисления и повысить производительность программ с помощью принципов массивного параллелизма и OpenCL — Разработка на vc.ru

Nvidia opencl

Стандартный подход к написанию программ является линейным – операция b выполняется после завершения операции a. Но что делать в случае если таких операций десятки тысяч, а задача требует быстрого произведения данных операций?

Допустим, вы разрабатываете приложение с искусственным интеллектом для распознавания предметов основываясь на данных получаемых с сенсора, или пишете графическое приложение, которое требует множество вычислений на каждом из пикселей. Как сделать так, чтобы обработка информации происходила в реальном времени, а задержка между получением информации, её обработкой и выдачей результата была минимальной?

Те кто сталкивался с данной проблемой, наверняка знают про многопоточность (multithreading) — способ параллельного запуска определённых фрагментов кода для ускорения обработки этого кода.

Но, к сожалению, этот метод подходит не всегда, и когда требуется произведение одинаковых операций на большом количестве данных, гораздо эффективнее будет прибегнуть к массивному параллелизму и использовать фреймворки OpenCL или CUDA.

В этой статье мы познакомимся с массивным параллелизмом и напишем программу для параллельных вычислений, используя фреймворк OpenCL.

OpenCL (Open Computing Language) — фреймворк разработанный Apple в 2008 году и поддерживаемый Khronos Group с 2009 года. Он позволяет создавать программы для параллельного исполнения на различных вычислительных девайсах (CPU и GPU), упакованные в “кернели”-ядра (kernels) — части кода, которые будут отправлены на вычислительный девайс для произведения каких-то операций.

OpenCL — замечательный инструмент, который может ускорить вашу программу в десятки, если не сотни\тысячи раз.

К сожалению, из-за отсутствия простых и доступных гайдов по данной спецификации, в особенности на русском языке, а так-же особенностям работы с ней (о чём мы поговорим чуть позже), начинающему разработчику может быть очень трудно разобраться в теме и попытки изучить спецификацию остаются безуспешными.

Это большое упущение, и цель этой статьи — не только доступно и подробно рассказать о спецификации и продемонстрировать как работать с ней, но и написать гайд, который мне хотелось бы прочитать самому когда я начал изучать OpenCL.

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

В линейном программировании мы имеем чёткую последовательность действий: a, b, c, d; действие b не будет выполнено до того как завершиться a и c не будет выполнено пока не завершиться b.

Но что делать, если нам, например, требуется найти суммы элементов из двух массивов (листов), и в каждом массиве по 100,000 элементов? Последовательное вычисление заняло бы достаточно долгое время, так-как нам пришлось бы совершить минимум 100,000 операций.

А что если такая процедура требует многочисленного повторения и результат нужен в реальном времени с минимальной задержкой? Тут нам и приходит на помощь массивный параллелизм!

Допустим, мы хотим вычислить суммы 0 + 3, 1 + 2, 2 + 1, 3 + 0 и записать результаты в массив. В линейном программировании, мы воспользуемся циклом for или while, где операции будут выполняться последовательно, и схема вычислений будет выглядеть примерно так:

Через последовательную итерацию, мы будем выполнять первое действие, записывать результат в массив и переходить к следующему действию. Поскольку для выполнения данных вычислений нам требуется 4 итерации, для наглядности, давайте обозначим что время (t) потраченное на выполнение данных операций равняется 4.

Массивный параллелизм позволяет нам сформировать и отправить данную задачу (0 + 3 и т.д.) для выполнения используя ресурсы, например, видеокарты — она имеет десятки, сотни, тысячи вычислительных единиц (ядер), которые могут производить операции параллельно, независимо друг от друга.

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

Другими словами, если 0 + 3 — вычисление номер один, а 1 + 2 — вычисление номер два, мы можем посчитать 1 + 2 и записать ответ во второе место в массиве (res[1]) не зависимо от того записан ли ответ 0 + 3 в первое место (res[0]). При этом, если мы попытаемся одновременно записать информацию в ячейки res[0] (первое место) и res[1] (второе место), у нас не возникнет ошибки.

Таким образом, с помощью массивного параллелизма мы можем одновременно и независимо друг от друга выполнить все нужные нам операции, и записать все ответы в массив, содержащий результаты, всего за одно действие, тем самым, сократив t до 1. Мы только что сократили временную сложность алгоритма (время работы алгоритма) до константного значения 1 (одно действие).

Перед тем как мы перейдём к практике, важно прояснить специфику работы с OpenCL и разобраться как переписывать линейный код в параллельном формате. Не волнуйтесь — это совсем не сложно!

Кернель (kernel, вектор — функция, отправляемая на вычислительный девайс в контексте работы OpenCL) и хост (host — код, вызывающий OpenCL; ваш код) существуют, по большему счёту, изолированно друг от друга.

Компиляция и запуск кернеля OpenCL происходят внутри вашего кода, во время его исполнения (онлайн, или runtime execution).

Так-же, важно понимать что кернель и хост не имеют общего буфера памяти и мы не можем динамически выделять память (с помощью malloc() и подобных) внутри кернеля.

Обмен информацией между двумя системами происходит посредством отправления между ними заранее выделенных регионов памяти.

Другими словами, если у меня в хосте есть объект Х, для того чтобы обратится к нему из кернеля OpenCL, мне для начала нужно его туда отправить. Если вы всё ещё не до конца поняли о чём идёт речь — читайте дальше и всё прояснится!

Модель памяти OpenCL выглядит так:

При создании контекста OpenCL (среда в которой существует данный инстанс OpenCL), мы обозначаем нашу задачу как NDRange — общий размер вычислительной сетки — количество вычислений которые будут выполнены (в примере с суммами использованном выше, NDRange = 4). Информацию записанную в глобальную память (global memory) мы можем получить из любого элемента NDRange.

При отправке задачи на девайс OpenCL (например, видеокарту компьютера), наш NDRange разбивается на рабочие группы (work-groups) — локальная память (local memory), которые содержат в себе рабочие единицы (work-items, изолированные инстансы кернеля) — приватная память (private memory).

Мы не можем считать объект из локальной памяти в глобальную. Это значит что значение существующее внутри одной рабочей группы не будет доступно из другой группы.

Локальная память имеет доступ к объектам из глобальной памяти, но не может получить информацию из приватной памяти. Наконец, приватная память может считывать из глобальной и локальной памяти, но всё что существует внутри её, остаётся в ней.

Стоит добавить, что от выбора памяти зависит скорость выполнения программы. Так, запрос к глобальной памяти является самым времязатратным, и работать с глобальной памятью стоит только в случае необходимости.

В большинстве случаев, будет грамотнее объявить переменную в локальной или приватной памяти (нет смысла создавать переменную в глобальной памяти, если она не используется за пределами одной рабочей единицы).

Так-же, зачастую будет грамотным решением перевести глобальный объект в локальную или приватную память, после получения его внутри кернеля, если требуется произвести с ним множество операций внутри одной рабочей единицы, так-как это может значительно ускорить выполнение программы.

Для обмена данными между хостом и кернелем, внутри хоста мы создаём специальный буфер, содержащий информацию, нужную для вычислений на девайсе OpenCL, а так-же буфер с выделенным местом (памятью), в который будут записаны результаты вычислений кернеля. Эти элементы отправляются в кернель, он производит свои вычисления, записывает результат в буфер который мы специально для этого подготовили и отправляет его обратно в хост.

В общих чертах, схема работы с OpenCL выглядит следующим образом:

Начнём с установки и настройки OpenCL на нашем компьютере.

Первым делом, скачайте и обновите драйвера вашей видеокарты. Это очень важно, так-как OpenCL не будет работать если ваши драйвера его не поддерживают.

Если вы пользуетесь Apple MacOS, всё что вам нужно сделать — убедиться что у вас установлена новейшая версия ОС и XCode. OpenCL поставляется с вашей системой.

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

В качестве простого примера, давайте возьмём задачу векторного сложения.

Допустим, у нас есть два массива, A и B, равного размера. Наша цель — найти сумму элементов А и B и записать её в элемент нового массива, С, такого-же размера.

Стандартный метод решения данной задачи подразумевает использование цикла for или while, для последовательной итерации через массив, выполняя операцию:

for (int i = 0; i < РАЗМЕР_МАССИВА; i++){ C[i] = A[i] + B[i];}

Алгоритм очень простой, но имеет линейную временную сложность, O(n), где n — размер массива.

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

Таким образом, если мы имеем n ядер в нашем вычислительном девайсе, временная сложность становится константной O(1). Это как-раз то, о чём мы уже говорили раньше.

Начать написание нашей программы стоит именно с кернеля — функции, которую мы отправим на видеокарту для параллельного вычисления. Давайте рассмотрим как это делается.

Функцию кернеля нужно прописывать в отдельном файле с расширением .cl

Давайте поместим этот файл в корневую директорию нашего проекта и назовём vector_add.cl

Так-как язык OpenCL это слегка модифицированный С, проблем с написанием у нас не возникнет, и данный код выполнит нашу задачу:

__kernel void addition(__global const int *A, __global const int *B, __global int *C){ int i = get_global_id(0); // получаем индекс обрабатываемого элемента, он-же позиция элемента в массиве C[i] = A[i] + B[i]; // выполняем сложение}

  • Здесь, всё что мы делаем, это избавляемся от цикла for. Мы представляем что нужную нам операцию требуется выполнить всего один раз. Делается это потому что наш кернель будет отправлен на какое-то количество ядер видеокарты одновременно, и каждое ядро параллельно посчитает один элемент под индексом i из нашего массива. Стоит заметить что OpenCL не гарантирует выполнение операций по порядку — он может посчитать сначала двадцатый элемент, а потом третий.
  • Ключевое слово __kernel даст компилятору понять что функция addition — именно функция кернеля. Каждая декларация основной функции кернеля должна с него начинаться. Поскольку кернели ничего не возвращают, мы всегда указываем void как тип return функции (речь идёт об основных функциях, не вспомогательных. С ними вы можете работать так-же как и с обычными функциями С)
  • __global перед типом аргумента означает что данная переменная будет обработана в глобальной памяти (для обращения к локальной или приватной памяти, используются __local и __private соответственно)
  • Указатели на массивы A и B имеют модификатор constant, так как в этих массивах мы будем передавать информацию в кернель. В массив С мы будем записывать результат, по этому такого модификатора нет.
  • Функция get_global_id() позволяет получить уникальный идентификатор рабочей единицы (work-item) для данного измерения. Мы отправляем 0, потому-что у нас одномерный массив, соответственно, мы используем 0 для указания первого (и единственного) измерения. Да, с помощью OpenCL мы можем обрабатывать 2-х, 3-х, …-мерные объекты.

Программа-хост контролирует запуск и выполнение кернелей на вычислительных девайсах. Хост пишется на языке С, но существуют различные библиотеки-обвязки для работы с другими языками, например С++ или Python.

#include #include #ifdef __APPLE__# include // для компьютеров на MacOsX#else# include // для компьютеров на Win\Linux указывайте путь к файлу cl.h #endif #define MAX_SRC_SIZE (0x100000) // максимальный размер исходного кода кернеля

Всё приведённое ниже находится в теле функции main(). Для наглядности, я не стал это прописывать.

int main(void){ …код… return(0);}

int i;const int arr_size = 1024; // размер наших массивов int *A = (int *)malloc(sizeof(int) * arr_size); // выделяем место под массивы А и Вint *B = (int *)malloc(sizeof(int) * arr_size); for(i = 0; i < arr_size; i++) // наполняем массивы данными для отправки в кернель OpenCL{ A[i] = i; B[i] = arr_size - i;}

int fd;char *src_str; // сюда будет записан исходный код кернеляsize_t src_size; src_str = (char *)malloc(MAX_SRC_SIZE); // выделяем память для исходного кодаfd = open(“vector_add.cl”, O_RDONLY); // открываем файл с кодом кернеляif (fd

Источник: https://vc.ru/dev/159198-kak-uskorit-vychisleniya-i-povysit-proizvoditelnost-programm-s-pomoshchyu-principov-massivnogo-parallelizma-i-opencl

Драйверы OpenCL

Nvidia opencl

МИР NVIDIAДрайверы

Драйвер для видеокарт семейства GeForce 400 и выше, поддержка CUDA и ION/ION LE. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software. Обеспечивает поддержку дисплеев 4K (4kx2k @ 60 Hz).

Поддержка технологий GeForce ShadowPlay, NVIDIA GameStream, NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target, а также функции ShadowPlay Twitch Streaming. Добавлены и обновлены ряд SLI и 3D Vision профилей.

Драйверы Game Ready оптимизированы для Tekken 7 и Star Trek Bridge Crew.

Включают оптимизации для ряда популярных игр, обеспечивающие увеличение производительности для видеокарт семейств GeForce 800/900/10.

Драйвер для видеокарт семейства GeForce 8 и выше, поддержка CUDA и ION/ION LE. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software. Обеспечивает поддержку дисплеев 4K (4kx2k @ 60 Hz).

Поддержка технологий GeForce ShadowPlay, NVIDIA GameStream, NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target, а также функции ShadowPlay Twitch Streaming. Добавлены и обновлены ряд SLI и 3D Vision профилей.

Включают оптимизации для ряда популярных игр, обеспечивающие увеличение производительности для видеокарт семейств GeForce 400/500/600/700/900.

Драйвер для видеокарт семейства GeForce 8 и выше, поддержка CUDA и ION/ION LE. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software. Обеспечивает поддержку дисплеев 4K (4kx2k @ 60 Hz).

Поддержка технологий GeForce ShadowPlay, NVIDIA GameStream, NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target, а также функции ShadowPlay Twitch Streaming. Добавлены и обновлены ряд SLI и 3D Vision профилей.

Включают оптимизации для ряда популярных игр, обеспечивающие увеличение производительности для видеокарт семейств GeForce 400/500/600/700.

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software.

Обеспечивает поддержку дисплеев 4K (4kx2k @ 60 Hz).

Поддержка технологий NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target. Добавлено и обновлено множество SLI профилей и профилей 3D Vision.

Включают оптимизации для ряда популярных игр, обеспечивающие увеличение производительности для видеокарт семейств GeForce 400/500/600/700. Рекомендован для использования с ОС Windows 8.1 Preview.

Драйвер для видеокарт GeForce серии 8 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software. Обеспечивает поддержку DisplayPort 1.2 для серии GeForce GTX 600.

Поддержка технологий NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target. Добавлено и обновлено множество SLI профилей, а также профилей 3D Vision.

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

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software.

Поддержка технологий NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target. Добавлено и обновлено множество SLI профилей, а также профилей 3D Vision.

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

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision, HD Audio и PhysX System Software. Поддержка GPU серии GeForce GTX 6Х0. Добавлено и обновлено множество SLI профилей.

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision, HD Audio, NVIDIA Surround и PhysX System Software.

Поддержка GPU серии GeForce GTX 6Х0. Поддержка технологий NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target. Добавлено и обновлено множество SLI профилей. Рекомендованный драйвер для запуска ОС Windows 8.

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision, HD Audio и PhysX System Software. Поддержка новых GPU серии GeForce GT 600, введена поддержка GeForce GTX 660 и GeForce GTX 650. Поддержка технологий NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target.

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision. Поддержка новых GPU серии GeForce GT 600, введена поддержка GeForce GTX 660 Ti. Поддержка технологий NVIDIA FXAA, TXAA, Adaptive Vertical Sync, Frame Rate Target.

Драйвер для видеокарт GeForce 6 и выше, поддержка CUDA. Включает в себя драйвер контроллера 3D Vision. Поддержка новых GPU серии GeForce GT 600. Поддержка технологий NVIDIA FXAA, Adaptive Vertical Sync, Frame Rate Target.

Драйвер для видеокарт GeForce 6 и выше, поддержка ION. Включает в себя драйвер контроллера 3D Vision.

Источник: https://nvworld.ru/drivers/tags/opencl/

Как в Linux взламывать пароли видеокартой и центральным процессором

Nvidia opencl

В этой статье показано, какие драйверы и программы установить для того, чтобы hashcat и аналогичные программы для брут-форса могли использовать видеокарту и процессор для взлома паролей.

В настоящее время hashcat использует OpenCL. Как написано в Википедии, OpenCL (англ. Open Computing Language — открытый язык вычислений) — фреймворк для написания компьютерных программ, связанных с параллельными вычислениями на различных графических и центральных процессорах, а также FPGA.

В OpenCL входят язык программирования, который основан на стандарте языка программирования Си C99, и интерфейс программирования приложений. OpenCL обеспечивает параллелизм на уровне инструкций и на уровне данных и является осуществлением техники GPGPU.

OpenCL является полностью открытым стандартом, его использование не облагается лицензионными отчислениями.

Цель OpenCL состоит в том, чтобы дополнить открытые отраслевые стандарты для трёхмерной компьютерной графики и звука OpenGL и OpenAL возможностями GPU для высокопроизводительных вычислений. OpenCL разрабатывается и поддерживается некоммерческим консорциумом Khronos Group, в который входят много крупных компаний, включая AMD, Apple, ARM, Intel, Nvidia, Sony Computer Entertainment и другие.

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

OpenCL поддерживают видеокарты AMD, NVIDIA, а также Intel GPU.

Информацию о поддерживаемых процессорах Intel вы найдёте на странице https://github.com/intel/compute-runtime (поддержка «Intel Graphics Compute Runtime for oneAPI Level Zero and OpenCL» появилась с Gen8) и https://www.intel.ru/content/www/ru/ru/support/articles/000005524/graphics-drivers.html (поддержка OpenCL разными поколениями и моделями процессоров).

карты AMD, NVIDIA также в большинстве поддерживают OpenCL, кроме совсем старых.

Для работы OpenCL необходима установка драйвера и инструментов взаимодействия с OpenCL. Данная статья посвящена установке OpenCL в Linux. Аналогичные инструкции для Windows даны в статье «Инструкция по hashcat: запуск и использование программы для взлома паролей» (смотрите раздел «Драйверы для hashcat»).

Итак, требования для работы hashcat с OpenCL следующие:

  • Для AMD видеокарт необходимо: “RadeonOpenCompute (ROCm)” Software Platform (1.6.180 или более поздняя версия)
  • Для процессоров Intel необходимо: “OpenCL Runtime for Intel Core and Intel Xeon Processors” (16.1.1 или более поздняя версия)
  • Для NVIDIA видеокарт необходимо: “NVIDIA Driver” (367.x или более поздняя версия)

Для устаревших процессоров (до Broadwell) используется “OpenCL 2.0 GPU Driver Package for Linux” (Iris, Iris Pro).

В этой статье будет показано, как установить всё необходимое для использования OpenCL на видеокартах NVIDIA и современных процессорах Intel. Инструкции будут даны на примере Kali Linux (также должны подходить для Debian, Linux Mint, Ubuntu и их производных) и Arch Linux (BlackArch).

Включение OpenCL для NVIDIA

Начните с полного обновления системы и затем перезагрузитесь:

sudo apt update && sudo apt full-upgrade -y reboot

После того, как мы обновили систему, нужно проверить модули ядра nouveau (свободные драйвера Nvidia, они будут конфликтовать с проприетарными)

lsmod |grep -i nouveau

Если предыдущая команда хоть что-то вывела, например:

nouveau 1499136 1 mxm_wmi 16384 1 nouveau wmi 16384 2 mxm_wmi,nouveau video 40960 1 nouveau

это означает, что они включены. Поэтому необходимо добавить их в чёрный список:

echo -e “blacklist nouveauoptions nouveau modeset=0alias nouveau off” | sudo tee /etc/modprobe.d/blacklist-nouveau.conf

После изменения параметров ядра, нам нужно обновить наши initramfs и перезагрузиться.

update-initramfs -u && reboot После перезагрузки и проверки, что модули nouveau не загружены, мы переходим к установке загрузчика OpenCL ICD, драйверов и набора инструментов CUDA.
sudo apt install -y ocl-icd-libopencl1 nvidia-driver nvidia-cuda-toolkit

Во время установки драйверов система создаёт новые модули ядра, поэтому требуется ещё одна перезагрузка.

Проверка установленных драйверов

Теперь наша система должна быть готова, нам нужно проверить, что драйверы корректно загружены. Мы можем быстро в этом убедиться запустив инструмент nvidia-smi.

nvidia-smi

Вывод показывает, что наш драйвер и GPU в порядке — можно приступать к взлому паролей. Перед продолжением, давайте ещё раз сделаем проверку и убедимся, что hashcat и CUDA работают вместе.

hashcat -I

Примечание:

Если вы получили ошибку clGetDeviceIDs(): CL_DEVICE_NOT_FOUND с отметкой Platform ID Vendor: Mesa, то запустите:

sudo apt remove mesa-opencl-icd

Продолжим запуском теста производительности. Бенчмарк

hashcat -b -D 1,2 –force

Включение OpenCL для Intel

Если ваш центральный процессор поддерживает OpenCL, то установите следующие пакеты:

sudo apt install firmware-misc-nonfree intel-opencl-icd

Просмотрим список устройств ещё раз (должно добавиться новое устройство):

hashcat -I

И выполним бенчмар ещё раз:

hashcat -b -D 1,2 –force

Пакет beignet

beignet — это реализация OpenCL для Intel IvyBridge и Haswell iGPUs. В настоящее время этот пакет считается устаревшим и его должен заменить intel-compute-runtime. У меня в системе установить beignet, то появляется дополнительное устройство OpenCL — как на Kali Linux, где также видно 3 устройства OpenCL. Но это устройство работает нестабильно с Hashcat.

Вы можете протестировать, как себя ведёт beignet на вашей системе. Возможно, для более старых процессоров это единственная опция.

Поделиться:
Нет комментариев

    Добавить комментарий

    Ваш e-mail не будет опубликован. Все поля обязательны для заполнения.