43

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

有谁知道类似的库,或者有没有人有 GPU++ 的代码?像 CUDA 这样的库级别太低,无法处理我的大部分操作(至少在不重写我所有的流程和算法的情况下不能——我不想这样做)。

4

8 回答 8

56

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

CUDA

您可以在 NVIDIA网站上找到一些 CUDA 库示例。

  • 推力:官方描述不言自明

Thrust 是一个类似于 C++ 标准模板库 (STL) 的并行算法库。Thrust 的高级接口极大地提高了程序员的工作效率,同时实现了 GPU 和多核 CPU 之间的性能可移植性。与现有技术(如 CUDA、TBB 和 OpenMP)的互操作性有助于与现有软件的集成。

正如@Ashwin 所指出的,在开发 CUDA 程序时,Thrust 的类似 STL 的语法使其成为广泛选择的库。如果您决定使用这个库,快速浏览这些示例会显示您将编写的代码类型。NVIDIA 的网站介绍了该库的主要功能。还提供视频演示(来自 GTC 2012)。

  • CUB:官方描述告诉我们:

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

它提供了设备范围、块范围和扭曲范围的并行原语,例如并行排序、前缀扫描、归约、直方图等。

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

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

这个库主要用于机器学习,并且依赖于表达式模板

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

开放式

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

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

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

  • Bolt:具有类似 STL 接口的开源库。

Bolt 是针对异构计算优化的 C++ 模板库。Bolt 旨在为扫描、归约、转换和排序等常见算法提供高性能库实现。Bolt 接口以 C++ 标准模板库 (STL) 为模型。熟悉 STL 的开发人员会认识许多 Bolt API 和定制技术。

  • Boost.Compute:正如@Kyle Lutz所说,Boost.Compute 为OpenCL 提供了一个类似STL 的接口。请注意,这还不是官方的 Boost 库。

  • SkelCL “是一个为现代并行异构系统的简化编程提供高级抽象的库”。这个库依赖于骨架编程,你可以在他们的研究论文中找到更多信息。

CUDA + OpenCL

  • ArrayFire是一个开源(曾经是专有的)GPGPU 编程库。他们首先针对 CUDA,但现在也支持 OpenCL。您可以查看在线提供的示例。NVIDIA 的网站对其主要功能进行了很好的总结

补充资料

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

如果您需要进行线性代数(例如)或其他特定运算,也可以使用 CUDA 和 OpenCL 的专用数学库(例如ViennaCLCUBLASMAGMA等)。

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

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

于 2013-05-12T08:52:04.727 回答
35

Thrust库提供容器、并行原语和算法。所有这些功能都很好地封装在类似 STL 的语法中。因此,如果您熟悉 STL,您实际上可以仅使用 Thrust 编写整个 CUDA 程序,而无需编写单个 CUDA 内核。查看快速入门指南中的简单示例,了解您可以使用 Thrust 编写的高级程序。

于 2013-05-10T08:52:08.627 回答
15

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

它基于OpenCL构建,可以在大多数现代 GPU 和 CPU 上运行,包括 NVIDIA、AMD 和 Intel 的 CPU。

于 2013-05-08T12:44:32.703 回答
2

另一个高级库是VexCL ——OpenCL 的矢量表达式模板库。它为向量运算提供直观的符号,并在 MIT 许可下可用。

于 2013-05-18T06:38:28.720 回答
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++ 扩展做的事情。

于 2016-02-02T20:54:07.897 回答
1

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

请参阅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;
}
于 2014-02-07T19:43:37.440 回答
1

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

AFAIK GPU 被视为加速器。

于 2014-03-14T11:19:19.010 回答
0

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

于 2013-05-12T17:52:15.103 回答