Все, что связано с GPU: часть 4

В разделе 3 мы рассмотрели основы ядер и рабочих измерений. Мы также сделали несколько базовых выборок и параллельную математику для выборок. Как насчет более практических вариантов использования? В этом разделе мы представим еще несколько приемов в стеке Mawsh, которые помогут упростить разработку. А именно, мы упростим размещение удобочитаемых данных в ваших буферах и работу с ними. Не забывайте, что вы можете установить любой код и примеры из этой серии через репозиторий COPR здесь: https://copr.fedorainfracloud.org/coprs/boeroboy/mawenzy/

Уродливый

Многие алгоритмы не являются идеальными кандидатами для параллельной реализации. Строки переменной длины, неоднородные данные и динамические адреса обычно не выиграют от устройства с графическим процессором. На самом деле многие из них будут работать намного медленнее без правильной настройки или подхода. Мы уже показали это на примере циклов for по сравнению с параллельными волновыми фронтами. Здесь мы рассмотрим некоторые из самых больших табу вычислений на GPU. На самом деле, наложите на себя некоторые табу, пока мы освещаем эти темы, потому что профессионалы по графическим процессорам будут стоять рядом с возражениями на каждом этапе пути. Это урок того, что можно сделать, но, вероятно, не следует делать с устройствами на GPU. Затем мы расскажем, как оптимизировать и заставить эти задачи работать намного лучше. Наконец, мы придем к выводу, какие из них являются хорошими кандидатами, а какие нет после оптимизации.

  • Мы введем нотацию объекта для простого импорта жестких данных с ограниченной схемой в стиле CSV. База OpenCL C99 и статические буферы не подходят для данных без схемы, но создание схемы с использованием структур может быть очень простым с проверкой ошибок типов.
  • Текстовый анализ. Мы покажем, как легко можно создать простое приложение grep на графическом процессоре. Потом будем оптимизировать. В следующем разделе мы удвоим и изменим его, чтобы делать замечательные вещи.
  • Мы представим пакет HTML и покажем, как на самом деле можно генерировать HTML-ответы непосредственно из графического процессора, управляя состоянием с помощью буферов графического процессора. Хотя GPU не подходит для обычного HTML, он может ускорить некоторые операции рендеринга таблиц и сортировки с помощью параллелизма.
  • Мы познакомимся с набором инструментов BMP, который позволяет быстро генерировать необработанные файлы изображений BMP и использовать их в качестве буферов. Это требует некоторой хитрости выравнивания, прежде чем это сработает. OpenCL имеет встроенные типы текстур и изображений, обычно предназначенные для приложений OpenGL, но не все оборудование поддерживает их. Мы пойдем довольно обобщенно, даже если это не оптимально, демонстрируя базовые фильтры изображений и базовый трассировщик лучей.

Атомикс

Поскольку волновые фронты ядра параллельны, у нас нет никаких гарантий относительно порядка вещей. Нам может понадобиться синхронизация при трансляции параллельных заданий на независимые ядра. Если тысячи рабочих элементов одновременно назначают один и тот же адрес памяти, какой из них выиграет? Atomics позволяет контролировать этот уродливый сценарий в параллельных вычислениях. Рабочий элемент может эффективно заблокировать адрес для эксклюзивных операций, но это приостановит выполнение. Например, если у нас есть 16 000 сделок с акциями, и нам нужно вычислить их минимальное/максимальное значение, как мы это сделаем? Традиционный максимум массива обычно представляет собой цикл for по всему массиву. В OpenCL мы можем найти массив max с помощью одной строки, используя одну из встроенных атомарных функций OpenCL, которая называется atomic_max. Обратите внимание, что хотя это все еще может работать не лучше, чем мощный ЦП, может быть выгодно вычислять их на ГП, когда данные уже есть, а не загружать/выгружать буферы ГП. Кроме того, это может иногда давать лучшую производительность на ватт, а также стабильно работать, когда ЦП уже загружен другими задачами. В наших испытаниях будет довольно часто использоваться атомарность, но постарайтесь свести ее к минимуму, когда счет идет на наносекунды.

OpenCL 2.0 представил новые способы работы с атомарными объектами, которые можно найти здесь: https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/atomicFunctions.html. Лично я нахожу его гораздо более громоздким, но он дает немного более детальный контроль.

КЛОН

Ранее мы работали с необработанными бинарными буферами. Когда MawD создает буферы, он инициализирует их нулями. Затем мы заполнили буферы случайным двоичным кодом через процессор и устройство /dev/urandom. В идеале мы могли бы работать с большими наборами данных, не обращая внимания на двоичные или шестнадцатеричные калькуляторы. В еще более идеальном случае мы могли бы использовать полнофункциональную базу данных на базе графического процессора, такую ​​​​как MapD, но сейчас мы сначала подробно изучаем, как работают эти платформы.

Так уж получилось, что C99 допускает некоторые хитрости, делающие загрузку плоских массивов проще простого. Считайте это таблицей со схемой, загруженной компилятором. В простейшем виде это выглядит так:

Не многие понимают, что C позволяет инициализировать структуры аналогично JSON, но это может быть мощным инструментом. Предостережения заключаются в том, что схема должна быть определена, и компилятор должен анализировать все сразу. Хорошей новостью является отличная производительность и проверка ошибок. Объекты автоматически преобразуются в собственные типы без необходимости анализа чисел во время выполнения. Простая обертка файла CSV может создать простой импорт для анализа графического процессора. К сожалению, нам нужно написать сериализатор для извлечения этих двоичных данных обратно в качестве источника, поскольку в C99 нет отражения.

HTML

Как я уже упоминал ранее, строки и данные переменной длины, как правило, не являются хорошими кандидатами для вычислений на GPU, но вполне возможно генерировать веб-контент, используя только GPU. Это даже просто и в некоторых случаях идеально. HTML — чрезвычайно неэффективный язык разметки для чтения машинами в целом, но для его создания можно использовать графический процессор. Что еще более важно, графические процессоры также могут анализировать HTML, что является гораздо лучшим вариантом использования. Мы попробуем и то, и другое, начиная с уродливого способа сделать что-то. Для начала мы просто используем printmc, который копирует строки байт за байтом с помощью цикла for. В следующих разделах мы покажем менее уродливый пример того, как мы можем использовать параллельные ядра для гораздо более быстрого рендеринга результата.

Некоторые веб-разработчики не ценят приложение, которое не использует HTTP или веб-службу, поэтому давайте создадим его. Поскольку код графического процессора теперь можно запускать как скрипт, мы можем представить его с помощью простого CGI. У CGI есть проблемы как с производительностью, так и с безопасностью, поэтому в идеале мы должны создать плагин для NGinx или Apache, который использует быстрые встроенные буферы с отображением DMA. На данный момент все, что нам нужно сделать, это включить Apache или NGinx с CGI и вызвать наш скрипт для создания контента. Мы даже можем передавать параметры, значения GET или POST, но сейчас мы просто начнем с простого (и уродливого). Содержимое mawsh.cgi:

#!/bin/bash 
./test.mawsh state=@[8]state

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

JSON

HTML переменной длины далеко не оптимален для графического процессора, но как насчет структур одинаковой длины? Такие вещи, как таблицы HTML и списки JSON, на самом деле удивительно подходят для параллельных вычислений при работе с большими наборами данных. Вместо рендеринга мозаичных повторяющихся текстур мы можем рендерить однородные блоки данных JSON с удивительной скоростью. В следующем разделе мы соберем вместе несколько больших наборов данных и посмотрим, насколько быстро это можно сделать.

Наборы инструментов BMP + TIFF

Внутри каталога mawsh include также есть инструменты для создания необработанных изображений BMP и TIFF. Используя некоторые ярлыки, эти заголовки включают базовую, но универсальную реализацию 32-битного BMP примерно в 80 строках кода. Поскольку некоторые реализации BMP не очень хорошо поддерживают альфа-канал, TIFF включен в качестве альтернативы примерно в 130 строк кода. Вы указываете размер своего изображения и предоставляете для него собственный буфер. Написание этого кода выявляет некоторые проблемы с выравниванием памяти в OpenCL. Теоретически было бы просто иметь стандартный 24-битный BMP, но на практике большинство реализаций OpenCL используют выравнивание структур и заполнение до степени двойки. Часто структура с 4-байтовым элементом приводит к тому, что все элементы занимают 4 байта. Таким образом, в массиве векторов uchar3 каждый элемент фактически занимает то же место, что и uchar4. Это приводит к тому, что встроенная двоичная поддержка прерывается при чтении на хосте с другими правилами выравнивания. Некоторые библиотеки изображений и приложения не могут обрабатывать 32-битные файлы BMP, хотя они соответствуют спецификации BMP. Иногда простой просмотрщик изображений не может его взломать, но мне всегда нравится включать альфа-каналы.

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

Тест несправедлив, так как и ЦП, и ГП также заняты другими задачами, а именно захватом этого GIF и Spotify my Crosby Stills Nash & Young. В идеале изображения должны обрабатываться через объектный тип OpenCL image2d вместо общих буферов, но тогда мы не могли бы инкапсулировать их в файл структуры изображения с информацией заголовка и просматривать их в приложениях-редакторах. Этот код выполняет довольно небольшое преобразование между числами с плавающей запятой и uchar, что было бы намного проще с помощью собственного типа image2d. MawD еще не поддерживает типы объектов изображения, но если бы вы писали механизм рендеринга, в котором учитываются наносекунды, вы определенно хотели бы использовать объекты изображения в своем коде. Даже 0,012 секунды — это вечность, когда нужно рендерить всю сцену 100 раз в секунду. Изображение, сгенерированное приведенным выше кодом, можно найти ниже при просмотре с альфа-каналом в Gimp. Mandelbrot представляет собой забавный порт OpenCL и действительно хорошо сочетается с CSN & Y, но требуются итерации, которые проверяют преимущество GPU перед CPU. Мы можем заняться этим позже.

Вывод

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

Мы изучили некоторые базовые фреймворки для веб-контента и графического контента, а также рассмотрели, как можно управлять большими наборами данных в самом графическом процессоре. Эти данные довольно жесткие по сравнению с данными без схемы, используемыми в ЦП, но хорошая новость заключается в том, что установление жесткой схемы на самом деле упрощает быстрый анализ, например поиск данных для минимальных/максимальных значений или значений, которые представляют интерес.

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

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

Раздел 5: Плохое (СКОРО)