C ++中的高级GPU编程

时间:2013-05-08 10:17:07

标签: c++ cuda gpu gpu-programming

我一直在研究C ++的库/扩展,它们将允许基于GPU的高级处理。我不是GPU编程方面的专家,我不想深入挖掘。我有一个由具有虚函数的类组成的神经网络。我需要一个基本上为我分配GPU的库 - 在很高的层次上。有一个人在一个名为GPU ++的系统上写了一篇论文,它为你做了大部分的GPU工作。我无法在任何地方找到代码,只是他的论文。

有没有人知道类似的库,或者有没有人拥有GPU ++的代码?像CUDA这样的库太低了,无法处理我的大部分操作(至少没有重写我的所有进程和算法 - 我不想这样做。)

8 个答案:

答案 0 :(得分:45)

有许多专门用于GPGPU编程的高级库。由于它们依赖于CUDA和/或OpenCL,因此必须明智地选择它们(基于CUDA的程序不会在AMD的GPU上运行,除非它通过{{3}等项目进行预处理步骤})。

CUDA

您可以在NVIDIA gpuocelot上找到一些CUDA库的示例。

  • website:官方说明不言而喻
  

Thrust是一个类似于C ++标准的并行算法库   模板库(STL)。 Thrust的高级界面大大增强   程序员的工作效率,同时实现性能可移植性   GPU和多核CPU。与已建立的互操作性   技术(如CUDA,TBB和OpenMP)有助于集成   使用现有软件。

正如Thrust指出的那样,Thrust的类似STL的语法使其成为开发CUDA程序时广泛选择的库。快速查看这些示例,可以看出如果您决定使用此库,您将编写的代码类型。 NVIDIA的网站提供了此库的@Ashwin。还可以获得key features(来自GTC 2012)。

  

CUB为​​CUDA编程模式的每一层提供最先进的,可重复使用的软件组件。它是一个灵活的协作线程块原语库和其他用于CUDA内核编程的实用程序。

它提供设备范围,块宽和整个经线的并行原语,如并行排序,前缀扫描,缩减,直方图等。

它是开源的,可在CUB上找到。从实现的角度来看,它不是高级的(你在CUDA内核中开发),但它提供了高级算法和例程。

  • GitHub:C ++ / CUDA中的轻量级CPU / GPU矩阵/张量模板库。

此库主要用于机器学习,并依赖于mshadow

  

从Eigen 3.3开始,现在可以在CUDA内核中使用Eigen的对象和算法。但是,仅支持一部分功能,以确保在CUDA内核中不会触发动态分配。

的OpenCL

请注意,TensorFlow不仅仅是GPGPU计算,因为它支持异构平台(多核CPU,GPU等)。

  • OpenCL:此项目为GPGPU提供类似OpenMP的支持。编程的很大一部分是由编译器和运行时API隐式完成的。您可以在他们的网站上找到OpenACC
  

OpenACC应用程序接口描述了一个集合   编译器指令,用于指定标准中的循环和代码区域   C,C ++和Fortran从主机CPU卸载到附加   加速器,提供跨操作系统,主机CPU的可移植性   和加速器。

  

Bolt是一个针对异构计算而优化的C ++模板库。   Bolt旨在提供高性能库实现   用于常见算法,例如扫描,缩小,转换和排序。该   Bolt接口在C ++标准模板库(STL)上建模。   熟悉STL的开发人员将认识到许多Bolt API   和定制技术。

  • Bolt:正如Boost.Compute所述,Boost.Compute为OpenCL提供类似STL的接口。请注意,这还不是官方的Boost库。

  • @Kyle Lutz"是一个提供高级抽象的库,用于缓解现代并行异构系统的编程"。此库依赖于SkelCL,您可以在skeleton programming中找到更多信息。

CUDA + OpenCL

  • research papers是一个开源(以前是专有的)GPGPU编程库。他们首先针对CUDA,但现在也支持OpenCL。您可以在线查看ArrayFire。 NVIDIA的网站提供examples其主要功能。

补充资料

虽然这不是这个问题的范围,但对其他编程语言也有同样的支持:

如果您需要进行线性代数(例如)或其他特定操作,专用数学库也可用于CUDA和OpenCL(例如other questionViennaCLCUBLAS等。 )。

另请注意,如果您需要进行一些非常具体的计算,使用这些库并不会阻止您执行某些低级操作。

最后,我们可以提到C ++标准库的未来。已经进行了大量工作来增加并行性支持。这是MAGMA,并没有明确提到GPU(AFAIK)(尽管NVIDIA的Thrust开发商Jared Hoberock直接参与其中),但是实现这一目标的意愿绝对存在。

答案 1 :(得分:26)

Thrust 库提供容器,并行基元和算法。所有这些功能都很好地包含在类似STL的语法中。因此,如果您熟悉STL,您实际上可以使用Thrust编写整个CUDA程序,而无需编写单个CUDA内核。查看 Quick Start Guide 中的简单示例,了解您可以使用Thrust编写的高级程序。

答案 2 :(得分:15)

看看Boost.Compute。它提供了一个类似STL的高级接口,包括vector<T>等容器以及transform()sort()等算法。

它基于OpenCL构建,允许它在大多数现代GPU和CPU上运行,包括NVIDIA,AMD和Intel的那些。

答案 3 :(得分:2)

另一个高级库是VexCL - OpenCL的矢量表达式模板库。它为矢量操作提供了直观的表示法,并且可以在MIT许可下使用。

答案 4 :(得分:2)

如果您正在寻找更高维度的容器以及在内核代码中传递和操作这些容器的能力,我花了几年时间开发ecuda API来协助我自己的科研项目(所以它已经完成了步伐)。希望它可以填补所需的利基。它是如何使用的简短示例(此处使用了C ++ 11特性,但ecuda可以与前C ++ 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;

}

我把它写成尽可能直观(通常就像用ecuda替换std :: :)一样简单。如果你知道STL,那么ecuda应该做你在逻辑上期望基于CUDA的C ++扩展所做的事情。

答案 5 :(得分:1)

cpp-opencl项目提供了一种使开发人员可以轻松编程GPU的方法。它允许您直接在C ++中实现GPU上的数据并行性,而不是使用OpenCL。

请参阅http://dimitri-christodoulou.blogspot.com/2014/02/implement-data-parallelism-on-gpu.html

源代码:https://github.com/dimitrs/cpp-opencl

请参阅下面的示例。 parallel_for_each lambda函数中的代码在GPU上执行,其余所有代码都在CPU上执行。更具体地说,“square”函数在CPU上(通过调用std :: transform)和GPU(通过调用compute :: 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;
}

答案 6 :(得分:1)

新的OpenMP版本4现在包含加速器卸载支持。

AFAIK GPU被视为加速器。

答案 7 :(得分:0)

C ++ AMP是您正在寻找的答案。