Введение
С точки зрения платформы .NET вплоть до недавно выпущенной 4-й версии фактически не было средств, облегчающих параллельную обработку данных. Однако ещё 4 июля 2008 года увидела свет версия 1.1 alpha библиотеки CUDA.NET. Она работала только под Windows XP, и поддерживала CUDA версии 1.1. С тех пор проект довольно динамично развивался, и на данный момент актуальной является релиз 3.0.0 — кроссплатформенный (в Linux и Mac OS использующий Mono), совместимый с CUDA версии 3.0, вышел он 17 июня 2010 года. Этого пакета вполне достаточно для изучения CUDA и создания каких-либо приложений на её основе: примером может служить программа для конвертации музыки в формат FLAC — FlaCuda. Фактически, CUDA.NET представляет собой объектно-ориентированную обёртку для использования API, предоставляемых драйвером CUDA.
Давайте попробуем написать простую программу, взаимодействующую с CUDA API. Качаем архив с библиотекой, внутри есть документация в виде CHM-файла и собственно сама сборка CUDA.NET.dll. Напишем небольшую консольную утилиту, отображающую сведения о CUDA-совместимых устройствах.
Чтобы начать, создадим в Visual Studio новый С#-проект — консольное приложение и сошлёмся на сборку CUDA.NET.
Основная точка взаимодействия с API драйвера CUDA — это класс GASS.CUDA.CUDA. Создадим объект этого класса:
CUDA cuda = new CUDA( true );
Параметр true конструктора позволяет инициализировать драйвер, «включая» механизмы CUDA. В общем-то дальше всё довольно просто:
Console.WriteLine();
Console.WriteLine( "Список CUDA-оборудования:" );
Console.WriteLine();
var devices = cuda.Devices;
Console.WriteLine( "Количество устройств: " + devices.Count() );
Console.WriteLine();
foreach ( var dev in devices )
{
Console.WriteLine( "Название чипа видеоадаптера: " + dev.Name );
Console.WriteLine( "Объём доступной видеопамяти: {0}Кб", dev.TotalMemory / 1024 );
Console.WriteLine( "CUDA Compute Capability: " + dev.ComputeCapability );
Console.WriteLine();
Console.WriteLine( "Расширенные свойства:" );
var props = dev.Properties;
Console.WriteLine( "\tЧастота работы шейдерного домена: {0}МГц", props.ClockRate / 1000 );
Console.WriteLine( "\tМаксимальное число нитей в блоке: " + props.MaxThreadsPerBlock );
Console.WriteLine( "\tРегистров в мультипроцессоре: {0} шт.", props.RegistersPerBlock );
Console.WriteLine( "\tОбъём общей памяти в мультипроцессоре: {0} байт(а)", props.SharedMemoryPerBlock );
Console.WriteLine( "\tРазмер варпа: " + props.SIMDWidth );
Console.WriteLine();
Console.WriteLine( "Нажмите ENTER..." );
Console.ReadLine();
}
}
catch ( CUDAException ex )
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( "CUDAException" );
Console.WriteLine( ex.Message );
}
Наверняка многим знакомы утилиты CPU-Z и GPU-Z, отображающие информацию о CPU и GPU соответственно. Имеется и open-source проект CUDA-Z — это программа, выводящая описание CUDA-«железа», доступного в данный момент. Она содержит любопытный встроенный бенчмарк, позволяющий оценить производительность видеокарты.
Итог
Итак, мы рассмотрели подход компании NVidia к выполнению вычислений общего назначения на графических адаптерах — технологию CUDA. По моим личным ощущениям потенциал у технологии весьма хороший — дешевые потоковые процессоры таят в себе такие вычислительные мощности, которые несравненно больше предоставляемых любым современным CPU. С другой стороны, чтобы их утилизировать, нужно изначально адаптировать алгоритм к выполнению на GPGPU — большое количество задач в эти рамки не укладывается. Просто мало где требуется столь громадные объёмы вычислений, чтобы загрузить «под завязку» все SP. Накладные расходы, связанные с копированием данных из хоста в устройство и обратно, и др. при малых объёмах данных могут нивелировать преимущества от внедрения CUDA. Однако, по-моему стоит «держать руку на пульсе» и следить за развитием событий!
Существование CUDA.NET существенно упрощает жизнь .NET-разработчику, который решил применить CUDA в своём проекте — не нужно вручную оборачивать native библиотеки, всё уже готово. Ну а вместе с Parallel Nsight отладка и тестирование CUDA-функций становятся ещё проще.
И ещё, не думаю, что правильно противопоставлять CPU и GPGPU — это разные классы устройств. Стоит скорее рассматривать GPGPU как очень мощный «сопроцессор», буквально машину для выполнения тяжелых вычислений — и использовать оба этих устройства по назначению.
Спасибо за внимание, успехов в разработке!