Подтвердить что ты не робот

Программирование на GPU высокого уровня в С++

Я изучал библиотеки/расширения для С++, что позволит обрабатывать GPU на высоком уровне. Я не специалист по программированию на GPU, и я не хочу копать слишком глубоко. У меня есть нейронная сеть, состоящая из классов с виртуальными функциями. Мне нужна библиотека, которая в основном выделяет мне GPU - на высоком уровне. Есть парень, который написал диссертацию на систему под названием GPU ++, которая делает для вас большую часть материала GPU. Я не могу найти код нигде, просто его тезис.

Кто-нибудь знает о подобной библиотеке, или у кого-нибудь есть код для GPU ++? Библиотеки, подобные CUDA, слишком низки и не могут обрабатывать большинство моих операций (по крайней мере, не переписывая все мои процессы и алгоритмы, которые я не хочу делать).

4b9b3361

Ответ 1

Библиотека Thrust предоставляет контейнеры, параллельные примитивы и алгоритмы. Вся эта функциональность хорошо дополняется синтаксисом типа STL. Итак, если вы знакомы с STL, вы можете писать целые программы CUDA, используя только Thrust, без необходимости писать одно ядро ​​CUDA. Взгляните на простые примеры в Краткое руководство, чтобы увидеть вид высокоуровневых программ, которые вы можете написать используя Thrust.

Ответ 2

Есть много высокоуровневых библиотек, посвященных программированию GPGPU. Поскольку они полагаются на CUDA и/или OpenCL, их нужно выбирать с умом (программа на основе CUDA не будет работать на графических процессорах AMD, если она не пройдет этап предварительной обработки с такими проектами, как gpuocelot).

CUDA

Вы можете найти некоторые примеры библиотек CUDA на веб-сайте NVIDIA website.

  • Тяга: официальное описание говорит само за себя

Thrust - это библиотека параллельных алгоритмов, напоминающая стандарт C++ Библиотека шаблонов (STL). Упорный интерфейс высокого уровня значительно повышает продуктивность программиста при обеспечении переносимости производительности между GPU и многоядерные процессоры. Совместимость с установленными технологии (такие как CUDA, TBB и OpenMP) облегчают интеграцию с существующим программным обеспечением.

Как отметил @Ashwin, STL-подобный синтаксис Thrust делает его широко выбранной библиотекой при разработке программ CUDA. Беглый взгляд на примеры показывает, какой код вы будете писать, если решите использовать эту библиотеку. На сайте NVIDIA представлены ключевые функции key features этой библиотеки. Видео-презентация video presentation (из GTC 2012) также доступна.

  • CUB: официальное описание говорит нам:

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

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

Он с открытым исходным кодом и доступен на GitHub. Он не является высокоуровневым с точки зрения реализации (вы разрабатываете в ядрах CUDA), но предоставляет высокоуровневые алгоритмы и процедуры.

  • mshadow: облегченная библиотека матричных/тензорных шаблонов CPU/GPU в C++/CUDA.

Эта библиотека в основном используется для машинного обучения и использует шаблоны выражений expression templates.

  • Eigen: поддержка CUDA с новым классом Tensor была добавлена в версии 3.3. Он используется Google в TensorFlow и все еще экспериментален.

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

OpenCL

Обратите внимание, что OpenCL выполняет не только вычисления на GPGPU, поскольку поддерживает гетерогенные платформы (многоядерные процессоры, графические процессоры и т.д.).

  • OpenACC: этот проект обеспечивает OpenMP-подобную поддержку GPGPU. Большая часть программирования выполняется неявно компилятором и исполняемым API. Вы можете найти образец кода sample code на их веб-сайте.

Интерфейс прикладной программы OpenACC описывает набор директивы компилятора для указания циклов и областей кода в стандарте C, C++ и Fortran должны быть выгружены с центрального процессора на подключенный ускоритель, обеспечивающий переносимость между операционными системами, хост-процессорами и ускорители.

  • Bolt: библиотека с открытым исходным кодом с STL-подобным интерфейсом.

Bolt - это библиотека шаблонов C++, оптимизированная для разнородных вычислений. Bolt предназначен для обеспечения высокопроизводительных библиотечных реализаций. для распространенных алгоритмов, таких как сканирование, уменьшение, преобразование и сортировка. Интерфейс болта был смоделирован в стандартной библиотеке шаблонов C++ (STL). Разработчики, знакомые с STL, распознают многие API-интерфейсы Bolt. и методы настройки.

  • Boost.Compute: как сказал @Kyle Lutz, Boost.Compute предоставляет STL-подобный интерфейс для OpenCL. Обратите внимание, что это не официальная библиотека Boost (пока).

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

CUDA + OpenCL

  • ArrayFire - библиотека программирования GPGPU с открытым исходным кодом. Сначала они предназначались для CUDA, но теперь также поддерживают OpenCL. Вы можете проверить примеры examples, доступные онлайн. Веб-сайт NVIDIA предоставляет хорошее резюме его основных функций.

Дополнительная информация

Хотя на самом деле это не входит в сферу этого вопроса, есть и такая же поддержка для других языков программирования:

Если вам нужно выполнить линейную алгебру (например) или другие конкретные операции, выделенные математические библиотеки также доступны для CUDA и OpenCL (например, ViennaCL, CUBLAS, MAGMA ] и т.д.).

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

Наконец, мы можем упомянуть будущее стандартной библиотеки C++. Была проделана большая работа по добавлению поддержки параллелизма. Это по-прежнему техническая спецификация, и графические процессоры не упоминаются в явном виде как AFAIK (хотя NVIDIA Jared Hoberock, разработчик Thrust, принимает непосредственное участие), но желание воплотить это в реальность определенно есть.

Ответ 3

Взгляните на Boost.Compute. Он обеспечивает высокоуровневый STL-подобный интерфейс, включая контейнеры, такие как vector<T> и такие алгоритмы, как transform() и sort().

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

Ответ 4

Другая библиотека высокого уровня VexCL - библиотека шаблонов векторных выражений для OpenCL. Он предоставляет интуитивную нотацию для векторных операций и доступен по лицензии MIT.

Ответ 5

Если вы ищете контейнеры с более высоким размером и возможность передавать и манипулировать этими контейнерами в коде ядра, я потратил последние несколько лет на разработку ecuda API для оказания помощи в моих собственных проектах научных исследований (так что это было сделано через шаги). Надеюсь, он может заполнить нужную нишу. Краткий пример того, как его можно использовать (здесь используются функции С++ 11, но ecuda отлично работает с компиляторами pre-С++ 11):

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <vector>

#include <ecuda/ecuda.hpp>

// kernel function
__global__
void calcColumnSums(
  typename ecuda::matrix<double>::const_kernel_argument mat,
  typename ecuda::vector<double>::kernel_argument vec
)
{
    const std::size_t t = threadIdx.x;
    auto col = mat.get_column(t);
    vec[t] = ecuda::accumulate( col.begin(), col.end(), static_cast<double>(0) );
}

int main( int argc, char* argv[] )
{

    // allocate 1000x1000 hardware-aligned device memory matrix
    ecuda::matrix<double> deviceMatrix( 1000, 1000 );

    // generate random values row-by-row and copy to matrix
    std::vector<double> hostRow( 1000 );
    for( std::size_t i = 0; i < 1000; ++i ) {
        for( double& x : hostRow ) x = static_cast<double>(rand())/static_cast<double>(RAND_MAX);
        ecuda::copy( hostRow.begin(), hostRow.end(), deviceMatrix[i].begin() );
    }

    // allocate device memory for column sums
    ecuda::vector<double> deviceSums( 1000 );

    CUDA_CALL_KERNEL_AND_WAIT(
        calcColumnSums<<<1,1000>>>( deviceMatrix, deviceSums )
    );

    // copy columns sums to host and print
    std::vector<double> hostSums( 1000 );
    ecuda::copy( deviceSums.begin(), deviceSums.end(), hostSums.begin() );

    std::cout << "SUMS =";
    for( const double& x : hostSums ) std::cout << " " << std::fixed << x;
    std::cout << std::endl;

    return 0;

}

Я написал его как можно более интуитивно понятным (обычно так же просто, как замена std:: ecuda::). Если вы знаете STL, то ecuda должна делать то, что вы логически ожидаете от расширения С++ на CUDA.

Ответ 6

Проект cpp-opencl предоставляет возможность легко программировать графические процессоры для разработчика. Он позволяет реализовать данные parallelism на графическом процессоре непосредственно на С++ вместо использования OpenCL.

См. http://dimitri-christodoulou.blogspot.com/2014/02/implement-data-parallelism-on-gpu.html

И исходный код: https://github.com/dimitrs/cpp-opencl

См. пример ниже. Код в функции lambda parallel_for_each выполняется на графическом процессоре, а все остальное выполняется на CPU. Более конкретно, функция "квадрат" выполняется как на CPU (посредством вызова std:: transform), так и на GPU (посредством вызова для вычисления:: parallel_for_each).

#include <vector>
#include <stdio.h>
#include "ParallelForEach.h"

template<class T> 
T square(T x)  
{
    return x * x;
}

void func() {
  std::vector<int> In {1,2,3,4,5,6};
  std::vector<int> OutGpu(6);
  std::vector<int> OutCpu(6);

  compute::parallel_for_each(In.begin(), In.end(), OutGpu.begin(), [](int x){
      return square(x);
  });


  std::transform(In.begin(), In.end(), OutCpu.begin(), [](int x) {
    return square(x);
  });

  // 
  // Do something with OutCpu and OutGpu …..........

  //

}

int main() {
  func();
  return 0;
}

Ответ 7

Новая OpenMP версия 4 теперь включает поддержку разгрузки ускорителя.

Графики AFAIK рассматриваются как ускорители.

Ответ 8

С++ AMP - это ответ, который вы ищете.