CUDA C和c++的说明

Explanation of CUDA C and C++

本文关键字:说明 c++ CUDA      更新时间:2023-10-16

谁能给我一个很好的解释CUDA C和c++的性质?据我所知,CUDA应该是带有NVIDIA的GPU库的C语言。到目前为止,CUDA C支持一些c++特性,但不支持其他特性。

NVIDIA的计划是什么?他们会在C的基础上构建,并添加自己的库(例如Thrust vs. STL),与c++的库并行吗?它们最终会支持所有的c++吗?在.cu文件中使用c++头是不好的吗?

CUDA C是一种使用C语法的编程语言。从概念上讲,它与c有很大的不同。

它试图解决的问题是为多个处理器编码多个(类似的)指令流。

CUDA提供了比单指令多数据(SIMD)矢量处理更多的数据流>指令流,否则会有更少的好处。

CUDA提供了一些机制来做到这一点,并隐藏了一些复杂性。

CUDA没有像多核x86那样针对多个不同的指令流进行优化。CUDA不像x86矢量指令那样局限于单个指令流,也不像x86矢量指令那样局限于特定的数据类型。

CUDA支持'循环',可以并行执行。这是它最关键的特点。CUDA系统将对"循环"的执行进行分区,并在一组相同的处理器上同时运行"循环"体,同时提供一些正常顺序循环的错觉(特别是CUDA管理循环索引)。开发人员需要了解GPU机器的结构来有效地编写"循环",但几乎所有的管理都是由CUDA运行时处理的。效果是数百(甚至数千)个"循环"在同一时间完成一个"循环"。

CUDA支持看起来像if分支。只有运行与if测试匹配的代码的处理器才能处于活动状态,因此对于if测试的每个"分支",处理器的子集将处于活动状态。以if... else if ... else ...为例,它有三个分支。每个处理器将只执行一个分支,并"重新同步",准备在if完成时与其他处理器一起继续。可能是某些分支条件与任何处理器都不匹配。因此不需要执行该分支(对于该示例,三个分支是最坏的情况)。然后依次执行一个或两个分支,更快地完成整个if

没有"魔法"。程序员必须意识到代码将在CUDA设备上运行,并有意识地为它编写代码。

CUDA不接受旧的C/c++代码,自动神奇地在一组处理器上运行计算。CUDA可以按顺序编译和运行普通的C语言和大部分c++语言,但这样做几乎没有什么好处,因为它是按顺序运行的,而且比现代CPU要慢。这意味着某些库中的代码(尚未)与CUDA功能很好地匹配。CUDA程序可以同时处理多kbyte的位向量。CUDA不能自动神奇地将现有的顺序C/c++库代码转换成可以这样做的东西。

CUDA确实提供了一种相对直接的方式来编写代码,使用熟悉的C/c++语法,添加一些额外的概念,并生成将在一系列处理器上运行的代码。与多核x86相比,它有可能提供超过10倍的加速。

编辑-计划:我不为NVIDIA工作

为了获得最佳性能,CUDA需要在编译时获取信息。

所以模板机制是最有用的,因为它给了开发人员一种在编译时说事情的方式,CUDA编译器可以使用。举个简单的例子,如果一个矩阵在编译时被定义(实例化)为2D和4 x 8,那么CUDA编译器可以使用它来组织跨处理器的程序。如果该大小是动态的,并且在程序运行时发生变化,那么编译器或运行时系统将很难非常有效地完成工作。

编辑:CUDA有类和函数模板。如果人们把这篇文章解读为CUDA不能做到这一点,我很抱歉。我承认我说得不够清楚。

我相信CUDA gpu端模板的实现是不完整的。用户harrism评论说我的回答是误导。harrism为NVIDIA工作,所以我会等待建议。希望这已经更清楚了。

跨多个处理器最困难的事情是动态分支到许多可选路径,因为这有效地序列化了代码;在最坏的情况下,一次只能执行一个处理器,这会浪费GPU的优势。因此,虚函数似乎很难做好。

有一些非常聪明的整个程序分析工具,它们可以推断出比开发人员可能理解的更多的类型信息。现有的工具可能会做出足够的推断来消除虚函数,从而将分支分析转移到编译时间。还有一些检测程序执行的技术,这些技术可以直接反馈到程序的重新编译中,从而可以做出更好的分支决策。

CUDA编译器在这些领域还不是最先进的。

(在我看来,对于任何有兴趣的人来说,花几天时间研究它们,并做一些实验是值得的,有CUDA或opencl支持的系统。)我还认为,对于对这些领域感兴趣的人来说,非常值得尝试一下Haskell,并看看Data Parallel Haskell)

CUDA是一个平台(架构、编程模型、汇编虚拟机、编译工具等),而不仅仅是一种编程语言。CUDA C只是建立在这个平台上的许多语言系统之一(CUDA C, c++, CUDA Fortran, PyCUDA,还有其他)。

CUDA c++

目前CUDA c++支持CUDA C编程指南附录D("C/c++语言支持")中描述的c++子集。

举几个例子:

  • __device__成员函数(包括构造函数和析构函数)
  • 继承/派生类
  • 虚函数
  • 类和函数模板
  • 操作符和重载
  • <
  • 函子类/gh>

编辑:从CUDA 7.0开始,CUDA c++在__device__代码(在GPU上运行的代码)中包含了对c++ 11标准的大多数语言特性的支持,包括auto、lambda表达式、基于范围的for循环、初始化列表、静态断言等等。

示例和具体限制也在上面链接的同一附录中详细说明。作为一个非常成熟的c++与CUDA结合使用的例子,我推荐你看看Thrust。

未来计划(披露:我为NVIDIA工作)

我不能明确说明未来的版本和时间,但我可以说明一个趋势,即几乎每个CUDA版本都添加了额外的语言特性,以使CUDA c++支持达到当前(在我看来非常有用)的状态。我们计划继续这一趋势,以改善对c++的支持,但我们自然会优先考虑在大规模并行计算架构(GPU)上有用且性能良好的特性。

很多人都没有意识到,CUDA实际上是两种新的编程语言,都源自c++。一种是编写在gpu上运行的代码,它是c++的一个子集。它的功能类似于HLSL (DirectX)或Cg (OpenGL),但具有更多的功能和与c++的兼容性。各种GPGPU/SIMT/性能相关的问题适用于它,我不需要提及。另一个是所谓的"运行时API",它几乎不是传统意义上的"API"。运行时API用于编写在主机CPU上运行的代码。它是c++的超集,使得链接和启动GPU代码变得更加容易。它需要NVCC预编译器,然后调用平台的c++编译器。相比之下,驱动程序API(和OpenCL)是一个纯粹的、标准的C库,使用起来要冗长得多(同时提供了一些额外的功能)。

对于NVIDIA来说,创造一种新的主机端编程语言是一个大胆的举动。它使CUDA入门更容易,编写代码更优雅。然而,真正优秀的不是把它作为一种新语言来营销。

有时你会听说CUDA是C和c++,但我不这么认为,原因很简单,这是不可能的。从他们的编程指南中引用:

对于主机代码,nvcc支持c++ ISO/IEC的任何部分14882:2003主机c++编译器支持的规范。

对于设备代码,nvcc支持章节中说明的特性D.1,但有D.2节所述的一些限制;事实并非如此支持运行时类型信息(RTTI)、异常处理和c++标准库。

正如我所看到的,它只指c++,并且只在C和c++的交集处支持C。所以最好把它看作是带有设备部分扩展的c++,而不是C。如果你习惯使用C,这会避免很多麻烦。

NVIDIA的计划是什么?

我相信总的趋势是CUDA和OpenCL对于许多应用程序来说被认为是太低级的技术。现在,英伟达正在大力投资OpenACC,这可以大致描述为gpu的OpenMP。它遵循一种声明式的方法,在更高的层次上解决GPU并行化的问题。以上就是我对英伟达计划的主观印象。