Использование карты для вычислений. Эффективное использование GPU. Что такое CUDA

Часто стал появляться вопрос: почему нет GPU ускорения в программе Adobe Media Encoder CC? А то что Adobe Media Encoder использует GPU ускорение, мы выяснили , а также отметили нюансы его использования . Также встречается утверждение: что в программе Adobe Media Encoder CC убрали поддержку GPU ускорения. Это ошибочное мнение и вытекает из того, что основная программа Adobe Premiere Pro CC теперь может работать без прописанной и рекомендованной видеокарты, а для включения GPU движка в Adobe Media Encoder CC, видеокарта должна быть обязательно прописана в документах: cuda_supported_cards или opencl_supported_cards. Если с чипсетами nVidia все понятно, просто берем имя чипсета и вписываем его в документ cuda_supported_cards. То при использовании видеокарт AMD прописывать надо не имя чипсета, а кодовое название ядра. Итак, давайте на практике проверим, как на ноутбуке ASUS N71JQ с дискретной графикой ATI Mobility Radeon HD 5730 включить GPU движок в Adobe Media Encoder CC. Технические данные графического адаптера ATI Mobility Radeon HD 5730 показываемые утилитой GPU-Z:

Запускаем программу Adobe Premiere Pro CC и включаем движок: Mercury Playback Engine GPU Acceleration (OpenCL).

Три DSLR видео на таймлайне, друг над другом, два из них, создают эффект картинка в картинке.

Ctrl+M, выбираем пресет Mpeg2-DVD, убираем черные полосы по бокам с помощью опции Scale To Fill. Включаем также повышеное качество для тестов без GPU: MRQ (Use Maximum Render Quality). Нажимаем на кнопку: Export. Загрузка процессора до 20% и оперативной памяти 2.56 Гбайт.


Загрузка GPU чипсета ATI Mobility Radeon HD 5730 составляет 97% и 352Мб бортовой видеопамяти. Ноутбук тестировался при работе от аккумулятора, поэтому графическое ядро / память работают на пониженных частотах: 375 / 810 МГц.

Итоговое время просчета: 1 минута и 55 секунд (вкл/откл. MRQ при использовании GPU движка, не влияет на итогове время просчета).
При установленной галке Use Maximum Render Quality теперь нажимаем на кнопку: Queue.


Тактовые частоты процессора при работе от аккумулятора: 930МГц.

Запускаем AMEEncodingLog и смотрим итоговое время просчета: 5 минут и 14 секунд .

Повторяем тест, но уже при снятой галке Use Maximum Render Quality, нажимаем на кнопку: Queue.

Итоговое время просчета: 1 минута и 17 секунд .

Теперь включим GPU движок в Adobe Media Encoder CC, запускаем программу Adobe Premiere Pro CC, нажимаем комбинацию клавиш: Ctrl + F12, выполняем Console > Console View и в поле Command вбиваем GPUSniffer, нажимаем Enter.


Выделяем и копируем имя в GPU Computation Info.

В директории программы Adobe Premiere Pro CC открываем документ opencl_supported_cards, и в алфавитном порядке вбиваем кодовое имя чипсета, Ctrl+S.

Нажимаем на кнопку: Queue, и получаем GPU ускорение просчета проекта Adobe Premiere Pro CC в Adobe Media Encoder CC.

Итоговое время: 1 минута и 55 секунд .

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


Тактовые частоты процессора: 1.6ГГц при работе от розетки и включении режима: Высокая производительность.

Итоговое время: 46 секунд .

Включаем движок: Mercury Playback Engine GPU Acceleration (OpenCL), как видно от сети ноутбучная видеокарта работает на своих базовых частотах, загрузка GPU в Adobe Media Encoder CC достигает 95%.

Итоговое время просчета, снизилось с 1 минуты 55 секунд , до 1 минуты и 5 секунд .

*Для визуализации в Adobe Media Encoder CC теперь используется графический процессор (GPU). Поддерживаются стандарты CUDA и OpenCL. В Adobe Media Encoder CC, движок GPU используется для следующих процессов визуализации:
- Изменение четкости (от высокой к стандартной и наоборот).
- Фильтр временного кода.
- Преобразования формата пикселей.
- Расперемежение.
Если визуализируется проект Premiere Pro, в AME используются установки визуализации с GPU, заданные для этого проекта. При этом будут использованы все возможности визуализации с GPU, реализованные в Premiere Pro. Для визуализации проектов AME используется ограниченный набор возможностей визуализации с GPU. Если последовательность визуализируется с использованием оригинальной поддержки, применяется настройка GPU из AME, настройка проекта игнорируется. В этом случае все возможности визуализации с GPU Premiere Pro используются напрямую в AME. Если проект содержит VST сторонних производителей, используется настройка GPU проекта. Последовательность кодируется с помощью PProHeadless, как и в более ранних версиях AME. Если флажок Enable Native Premiere Pro Sequence Import (Разрешить импорт исходной последовательности Premiere Pro) снят, всегда используется PProHeadless и настройка GPU.

Читаем про скрытый раздел на системном диске ноутбука ASUS N71JQ.

Использование GPU для вычислений с помощью C++ AMP

До сих пор в обсуждении приемов параллельного программирования мы рассматривали только ядра процессора. Мы приобрели некоторые навыки распараллеливания программ по нескольким процессорам, синхронизации доступа к совместно используемым ресурсам и использования высокоскоростных примитивов синхронизации без применения блокировок.

Однако, существует еще один способ распараллеливания программ - графические процессоры (GPU) , обладающие большим числом ядер, чем даже высокопроизводительные процессоры. Ядра графических процессоров прекрасно подходят для реализации параллельных алгоритмов обработки данных, а большое их количество с лихвой окупает неудобства выполнения программ на них. В этой статье мы познакомимся с одним из способов выполнения программ на графическом процессоре, с использованием комплекта расширений языка C++ под названием C++ AMP .

Расширения C++ AMP основаны на языке C++ и именно поэтому в данной статье будут демонстрироваться примеры на языке C++. Однако, при умеренном использовании механизма взаимодействий в. NET, вы сможете использовать алгоритмы C++ AMP в своих программах для.NET. Но об этом мы поговорим в конце статьи.

Введение в C++ AMP

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

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

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

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

Сразу возникает вопрос, какие задачи подходят для решения на графическом процессоре? Имейте в виду, что не всякий алгоритм подходит для выполнения на графическом процессоре. Например, графические процессоры не имеют доступа к устройствам ввода/вывода, поэтому у вас не получится повысить производительность программы, извлекающей ленты RSS из интернета, за счет использования графического процессора. Однако на графический процессор можно перенести многие вычислительные алгоритмы и обеспечить массовое их распараллеливание. Ниже приводится несколько примеров таких алгоритмов (этот список далеко не полон):

    увеличение и уменьшение резкости изображений, и другие преобразования;

    быстрое преобразование Фурье;

    транспонирование и умножение матриц;

    сортировка чисел;

    инверсия хеша «в лоб».

Отличным источником дополнительных примеров может служить блог Microsoft Native Concurrency , где приводятся фрагменты кода и пояснения к ним для различных алгоритмов, реализованных на C++ AMP.

C++ AMP - это фреймворк, входящий в состав Visual Studio 2012, дающий разработчикам на C++ простой способ выполнения вычислений на графическом процессоре и требующий лишь наличия драйвера DirectX 11. Корпорация Microsoft выпустила C++ AMP как открытую спецификацию , которую может реализовать любой производитель компиляторов.

Фреймворк C++ AMP позволяет выполнять код на графических ускорителях (accelerators) , являющихся вычислительными устройствами. С помощью драйвера DirectX 11 фреймворк C++ AMP динамически обнаруживает все ускорители. В состав C++ AMP входят также программный эмулятор ускорителя и эмулятор на базе обычного процессора, WARP, которые служит запасным вариантом в системах без графического процессора или с графическим процессором, но в отсутствие драйвера DirectX 11, и использует несколько ядер и инструкции SIMD.

А теперь приступим к исследованию алгоритма, который легко можно распараллелить для выполнения на графическом процессоре. Реализация ниже принимает два вектора одинаковой длины и вычисляет поточечный результат. Сложно представить что-либо более прямолинейное:

Void VectorAddExpPointwise(float* first, float* second, float* result, int length) { for (int i = 0; i < length; ++i) { result[i] = first[i] + exp(second[i]); } }

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

Для графического процессора эти предупреждения не нужны. Графические процессоры имеют множество ядер, выполняющих потоки очень быстро, а стоимость переключения контекста значительно ниже, чем в обычных процессорах. Ниже приводится фрагмент, пытающийся использовать функцию parallel_for_each из фреймворка C++ AMP:

#include #include using namespace concurrency; void VectorAddExpPointwise(float* first, float* second, float* result, int length) { array_view avFirst (length, first); array_view avSecond(length, second); array_view avResult(length, result); avResult.discard_data(); parallel_for_each(avResult.extent, [=](index<1> i) restrict(amp) { avResult[i] = avFirst[i] + fast_math::exp(avSecond[i]); }); avResult.synchronize(); }

Теперь исследуем каждую часть кода отдельно. Сразу заметим, что общая форма главного цикла сохранилась, но первоначально использовавшийся цикл for был заменен вызовом функции parallel_for_each. В действительности, принцип преобразования цикла в вызов функции или метода для нас не нов - ранее уже демонстрировался такой прием с применением методов Parallel.For() и Parallel.ForEach() из библиотеки TPL.

Далее, входные данные (параметры first, second и result) обертываются экземплярами array_view . Класс array_view служит для обертывания данных, передаваемых графическому процессору (ускорителю). Его шаблонный параметр определяет тип данных и их размерность. Чтобы выполнить на графическом процессоре инструкции, обращающиеся к данным, первоначально обрабатываемым на обычном процессоре, кто-то или что-то должен позаботиться о копировании данных в графический процессор, потому что большинство современных графических карт являются отдельными устройствами с собственной памятью. Эту задачу решают экземпляры array_view - они обеспечивают копирование данных по требованию и только когда они действительно необходимы.

Когда графический процессор выполнит задание, данные копируются обратно. Создавая экземпляры array_view с аргументом типа const, мы гарантируем, что first и second будут скопированы в память графического процессора, но не будут копироваться обратно. Аналогично, вызывая discard_data() , мы исключаем копирование result из памяти обычного процессора в память ускорителя, но эти данные будут копироваться в обратном направлении.

Функция parallel_for_each принимает объект extent, определяющий форму обрабатываемых данных и функцию для применения к каждому элементу в объекте extent. В примере выше мы использовали лямбда-функцию, поддержка которых появилась в стандарте ISO C++2011 (C++11). Ключевое слово restrict (amp) поручает компилятору проверить возможность выполнения тела функции на графическом процессоре и отключает большую часть синтаксиса C++, который не может быть скомпилирован в инструкции графического процессора.

Параметр лямбда-функции, index<1> объекта, представляет одномерный индекс. Он должен соответствовать используемому объекту extent - если бы мы объявили объект extent двумерным (например, определив форму исходных данных в виде двумерной матрицы), индекс также должен был бы быть двумерным. Пример такой ситуации приводится чуть ниже.

Наконец, вызов метода synchronize() в конце метода VectorAddExpPointwise гарантирует копирование результатов вычислений из array_view avResult, произведенных графическим процессором, обратно в массив result.

На этом мы заканчиваем наше первое знакомство с миром C++ AMP, и теперь мы готовы к более подробным исследованиям, а так же к более интересным примерам, демонстрирующим выгоды от использования параллельных вычислений на графическом процессоре. Сложение векторов - не самый удачный алгоритм и не самый лучший кандидат для демонстрации использования графического процессора из-за больших накладных расходов на копирование данных. В следующем подразделе будут показаны два более интересных примера.

Умножение матриц

Первый «настоящий» пример, который мы рассмотрим, - умножение матриц. Для реализации мы возьмем простой кубический алгоритм умножения матриц, а не алгоритм Штрассена, имеющий время выполнения, близкое к кубическому ~O(n 2.807). Для двух матриц: матрицы A размером m x w и матрицы B размером w x n, следующая программа выполнит их умножение и вернет результат - матрицу C размером m x n:

Void MatrixMultiply(int* A, int m, int w, int* B, int n, int* C) { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { int sum = 0; for (int k = 0; k < w; ++k) { sum += A * B; } C = sum; } } }

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

Void MatrixMultiply (int* A, int m, int w, int* B, int n, int* C) { array_view avA(m, w, A); array_view avB(w, n, B); array_view avC(m, n, C); avC.discard_data(); parallel_for_each (avC.extent, [=](index <2> idx) restrict(amp) { int sum = 0; for (int k = 0; k < w; ++k) { sum + = avA(idx*w, k) * avB(k*w, idx); } avC = sum; }); }

Эта реализация все еще близко напоминает последовательную реализацию умножения матриц и пример сложения векторов, приводившиеся выше, за исключением индекса, который теперь является двумерным и доступен во внутреннем цикле с применением оператора . Насколько эта версия быстрее последовательной альтернативы, выполняемой на обычном процессоре? Умножение двух матриц (целых чисел) размером 1024 х 1024 последовательная версия на обычном процессоре выполняет в среднем 7350 миллисекунд, тогда как версия для графического процессора - держитесь крепче - 50 миллисекунд, в 147 раз быстрее!

Моделирование движения частиц

Примеры решения задач на графическом процессоре, представленные выше, имеют очень простую реализацию внутреннего цикла. Понятно, что так будет не всегда. В блоге Native Concurrency, ссылка на который уже приводилась выше, демонстрируется пример моделирования гравитационных взаимодействий между частицами. Моделирование включает бесконечное количество шагов; на каждом шаге вычисляются новые значения элементов вектора ускорений для каждой частицы и затем определяются их новые координаты. Здесь распараллеливанию подвергается вектор частиц - при достаточно большом количестве частиц (от нескольких тысяч и выше) можно создать достаточно большое количество заданий, чтобы загрузить работой все ядра графического процессора.

Основу алгоритма составляет реализация определения результата взаимодействий между двумя частицами, как показано ниже, которую легко можно перенести на графический процессор:

// здесь float4 - это векторы с четырьмя элементами, // представляющие частицы, участвующие в операциях void bodybody_interaction (float4& acceleration, const float4 p1, const float4 p2) restrict(amp) { float4 dist = p2 – p1; // w здесь не используется float absDist = dist.x*dist.x + dist.y*dist.y + dist.z*dist.z; float invDist = 1.0f / sqrt(absDist); float invDistCube = invDist*invDist*invDist; acceleration + = dist*PARTICLE_MASS*invDistCube; }

Исходными данными на каждом шаге моделирования является массив с координатами и скоростями движения частиц, а в результате вычислений создается новый массив с координатами и скоростями частиц:

Struct particle { float4 position, velocity; // реализации конструктора, конструктора копирования и // оператора = с restrict(amp) опущены для экономии места }; void simulation_step(array & previous, array & next, int bodies) { extent <1> ext(bodies); parallel_for_each (ext, [&](index <1> idx) restrict(amp) { particle p = previous; float4 acceleration(0, 0, 0, 0); for (int body = 0; body < bodies; ++body) { bodybody_interaction (acceleration, p.position, previous.position); } p.velocity + = acceleration*DELTA_TIME; p.position + = p.velocity*DELTA_TIME; next = p; }); }

С привлечением соответствующего графического интерфейса, моделирование может оказаться очень интересным. Полный пример, представленный командой разработчиков C++ AMP, можно найти в блоге Native Concurrency. На моей системе с процессором Intel Core i7 и видеокартой Geforce GT 740M, моделирование движения 10 000 частиц выполняется со скоростью ~2.5 кадра в секунду (шагов в секунду) с использованием последовательной версии, выполняющейся на обычном процессоре, и 160 кадров в секунду с использованием оптимизированной версии, выполняющейся на графическом процессоре - огромное увеличение производительности.

Прежде чем завершить этот раздел, необходимо рассказать еще об одной важной особенности фреймворка C++ AMP, которая может еще больше повысить производительность кода, выполняемого на графическом процессоре. Графические процессоры поддерживают программируемый кеш данных (часто называемый разделяемой памятью (shared memory) ). Значения, хранящиеся в этом кеше, совместно используются всеми потоками выполнения в одной мозаике (tile). Благодаря мозаичной организации памяти, программы на основе фреймворка C++ AMP могут читать данные из памяти графической карты в разделяемую память мозаики и затем обращаться к ним из нескольких потоков выполнения без повторного извлечения этих данных из памяти графической карты. Доступ к разделяемой памяти мозаики выполняется примерно в 10 раз быстрее, чем к памяти графической карты. Иными словами, у вас есть причины продолжить чтение.

Чтобы обеспечить выполнение мозаичной версии параллельного цикла, методу parallel_for_each передается домен tiled_extent , который делит многомерный объект extent на многомерные фрагменты мозаики, и лямбда-параметр tiled_index, определяющий глобальный и локальный идентификатор потока внутри мозаики. Например, матрицу 16x16 можно разделить на фрагменты мозаики размером 2x2 (как показано на рисунке ниже) и затем передать функции parallel_for_each:

Extent <2> matrix(16,16); tiled_extent <2,2> tiledMatrix = matrix.tile <2,2> (); parallel_for_each (tiledMatrix, [=](tiled_index <2,2> idx) restrict(amp) { // ... });

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

При выполнении операций с матрицами, в ядре графического процессора, взамен стандартного индекса index<2>, как в примерах выше, можно использовать idx.global . Грамотное использование локальной мозаичной памяти и локальных индексов может обеспечить существенный прирост производительности. Чтобы объявить мозаичную память, разделяемую всеми потоками выполнения в одной мозаике, локальные переменные можно объявить со спецификатором tile_static.

На практике часто используется прием объявления разделяемой памяти и инициализации отдельных ее блоков в разных потоках выполнения:

Parallel_for_each(tiledMatrix, [=](tiled_index <2,2> idx) restrict(amp) { // 32 байта совместно используются всеми потоками в блоке tile_static int local; // присвоить значение элементу для этого потока выполнения local = 42; });

Очевидно, что какие-либо выгоды от использования разделяемой памяти можно получить только в случае синхронизации доступа к этой памяти; то есть, потоки не должны обращаться к памяти, пока она не будет инициализирована одним из них. Синхронизация потоков в мозаике выполняется с помощью объектов tile_barrier (напоминающего класс Barrier из библиотеки TPL) - они смогут продолжить выполнение только после вызова метода tile_barrier.Wait(), который вернет управление только когда все потоки вызовут tile_barrier.Wait. Например:

Parallel_for_each (tiledMatrix, (tiled_index <2,2> idx) restrict(amp) { // 32 байта совместно используются всеми потоками в блоке tile_static int local; // присвоить значение элементу для этого потока выполнения local = 42; // idx.barrier - экземпляр tile_barrier idx.barrier.wait(); // Теперь этот поток может обращаться к массиву "local", // используя индексы других потоков выполнения! });

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

Суть этого приема сводится к следующему. Чтобы найти C i,j (элемент в строке i и в столбце j в матрице результата), нужно вычислить скалярное произведение между A i,* (i-я строка первой матрицы) и B *,j (j-й столбец во второй матрице). Однако, это эквивалентно вычислению частичных скалярных произведений строки и столбца с последующим суммированием результатов. Мы можем использовать это обстоятельство для преобразования алгоритма умножения матриц в мозаичную версию:

Void MatrixMultiply(int* A, int m, int w, int* B, int n, int* C) { array_view avA(m, w, A); array_view avB(w, n, B); array_view avC(m, n, C); avC.discard_data(); parallel_for_each (avC.extent.tile <16,16> (), [=](tiled_index <16,16> idx) restrict(amp) { int sum = 0; int localRow = idx.local, localCol = idx.local; for (int k = 0; k

Суть описываемой оптимизации в том, что каждый поток в мозаике (для блока 16 х 16 создается 256 потоков) инициализирует свой элемент в 16 х 16 локальных копиях фрагментов исходных матриц A и B. Каждому потоку в мозаике требуется только одна строка и один столбец из этих блоков, но все потоки вместе будут обращаться к каждой строке и к каждому столбцу по 16 раз. Такой подход существенно снижает количество обращений к основной памяти.

Чтобы вычислить элемент (i,j) в матрице результата, алгоритму требуется полная i-я строка первой матрицы и j-й столбец второй матрицы. Когда потоки мозаике 16x16, представленные на диаграмме и k=0, заштрихованные области в первой и второй матрицах будут прочитаны в разделяемую память. Поток выполнения, вычисляющий элемент (i,j) в матрице результата, вычислит частичное скалярное произведение первых k элементов из i-й строки и j-го столбца исходных матриц.

В данном примере применение мозаичной организации обеспечивает огромный прирост производительности. Мозаичная версия умножения матриц выполняется намного быстрее простой версии и занимает примерно 17 миллисекунд (для тех же исходных матриц размером 1024 х 1024), что в 430 быстрее версии, выполняемой на обычном процессоре!

Прежде чем закончить обсуждение фреймворка C++ AMP, нам хотелось бы упомянуть инструменты (в Visual Studio), имеющиеся в распоряжении разработчиков. Visual Studio 2012 предлагает отладчик для графического процессора (GPU), позволяющий устанавливать контрольные точки, исследовать стек вызовов, читать и изменять значения локальных переменных (некоторые ускорители поддерживают отладку для GPU непосредственно; для других Visual Studio использует программный симулятор), и профилировщик, дающий возможность оценивать выгоды, получаемые приложением от распараллеливания операций с применением графического процессора. За дополнительной информацией о возможностях отладки в Visual Studio обращайтесь к статье «Пошаговое руководство. Отладка приложения C++ AMP» на сайте MSDN.

Альтернативы вычислений на графическом процессоре в.NET

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

Другой способ - использовать библиотеку, непосредственно работающую с графическим процессором из управляемого кода. В настоящее время существует несколько таких библиотек. Например, GPU.NET и CUDAfy.NET (обе являются коммерческими предложениями). Ниже приводится пример из репозитория GPU.NET GitHub, демонстрирующий реализацию скалярного произведения двух векторов:

Public static void MultiplyAddGpu(double a, double b, double c) { int ThreadId = BlockDimension.X * BlockIndex.X + ThreadIndex.X; int TotalThreads = BlockDimension.X * GridDimension.X; for (int ElementIdx = ThreadId; ElementIdx

Я придерживаюсь мнения, что гораздо проще и эффективнее освоить расширение языка (на основе C++ AMP), чем пытаться организовывать взаимодействия на уровне библиотек или вносить существенные изменения в язык IL.

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

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

Фреймворк C++ AMP и другие многоцелевые библиотеки организации параллельных вычислений на графическом процессоре с успехом можно использовать для распараллеливания вычислений между сотнями ядер графического процессора. Наконец, имеется, неисследованная ранее, возможность получить прирост производительности от применения облачных технологий распределенных вычислений, превратившихся в последнее время в одно из основных направлений развития информационных технологий.

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

Что такое майнинг на видеокарте

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

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

Какие видеокарты подойдут для майнинга

Итак, что касается выбора видеокарты, то здесь обычной практикой является приобретение AMD rx 470, rx 480, rx 570, rx 580 или Нвидиа 1060, 1070, 1080 ti. Также подойдут, но не принесут большой прибыли, видеокарты типа r9 280x, r9 290, 1050, 1060. Совершенно точно не принесёт прибыли майнинг на слабой видеокарте вроде geforce gtx 460, gts 450, gtx 550ti. Если говорить о памяти, то брать лучше от 2 гб. Может оказаться недостаточно даже 1 гб, не говоря уже о 512 мб. Если говорить про майнинг на профессиональной видеокарте, то приносит он примерно столько же, сколько и обычные или даже меньше. С учётом стоимости таких ВК - это невыгодно, но добывать с их помощью можно, если они уже есть у вас в наличии.

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

Самые популярные видеокарты для майнинга 2020

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

Видеокарта Ethash Equihash CryptoNight Энергопотребление
AMD Radeon R9 280x 11 MH/s 290 H/s 490 H/s 230W
AMD Radeon RX 470 26 MH/s 260 H/s 660 H/s 120W
AMD Radeon RX 480 29.5 MH/s 290 H/s 730 H/s 135W
AMD Radeon RX 570 27.9 MH/s 260 H/s 700 H/s 120W
AMD Radeon RX 580 30.2 MH/s 290 H/s 690 H/s 135W
Nvidia GeForce GTX 750 TI 0.5 MH/s 75 H/s 250 H/s 55W
Nvidia GeForce GTX 1050 TI 13.9 MH/s 180 H/s 300 H/s 75W
Nvidia GeForce GTX 1060 22.5 MH/s 270 H/s 430 H/s 90W
Nvidia GeForce GTX 1070 30 MH/s 430 H/s 630 H/s 120W
Nvidia GeForce GTX 1070 TI 30.5 MH/s 470 H/s 630 H/s 135W
Nvidia GeForce GTX 1080 23.3 MH/s 550 H/s 580 H/s 140W
Nvidia GeForce GTX 1080 TI 35 MH/s 685 H/s 830 H/s 190W

Возможен ли майнинг на одной видеокарте?

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

Какие криптовалюты можно майнить на видеокартах

Майнить на GPU можно любую криптовалюту, но следует понимать, что производительность на разных будет отличаться на одной и той же карточке. Более старые алгоритмы уже плохо подходят для видеопроцессоров и не принесут никакой прибыли. Происходит это из-за появления на рынке новых устройств - так называемых . Они являются куда более производительными и значительно повышают сложность сети, однако их стоимость высока и исчисляется тысячами долларов. Поэтому добыча монет на SHA-256 (Биткоин) или Scrypt (Litecoin, Dogecoin) в домашних условиях - это плохая идея в 2018-ом году.

Кроме LTC и DOGE, ASICи сделали невозможной добычу Bitcoin (BTC), Dash и других валют. Куда лучшим выбором станут криптовалюты, которые используют защищенные от ASIC-ов алгоритмы. Так, например, с помощью GPU получится добывать монеты на алгоритмах CryptoNight (Карбованец, Монеро, Electroneum, Bytecoin), Equihash (ZCash, Hush, Bitcoin Gold) и Ethash (Ethereum, Ethereum Classic). Список далеко не полный и постоянно появляются новые проекты на этих алгоритмах. Среди них встречаются как форки более популярных монет, так и совершенно новые разработки. Изредка даже появляются новые алгоритмы, которые предназначены для решения определённых задач и могут использовать различное оборудование. Ниже будет рассказано о том, как узнать хешрейт видеокарты.

Что нужно для майнинга на видеокарте

Ниже приведён список того, что вам понадобится для создания фермы:

  • Сами видеокарты. Выбор конкретных моделей зависит от вашего бюджета или того, что уже имеется в наличии. Конечно, старые устройства на AGP не подойдут, но можно использовать любую карту среднего или топового класса последних годов. Выше вы можете вернуться к таблице производительности видеокарт, которая позволит сделать подходящий выбор.
  • Компьютер для их установки. Не обязательно использовать топовое железо и делать ферму на базе высокопроизводительных комплектующих. Достаточно будет какого-нибудь старого AMD Athlon, нескольких гигабайт оперативной памяти и жесткого диска для установки операционной системы и нужных программ. Важна также материнская плата. Она должна иметь достаточное для вашей фермы количество PCI слотов. Существуют специальные версии для майнеров, которые содержат 6-8 слотов и в определённых случаях выгодней использовать их, чем собирать несколько ПК. Особое внимание стоит уделять лишь блоку питания, ведь система будет работать под высокой нагрузкой круглые сутки. Брать БП нужно обязательно с запасом мощности и желательно наличие сертификатов 80 Plus. Возможно также соединение двух блоков в один с помощью специальных переходников, но такое решение вызывает в интернете споры. Корпус лучше не использовать вовсе. Для лучшего охлаждения рекомендуется сделать или купить специальный стенд. Видеокарты в таком случае выносятся с помощью специальных переходников, которые называются райзеры. Приобрести их можно в профильных магазинах или на алиэкспрессе.
  • Хорошо проветриваемое сухое помещение. Размещать ферму стоит в нежилой комнате, а лучше вообще в отдельном помещении. Это позволит избавиться от дискомфорта, который возникает из-за шумной работы систем охлаждения и теплоотдачи. Если такой возможности нет, то следует выбирать видеокарты с максимально тихой системой охлаждения. Узнать о ней подробней вы сможете из обзоров в интернете, например, на YouTube. Следует также подумать о циркуляции воздуха и вентилируемости, чтобы максимально снизить температуру.
  • Программа майнер. GPU майнинг происходит с помощью специального , которое может быть найдено в интернете. Для производителей ATI Radeon и Nvidia используется разный софт. Это же касается и разных алгоритмов.
  • Обслуживание оборудования. Это очень важный пункт, так как не все понимают, что майнинг ферма требует постоянного ухода. Пользователю нужно следить за температурой, менять термопасту и очищать СО от пыли. Следует также помнить о технике безопасности и регулярно проверять исправность системы.

Как настроить майнинг на видеокарте с нуля

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

Как выбрать видеокарту для майнинга

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

Выбираем криптовалюту

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

Выбираем пул для майнинга

Также имеют некоторые отличия. Некоторые из них требуют регистрации, а некоторым достаточно лишь адреса вашего кошелька для начала работы. Первые обычно хранят заработанные вами средства до достижения минимальной для выплаты суммы, либо в ожидании вывода вами денег в ручном режиме. Хорошим примером такого пула является Suprnova.cc. Там предлагается множество криптовалют и для работы в каждом из пулов достаточно лишь раз зарегистрироваться на сайте. Сервис прост в настройке и хорошо подойдёт новичкам.

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

Создаем криптовалютный кошелек

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

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

Выбираем и устанавливаем программу для майнинга

Выбор программы для добычи крипты зависит от выбранной монеты и её алгоритма. Наверное, все разработчики такого ПО имеют темы на BitcoinTalks, где можно найти ссылки на скачивание и информацию о том, как происходят настройка и запуск. Почти все эти программы имеют версии как для Виндовс, так и для Линукс. Большинство таких майнеров бесплатные, но некоторый процент времени они используют для подключения к пулу разработчика. Это своего рода комиссия за использование программного обеспечения. В некоторых случаях её можно отключить, но это приводит к ограничениям функционала.

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

Если вы не знаете, какое ПО выбрать, посмотрите наш материал, посвященный либо изучите инструкции на сайте пула. Обычно там всегда есть раздел, который посвящён началу работы. Он содержит перечень программ, которые можно использовать и конфигурации для .bat файлов. С его помощью можно быстро разобраться с настройкой и начать майнинг на дискретной видеокарте. Можно сразу создать батники для всех валют, с которыми вы хотите работать, чтобы в дальнейшем было удобнее переключаться между ними.

Запускаем майнинг и следим за статистикой

После запуска .bat файла с настройками вы увидите консольное окно, куда будет выводиться лог происходящего. Его также можно будет найти в папке с запускаемым файлом. В консоли вы можете ознакомиться с текущими показателем хешрейта и температурой карты. Вызывать актуальные данные обычно позволяют горячие клавиши.

Вы также сможете увидеть, если устройство не находит хэши. В таком случае будет выведено предупреждение. Случается это, когда что-то настроено неправильно, выбрано неподходящее для монеты программное обеспечение или ГПУ не функционирует должным образом. Многие майнеры также используют средства для удалённого доступа к ПК, чтобы следить за работой фермы, когда они находятся не там, где она установлена.

Выводим криптовалюту

Если вы используете пулы вроде Suprnova, то все средства просто накапливаются на вашем аккаунте и вы можете вывести их в любой момент. Остальные пулы чаще всего используют систему, когда средства начисляются автоматически на указанный кошелёк после получения минимальной суммы вывода. Узнать о том, сколько вы заработали, обычно можно на сайте пула. Требуется лишь указать адрес вашего кошелька или залогиниться в личный кабинет.

Сколько можно заработать?

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

Окупаемость видеокарт

Подсчитать окупаемость поможет специальный онлайн калькулятор. В интернете их много, но мы рассмотрим этот процесс на примере сервиса WhatToMine . Он позволяет получать данные о текущем профите, основываясь на данных вашей фермы. Нужно только выбрать видеокарты, которые есть у вас в наличии, а потом добавить стоимость электроэнергии в вашем регионе. Сайт посчитает сколько вы можете заработать за сутки.

Следует понимать, что учитывается лишь текущее положение дел на рынке и ситуация может измениться в любой момент. Курс может упасть или подняться, сложность майнинга станет другой или появятся новые проекты. Так, например, может прекратиться добыча эфира в связи с возможным переходом сети на . Если прекратиться майнинг эфириума, то фермам нужно будет куда то направить свободные мощности, например, в майнинг ZCash на GPU, что повлияет на курс этой монеты. Подобных сценариев на рынке множество и важно понимать, что сегодняшняя картина может не сохраниться на протяжении всего срока окупаемости оборудования.

Как-то раз довелось мне побеседовать на компьютерном рынке с техническим директором одной из многочисленных компаний, занимающихся продажами ноутбуков. Этот «специалист» пытался с пеной у рта объяснить, какая именно конфигурация ноутбука мне нужна. Главный посыл его монолога заключался в том, что время центральных процессоров (CPU) закончилось, и сейчас все приложения активно используют вычисления на графическом процессоре (GPU), а потому производительность ноутбука целиком и полностью зависит от графического процессора, а на CPU можно не обращать никакого внимания. Поняв, что спорить и пытаться вразумить этого технического директора абсолютно бессмысленно, я не стал терять времени зря и купил нужный мне ноутбук в другом павильоне. Однако сам факт такой вопиющей некомпетентности продавца меня поразил. Было бы понятно, если бы он пытался обмануть меня, как покупателя. Отнюдь. Он искренне верил в то, что говорил. Да, видимо, маркетологи в NVIDIA и AMD не зря едят свой хлеб, и им-таки удалось внушить некоторым пользователям идею о доминирующей роли графического процессора в современном компьютере.

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

Вообще, вычисления на GPU главным образом выполняются на специализированных HPC-системах для научных расчетов. А вот пользовательские приложения, в которых применяются вычисления на GPU, можно пересчитать по пальцам. При этом следует сразу же оговориться, что термин «вычисления на GPU» в данном случае не вполне корректен и может ввести в заблуждение. Дело в том, что если приложение использует вычисление на GPU, то это вовсе не означает, что центральный процессор бездействует. Вычисление на GPU не предполагает переноса нагрузки с центрального процессора на графический. Как правило, центральный процессор при этом остается загруженным, а использование графического процессора, наряду с центральным, позволяет повысить производительность, то есть сократить время выполнения задачи. Причем сам GPU здесь выступает в роли своеобразного сопроцессора для CPU, но ни в коем случае не заменяет его полностью.

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

Различия в архитектурах GPU и CPU

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

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

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

Графические и центральные процессоры различаются и по принципам доступа к памяти. В GPU доступ к памяти легко предсказуем: если из памяти читается тексель текстуры, то через некоторое время придет срок и для соседних текселей. При записи происходит то же самое: если какой­то пиксел записывается во фрейм­буфер, то через несколько тактов будет записываться пиксел, расположенный рядом с ним. Поэтому GPU, в отличие от CPU, просто не нужна кэш­память большого размера, а для текстур требуются лишь несколько килобайт. Различен и принцип работы с памятью у GPU и CPU. Так, все современные GPU имеют несколько контроллеров памяти, да и сама графическая память более быстрая, поэтому графические процессоры имеют гораздо бо льшую пропускную способность памяти, по сравнению с универсальными процессорами, что также весьма важно для параллельных расчетов, оперирующих огромными потоками данных.

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

Сами же исполнительные блоки занимают в универсальном процессоре относительно немного места.

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

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

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

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

Итак, если алгоритм решения задачи может быть распараллелен на тысячи отдельных потоков, то эффективность решения такой задачи с применением GPU может быть выше, чем ее решение средствами только процессора общего назначения. Однако нельзя так просто взять и перенести решение какой­то задачи с CPU на GPU, хотя бы просто потому, что CPU и GPU используют разные команды. То есть когда программа пишется под решение на CPU, то применяется набор команд х86 (или набор команд, совместимый с конкретной архитектурой процессора), а вот для графического процессора используются уже совсем другие наборы команд, которые опять-таки учитывают его архитектуру и возможности. При разработке современных 3D-игр применяются API DirectX и OрenGL, позволяющие программистам работать с шейдерами и текстурами. Однако использование API DirectX и OрenGL для неграфических вычислений на графическом процессоре - это не лучший вариант.

NVIDIA CUDA и AMD APP

Именно поэтому, когда стали предприниматься первые попытки реализовать неграфические вычисления на GPU (General Purpose GPU, GPGPU), возник компилятор BrookGPU. До его создания разработчикам приходилось получать доступ к ресурсам видеокарты через графические API OpenGL или Direct3D, что значительно усложняло процесс программирования, так как требовало специфических знаний - приходилось изучать принципы работы с 3D-объектами (шейдерами, текстурами и т.п.). Это явилось причиной весьма ограниченного применения GPGPU в программных продуктах. BrookGPU стал своеобразным «переводчиком». Эти потоковые расширения к языку Си скрывали от программистов трехмерный API и при его использовании надобность в знаниях 3D-программирования практически отпала. Вычислительные мощности видеокарт стали доступны программистам в виде дополнительного сопроцессора для параллельных расчетов. Компилятор BrookGPU обрабатывал файл с кодом Cи и расширениями, выстраивая код, привязанный к библиотеке с поддержкой DirectX или OpenGL.

Во многом благодаря BrookGPU, компании NVIDIA и ATI (ныне AMD) обратили внимание на зарождающуюся технологию вычислений общего назначения на графических процессорах и начали разработку собственных реализаций, обеспечивающих прямой и более прозрачный доступ к вычислительным блокам 3D-ускорителей.

В результате компания NVIDIA разработала программно-аппаратную архитектуру параллельных вычислений CUDA (Compute Unified Device Architecture). Архитектура CUDA позволяет реализовать неграфические вычисления на графических процессорах NVIDIA.

Релиз публичной бета-версии CUDA SDK состоялся в феврале 2007 года. В основе API CUDA лежит упрощенный диалект языка Си. Архитектура CUDA SDK обеспечивает программистам реализацию алгоритмов, выполнимых на графических процессорах NVIDIA, и включение специальных функций в текст программы на Cи. Для успешной трансляции кода на этом языке в состав CUDA SDK входит собственный Си­компилятор командной строки nvcc компании NVIDIA.

CUDA - это кроссплатформенное программное обеспечение для таких операционных систем, как Linux, Mac OS X и Windows.

Компания AMD (ATI) также разработала свою версию технологии GPGPU, которая ранее называлась AТI Stream, а теперь - AMD Accelerated Parallel Processing (APP). Основу AMD APP составляет открытый индустриальный стандарт OpenCL (Open Computing Language). Стандарт OpenCL обеспечивает параллелизм на уровне инструкций и на уровне данных и является реализацией техники GPGPU. Это полностью открытый стандарт, его использование не облагается лицензионными отчислениями. Отметим, что AMD APP и NVIDIA CUDA несовместимы друг с другом, тем не менее, последняя версия NVIDIA CUDA поддерживает и OpenCL.

Тестирование GPGPU в видеоконвертерах

Итак, мы выяснили, что для реализации GPGPU на графических процессорах NVIDIA предназначена технология CUDA, а на графических процессорах AMD - API APP. Как уже отмечалось, использование неграфических вычислений на GPU целесообразно только в том случае, если решаемая задача может быть распараллелена на множество потоков. Однако большинство пользовательских приложений не удовлетворяют этому критерию. Впрочем, есть и некоторые исключения. К примеру, большинство современных видеоконвертеров поддерживают возможность использования вычислений на графических процессорах NVIDIA и AMD.

Для того чтобы выяснить, насколько эффективно используются вычисления на GPU в пользовательских видеоконвертерах, мы отобрали три популярных решения: Xilisoft Video Converter Ultimate 7.7.2, Wondershare Video Converter Ultimate 6.0.3.2 и Movavi Video Converter 10.2.1. Эти конвертеры поддерживают возможность использования графических процессоров NVIDIA и AMD, причем в настройках видеоконвертеров можно отключить эту возможность, что позволяет оценить эффективность применения GPU.

Для видеоконвертирования мы применяли три различных видеоролика.

Первый видеоролик имел длительность 3 мин 35 с и размер 1,05 Гбайт. Он был записан в формате хранения данных (контейнер) mkv и имел следующие характеристики:

  • видео:
    • формат - MPEG4 Video (H264),
    • разрешение - 1920*um*1080,
    • режим битрейта - Variable,
    • средний видеобитрейт - 42,1 Мбит/с,
    • максимальный видеобитрейт - 59,1 Мбит/с,
    • частота кадров - 25 fps;
  • аудио:
    • формат - MPEG-1 Audio,
    • аудиобитрейт - 128 Кбит/с,
    • количество каналов - 2,

Второй видеоролик имел длительность 4 мин 25 с и размер 1,98 Гбайт. Он был записан в формате хранения данных (контейнер) MPG и имел следующие характеристики:

  • видео:
    • формат - MPEG-PS (MPEG2 Video),
    • разрешение - 1920*um*1080,
    • режим битрейта - Variable.
    • средний видеобитрейт - 62,5 Мбит/с,
    • максимальный видеобитрейт - 100 Мбит/с,
    • частота кадров - 25 fps;
  • аудио:
    • формат - MPEG-1 Audio,
    • аудиобитрейт - 384 Кбит/с,
    • количество каналов - 2,

Третий видеоролик имел длительность 3 мин 47 с и размер 197 Мбайт. Он был записан в формате хранения данных (контейнер) MOV и имел следующие характеристики:

  • видео:
    • формат - MPEG4 Video (H264),
    • разрешение - 1920*um*1080,
    • режим битрейта - Variable,
    • видеобитрейт - 7024 Кбит/с,
    • частота кадров - 25 fps;
  • аудио:
    • формат - AAC,
    • аудиобитрейт - 256 Кбит/с,
    • количество каналов - 2,
    • частота семплирования - 48 кГц.

Все три тестовых видеоролика конвертировались с использованием видеоконвертеров в формат хранения данных MP4 (кодек H.264) для просмотра на планшете iPad 2. Разрешение выходного видеофайла составляло 1280*um*720.

Отметим, что мы не стали использовать абсолютно одинаковые настройки конвертирования во всех трех конвертерах. Именно поэтому по времени конвертирования некорректно сравнивать эффективность самих видеоконвертеров. Так, в видеоконвертере Xilisoft Video Converter Ultimate 7.7.2 для конвертирования применялся пресет iPad 2 - H.264 HD Video. В этом пресете используются следующие настройки кодирования:

  • кодек - MPEG4 (H.264);
  • разрешение - 1280*um*720;
  • частота кадров - 29,97 fps;
  • видеобитрейт - 5210 Кбит/с;
  • аудиокодек - AAC;
  • аудиобитрейт - 128 Кбит/с;
  • количество каналов - 2;
  • частота семплирования - 48 кГц.

В видеоконвертере Wondershare Video Converter Ultimate 6.0.3.2 использовался пресет iPad 2 cо следующими дополнительными настройками:

  • кодек - MPEG4 (H.264);
  • разрешение - 1280*um*720;
  • частота кадров - 30 fps;
  • видеобитрейт - 5000 Кбит/с;
  • аудиокодек - AAC;
  • аудиобитрейт - 128 Кбит/с;
  • количество каналов - 2;
  • частота семплирования - 48 кГц.

В конвертере Movavi Video Converter 10.2.1 применялся пресет iPad (1280*um*720, H.264) (*.mp4) со следующими дополнительными настройками:

  • видеоформат - H.264;
  • разрешение - 1280*um*720;
  • частота кадров - 30 fps;
  • видеобитрейт - 2500 Кбит/с;
  • аудиокодек - AAC;
  • аудиобитрейт - 128 Кбит/с;
  • количество каналов - 2;
  • частота семплирования - 44,1 кГц.

Конвертирование каждого исходного видеоролика проводилось по пять раз на каждом из видеоконвертеров, причем с использованием как графического процессора, так и только CPU. После каждого конвертирования компьютер перезагружался.

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

Конфигурация стенда для тестирования

Стенд для тестирования имел следующую конфигурацию:

  • процессор - Intel Core i7-3770K;
  • материнская плата - Gigabyte GA-Z77X-UD5H;
  • чипсет системной платы - Intel Z77 Express;
  • память - DDR3-1600;
  • объем памяти - 8 Гбайт (два модуля GEIL по 4 Гбайт);
  • режим работы памяти - двухканальный;
  • видеокарта - NVIDIA GeForce GTX 660Ti (видеодрайвер 314.07);
  • накопитель - Intel SSD 520 (240 Гбайт).

На стенде устанавливалась операционная система Windows 7 Ultimate (64-bit).

Первоначально мы провели тестирование в штатном режиме работы процессора и всех остальных компонентов системы. При этом процессор Intel Core i7-3770K работал на штатной частоте 3,5 ГГц c активированным режимом Turbo Boost (максимальная частота процессора в режиме Turbo Boost составляет 3,9 ГГц).

Затем мы повторили процесс тестирования, но при разгоне процессора до фиксированной частоты 4,5 ГГц (без использования режима Turbo Boost). Это позволило выявить зависимость скорости конвертирования от частоты процессора (CPU).

На следующем этапе тестирования мы вернулись к штатным настройкам процессора и повторили тестирование уже с другими видеокартами:

  • NVIDIA GeForce GTX 280 (драйвер 314.07);
  • NVIDIA GeForce GTX 460 (драйвер 314.07);
  • AMD Radeon HD6850 (драйвер 13.1).

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

Старшая видеокарта NVIDIA GeForce 660Ti основана на одноименном графическом процессоре с кодовым обозначением GK104 (архитектура Kepler), производимом по 28-нм техпроцессу. Этот графический процессор содержит 3,54 млрд транзисторов, а площадь кристалла составляет 294 мм2.

Напомним, что графический процессор GK104 включает четыре кластера графической обработки (Graphics Processing Clusters, GPC). Кластеры GPC являются независимыми устройствами в составе процессора и способны работать как отдельные устройства, поскольку обладают всеми необходимыми ресурсами: растеризаторами, геометрическими движками и текстурными модулями.

Каждый такой кластер имеет два потоковых мультипроцессора SMX (Streaming Multiprocessor), но в процессоре GK104 в одном из кластеров один мультипроцессор заблокирован, поэтому всего имеется семь мультипроцессоров SMX.

Каждый потоковый мультипроцессор SMX содержит 192 потоковых вычислительных ядра (ядра CUDA), поэтому в совокупности процессор GK104 насчитывает 1344 вычислительных ядра CUDA. Кроме того, каждый SMX-мультипроцессор содержит 16 текстурных модулей (TMU), 32 блока специальных функций (Special Function Units, SFU), 32 блока загрузки и хранения (Load-Store Unit, LSU), движок PolyMorph и многое другое.

Видеокарта GeForce GTX 460 основана на графическом процессоре с кодовым обозначением GF104 на базе архитектуры Fermi. Этот процессор производится по 40-нм техпроцессу и содержит порядка 1,95 млрд транзисторов.

Графический процессор GF104 включает два кластера графической обработки GPC. Каждый из них имеет четыре потоковых мультипроцессора SM, но в процессоре GF104 в одном из кластеров один мультипроцессор заблокирован, поэтому существует всего семь мультипроцессоров SM.

Каждый потоковый мультипроцессор SM содержит 48 потоковых вычислительных ядра (ядра CUDA), поэтому в совокупности процессор GK104 насчитывает 336 вычислительных ядра CUDA. Кроме того, каждый SM-мультипроцессор содержит восемь текстурных модулей (TMU), восемь блоков специальных функций (Special Function Units, SFU), 16 блоков загрузки и хранения (Load-Store Unit, LSU), движок PolyMorph и многое другое.

Графический процессор GeForce GTX 280 относится ко второму поколению унифицированной архитектуры графических процессоров NVIDIA и по своей архитектуре сильно отличается от архитектуры Fermi и Kepler.

Графический процессор GeForce GTX 280 состоит из кластеров обработки текстур (Texture Processing Clusters, TPC), которые, хоть и похожи, но в то же время сильно отличаются от кластеров графической обработки GPC в архитектурах Fermi и Kepler. Всего таких кластеров в процессоре GeForce GTX 280 насчитывается десять. Каждый TPC-кластер включает три потоковых мультипроцессора SM и восемь блоков текстурной выборки и фильтрации (TMU). Каждый мультипроцессор состоит из восьми потоковых процессоров (SP). Мультипроцессоры также содержат блоки выборки и фильтрации текстурных данных, используемых как в графических, так и в некоторых расчетных задачах.

Таким образом, в одном TPC-кластере - 24 потоковых процессора, а в графическом процессоре GeForce GTX 280 их уже 240.

Сводные характеристики используемых в тестировании видеокарт на графических процессорах NVIDIA представлены в таблице .

В приведенной таблице нет видеокарты AMD Radeon HD6850, что вполне естественно, поскольку по техническим характеристикам ее трудно сравнивать с видеокартами NVIDIA. А потому рассмотрим ее отдельно.

Графический процессор AMD Radeon HD6850, имеющий кодовое наименование Barts, изготовляется по 40-нм техпроцессу и содержит 1,7 млрд транзисторов.

Архитектура процессора AMD Radeon HD6850 представляет собой унифицированную архитектуру с массивом общих процессоров для потоковой обработки многочисленных видов данных.

Процессор AMD Radeon HD6850 состоит из 12 SIMD-ядер, каждое из которых содержит по 16 блоков суперскалярных потоковых процессоров и четыре текстурных блока. Каждый суперскалярный потоковый процессор содержит пять универсальных потоковых процессоров. Таким образом, всего в графическом процессоре AMD Radeon HD6850 насчитывается 12*um*16*um*5=960 универсальных потоковых процессоров.

Частота графического процессора видеокарты AMD Radeon HD6850 составляет 775 МГц, а эффективная частота памяти GDDR5 - 4000 МГц. При этом объем памяти составляет 1024 Мбайт.

Результаты тестирования

Итак, давайте обратимся к результатам тестирования. Начнем с первого теста, когда используется видеокарта NVIDIA GeForce GTX 660Ti и штатный режим работы процессора Intel Core i7-3770K.

На рис. 1-3 показаны результаты конвертирования трех тестовых видеороликов тремя конвертерами в режимах с применением графического процессора и без.

Как видно по результатам тестирования, эффект от использования графического процессора налицо. Для видеоконвертера Xilisoft Video Converter Ultimate 7.7.2 в случае применения графического процессора время конвертирования сокращается на 14, 9 и 19% для первого, второго и третьего видеоролика соответственно.

Для видеоконвертера Wondershare Video Converter Ultimate 6.0.32 использование графического процессора позволяет сократить время конвертирования на 10, 13 и 23% для первого, второго и третьего видеоролика соответственно.

Но более всех от применения графического процессора выигрывает конвертер Movavi Video Converter 10.2.1. Для первого, второго и третьего видеоролика сокращение времени конвертирования составляет 64, 81 и 41% соответственно.

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

Теперь посмотрим, каков будет выигрыш по времени конвертирования при разгоне процессора Intel Core i7-3770K до частоты 4,5 ГГц. Если считать, что в штатном режиме все ядра процессора при конвертировании загружены и в режиме Turbo Boost работают на частоте 3,7 ГГц, то увеличение частоты до 4,5 ГГц соответствует разгону по частоте на 22%.

На рис. 4-6 показаны результаты конвертирования трех тестовых видеороликов при разгоне процессора в режимах с использованием графического процессора и без. В данном случае применение графического процессора позволяет получить выигрыш по времени конвертирования.

Для видеоконвертера Xilisoft Video Converter Ultimate 7.7.2 в случае применения графического процессора время конвертирования сокращается на 15, 9 и 20% для первого, второго и третьего видеоролика соответственно.

Для видеоконвертера Wondershare Video Converter Ultimate 6.0.32 использование графического процессора позволяет сократить время конвертирования на 10, 10 и 20% для первого, второго и третьего видеоролика соответственно.

Для конвертера Movavi Video Converter 10.2.1 применение графического процессора позволяет сократить время конвертирования на 59, 81 и 40% соответственно.

Естественно, интересно посмотреть, как разгон процессора позволяет уменьшить время конвертирования при использовании графического процессора и без него.

На рис. 7-9 представлены результаты сравнения времени конвертирования видеороликов без использования графического процессора в штатном режиме работы процессора и в режиме разгона. Поскольку в данном случае конвертирование проводится только средствами CPU без вычислений на GPU, очевидно, что увеличение тактовой частоты работы процессора приводит к сокращению времени конвертирования (увеличению скорости конвертирования). Столь же очевидно, что сокращение скорости конвертирования должно быть примерно одинаково для всех тестовых видеороликов. Так, для видеоконвертера Xilisoft Video Converter Ultimate 7.7.2 при разгоне процессора время конвертирования сокращается на 9, 11 и 9% для первого, второго и третьего видеоролика соответственно. Для видеоконвертера Wondershare Video Converter Ultimate 6.0.32 время конвертирования сокращается на 9, 9 и 10% для первого, второго и третьего видеоролика соответственно. Ну а для видеоконвертера Movavi Video Converter 10.2.1 время конвертирования сокращается на 13, 12 и 12% соответственно.

Таким образом, при разгоне процессора по частоте на 20% время конвертирования сокращается примерно на 10%.

Сравним время конвертирования видеороликов с использованием графического процессора в штатном режиме работы процессора и в режиме разгона (рис. 10-12).

Для видеоконвертера Xilisoft Video Converter Ultimate 7.7.2 при разгоне процессора время конвертирования сокращается на 10, 10 и 9% для первого, второго и третьего видеоролика соответственно. Для видеоконвертера Wondershare Video Converter Ultimate 6.0.32 время конвертирования сокращается на 9, 6 и 5% для первого, второго и третьего видеоролика соответственно. Ну а для видеоконвертера Movavi Video Converter 10.2.1 время конвертирования сокращается на 0,2, 10 и 10% соответственно.

Как видим, для конвертеров Xilisoft Video Converter Ultimate 7.7.2 и Wondershare Video Converter Ultimate 6.0.32 сокращение времени конвертирования при разгоне процессора примерно одинаково как при использовании графического процессора, так и без его применения, что логично, поскольку эти конвертеры не очень эффективно используют вычисления на GPU. А вот для конвертера Movavi Video Converter 10.2.1, который эффективно использует вычисления на GPU, разгон процессора в режиме использования вычислений на GPU мало сказывается на сокращении времени конвертирования, что также понятно, поскольку в данном случае основная нагрузка ложится на графический процессор.

Теперь посмотрим результаты тестирования с различными видеокартами.

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

Что касается видеокарт на графических процессорах NVIDIA, то ситуация следующая. При использовании конвертеров Xilisoft Video Converter Ultimate 7.7.2 и Wondershare Video Converter Ultimate 6.0.32 время конвертирования практически никак не зависит от типа используемой видеокарты. То есть для видеокарт NVIDIA GeForce GTX 660Ti, NVIDIA GeForce GTX 460 и NVIDIA GeForce GTX 280 в режиме использования вычислений на GPU время конвертирования получается одно и то же (рис. 13-15).

Рис. 1. Результаты конвертирования первого
тестового видеоролика в штатном режиме
работы процессора

процессора видеокартах в режиме использования графического процессора

Рис. 14. Результаты сравнения времени конвертирования второго видеоролика

Рис. 15. Результаты сравнения времени конвертирования третьего видеоролика
на различных видеокартах в режиме использования графического процессора

Объяснить это можно лишь тем, что алгоритм вычислений на графическом процессоре, реализованный в конвертерах Xilisoft Video Converter Ultimate 7.7.2 и Wondershare Video Converter Ultimate 6.0.32, просто неэффективен и не позволяет активно задействовать все графические ядра. Кстати, именно этим объясняется и тот факт, что для этих конвертеров разница по времени конвертирования в режимах использования GPU и без использования невелика.

В конвертере Movavi Video Converter 10.2.1 ситуация несколько иная. Как мы помним, этот конвертер способен очень эффективно использовать вычисления на GPU, а поэтому в режиме использования GPU время конвертирования зависит от типа используемой видеокарты.

А вот с видеокартой AMD Radeon HD 6850 всё как обычно. То ли драйвер видеокарты «кривой», то ли алгоритмы, реализованные в конвертерах, нуждаются в серьезной доработке, но в случае применения вычислений на GPU результаты либо не улучшаются, либо ухудшаются.

Если говорить более конкретно, то ситуация следующая. Для конвертера Xilisoft Video Converter Ultimate 7.7.2 при использовании графического процессора для конвертирования первого тестового видеоролика время конвертирования увеличивается на 43%, при конвертировании второго ролика - на 66%.

Причем, конвертер Xilisoft Video Converter Ultimate 7.7.2 характеризуется еще и нестабильностью результатов. Разброс по времени конвертирования может достигать 40%! Именно поэтому мы повторяли все тесты по десять раз и рассчитывали средний результат.

А вот для конвертеров Wondershare Video Converter Ultimate 6.0.32 и Movavi Video Converter 10.2.1 при использовании графического процессора для конвертирования всех трех видеороликов время конвертирования не изменяется вообще! Вероятно, что конвертеры Wondershare Video Converter Ultimate 6.0.32 и Movavi Video Converter 10.2.1 либо не используют технологию AMD APP при конвертировании, либо видеодрайвер AMD попросту «кривой», в результате чего технология AMD APP не работает.

Выводы

На основании проведенного тестирования можно сделать следующие важные выводы. В современных видеоконвертерах действительно может применяться технология вычислений на GPU, что позволяет повысить скорость конвертирования. Однако это вовсе не означает, что все вычисления целиком переносятся на GPU и CPU остается незадействованным. Как показывает тестирование, при использовании технологии GPGPU центральный процессор остается загруженным, а значит, применение мощных, многоядерных центральных процессоров в системах, используемых для конвертирования видео, остается актуальным. Исключением из этого правила является технология AMD APP на графических процессорах AMD. Например, при использовании конвертера Xilisoft Video Converter Ultimate 7.7.2 с активированной технологией AMD APP нагрузка на CPU действительно снижается, но это приводит к тому, что время конвертирования не сокращается, а, наоборот, увеличивается.

Вообще, если говорить о конвертировании видео с дополнительным использованием графического процессора, то для решения этой задачи целесообразно применять видеокарты с графическими процессорами NVIDIA. Как показывает практика, только в этом случае можно добиться увеличения скорости конвертирования. Причем нужно помнить, что реальный прирост в скорости конвертирования зависит от очень многих факторов. Это входной и выходной форматы видео, и, конечно же, сам видеоконвертер. Конвертеры Xilisoft Video Converter Ultimate 7.7.2 и Wondershare Video Converter Ultimate 6.0.32 для этой задачи подходят плохо, а вот конвертер и Movavi Video Converter 10.2.1 способен очень эффективно использовать возможности NVIDIA GPU.

Что же касается видеокарт на графических процессорах AMD, то для задач видеоконвертирования их не стоит применять вообще. В лучшем случае никакого прироста в скорости конвертирования это не даст, а в худшем - можно получить ее снижение.



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: