CUDA C和C++的解释

32

有没有人能够对CUDA C和C++的本质给我一个很好的解释?据我所知,CUDA应该是带有NVIDIA GPU库的C语言。目前为止,CUDA C支持一些C++功能,但不支持其他功能。

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


1
我不会猜测他们会花费任何精力来支持在GPU硬件上性能较差的C++特性,例如异常处理,因为CUDA是围绕高性能数值计算设计的。 - Ben Voigt
我们能否将标题改为:“CUDA C/C++和ISO C/C++之间有什么区别?”这就是实际回答的内容,NVIDIA会做什么或不会做什么只能推测。 - Ciro Santilli OurBigBook.com
5个回答

28

CUDA C是一种具有C语法的编程语言。概念上与C有很大不同。

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

CUDA不仅支持单指令多数据(SIMD)向量处理,还支持数据流>>指令流,否则受益较少。

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

CUDA并不针对多样化的多个指令流进行优化,如多核x86。

CUDA不仅限于像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程序可以同时操作多千字节位向量。CUDA不能自动地将现有的顺序C/C++库代码转换成能够实现这一点的代码。

CUDA提供了一种相对简单的方法来编写代码,使用熟悉的C/C++语法,添加了几个额外的概念,并生成可以在处理器数组上运行的代码。它有可能比例如多核x86要快10倍以上。

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

对于最佳性能,CUDA希望在编译时获取信息。

因此,模板机制是最有用的,因为它给开发人员提供了一种在编译时表达的方式,CUDA编译器可以使用。作为一个简单的例子,如果一个矩阵被定义(实例化)为2D和4 x 8,则CUDA编译器可以使用它来组织程序跨处理器运行。如果该大小是动态的,并且在程序运行时发生变化,那么编译器或运行时系统要做一个非常高效的工作就会困难得多

编辑: CUDA具有类和函数模板。 如果人们认为我在说CUDA不支持这个,我很抱歉。我同意我表达得不够清楚。

我认为CUDA GPU端对C++的模板实现尚不完整。

用户harrism曾评论过我的回答是误导性的。harrism为NVIDIA工作,所以我会等待他的建议。希望现在已经更加清晰了。

跨多个处理器高效地完成动态分支的最困难的部分是因为它有效地使代码串行化;在最坏的情况下,只有一个处理器可以执行,这浪费了GPU的好处。因此,虚函数似乎很难做得很好。

有一些非常聪明的整体程序分析工具,可以推断出比开发人员更多的类型信息。现有工具可能已经推断出足够的信息来消除虚拟函数,从而将分支的分析移动到编译时。还有一些技术可以对程序执行进行仪器化,并直接反馈回重新编译程序,从而可能达到更好的分支决策。

据我所知(除了反馈),CUDA编译器在这些领域还没有最先进的水平。

我认为,任何对CUDA或OpenCL系统有兴趣的人,在几天内研究并进行一些实验是值得的。我也认为,对于那些对这些领域感兴趣的人来说,尝试使用Haskell,并查看Data Parallel Haskell也很值得努力。


1
感谢大家的回答。我刚开始学习CUDA,还没有完全掌握GPU编程的细节。 - Tianxiang Xiong
@xiongtx - 很高兴能帮忙。我花了一些时间才弄明白。他们一开始没有好好解释,让我有点失望。相反,他们变得着迷于它有多聪明。 - gbulmer
3
这个回答是错误的和不准确的。举例来说,CUDA并不会自动并行化“for”循环,并且它已经支持模板(除了继承、虚函数、运算符重载、引用、设备上的new/delete以及许多其他C++特性)。 - harrism
1
@harrism - 如果我对“模板”这个概念的描述不准确,我向你道歉。我试图保持在一个较高的层次上进行说明。我很愿意尝试改进它。我并没有说CUDA没有模板,但我可以看出我表达得不清楚。我曾经认为模板仍然受限(相对于C++),例如部分模板特化,它可以提供处理一般情况的方法,但对特定情况进行优化。如果这不是真的,请你指出一些例子给我吗?你所说的“不会自动并行化”是什么意思?我没有写过那样的话。CUDA不能做到这一点,所以我想修正我的措辞。 - gbulmer
你写道:“CUDA系统将分割循环的执行。”这是错误的。它并行运行内核。没有任何自动分区。内核中的循环(例如for,while)由每个线程按顺序执行。问题在于你试图解释CUDA是什么,而OP已经问了CUDA支持哪些C++特性。让你的答案变得更长并没有帮助。 - harrism
1
我再次道歉,我故意写成'loop'而不是'loops',是为了传达将for循环转换的想法。我以为使用"kernel"这个词不会有帮助,但我可以再试一次。我宁愿得到一个清晰的答案。原帖问道:"有人能给我一个关于CUDA C和C++本质的好解释吗?"我特别标注了第一部分为C,以便区分在CUDA中使用'vanilla' C(当然除了<<<...>>>)来完成内核和控制流的概念。至于CUDA对模板支持与C++的比较,CUDA是否支持全部C++(不包括C++11)的模板支持呢? - gbulmer

28

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

CUDA C++

目前,CUDA C++支持附录D(“C/C ++语言支持”)中描述的C++子集,该附录包含在CUDA C编程指南中。

例如:

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

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

示例和特定限制也在上面链接的同一附录中详细说明。作为CUDA中使用C ++的非常成熟的示例,我建议查看Thrust

未来计划

(声明:我在NVIDIA工作。)

我不能明确提及未来发布和时间安排,但我可以说明一个趋势,即几乎每个CUDA版本的发布都会添加其他语言特性,以将CUDA C++支持提高到其当前(在我看来非常有用的)状态。我们计划继续这种趋势,以改进对C ++的支持,但自然地,我们优先考虑在大规模并行计算架构(GPU)上有用且高效的特性。


1
你好@harrism,是否可能更新这个答案以反映CUDA中C++的当前状态和2015年后的未来计划? - Bar
CUDA Fortran和PyCUDA实际上是Fortran和Python的核心版本,编译后可以在GPU上运行吗?还是只是主机API? - Ciro Santilli OurBigBook.com
CUDA Fortran是带有CUDA扩展的Fortran编译器,同时还带有主机API。PyCUDA更多地是一个主机API和便利工具,但内核仍然必须用CUDA C++编写。"CUDA Python"是Numba的一部分,是用于在GPU上运行CUDA注释Python的编译器。 - harrism

10
许多人并没有意识到,CUDA实际上是两种新的编程语言,都源自于C++。其中一种用于编写在GPU上运行的代码,是C++的子集。它的功能类似于HLSL(DirectX)或Cg(OpenGL),但具有更多的特性和与C++的兼容性。需要注意的是,该语言涉及到各种GPGPU / SIMT / 性能相关的问题。另一个被称为“Runtime API”的语言实际上不完全是传统意义上的“API”。Runtime API用于编写在主机CPU上运行的代码。它是C ++的超集,使得链接和执行GPU代码变得更加容易。需要使用NVCC预编译器,然后调用平台的C++编译器。相比之下,驱动程序API(和OpenCL)是纯粹的标准C库,使用起来更加冗长(同时提供了很少的附加功能)。
创建一个新的主机端编程语言是NVIDIA的大胆举动。这使得入门CUDA变得更加容易,编写代码也更加优雅。然而,真正聪明的是将它作为一种新语言进行营销推广。

2
有时候您会听说CUDA是C和C ++,但我认为它不是,原因很简单,这是不可能的。引用他们的编程指南:
对于主机代码,nvcc支持主机c++编译器支持的C++ ISO/IEC 14882:2003规范的任何部分。 对于设备代码,nvcc支持第D.1节中所示的功能,并在第D.2节中描述了一些限制;不支持运行时类型信息(RTTI),异常处理和C++标准库。
据我所见,它只涉及C ++,并且仅支持与C ++重叠的C。因此最好将其视为C++,其中设备部分使用扩展而不是C。如果您习惯使用C,则可以避免许多麻烦。

1
"NVIDIA 的计划是什么?我认为总趋势是,对于许多应用程序来说,CUDA 和 OpenCL 被视为技术过于低级。现在,Nvidia 正在大力投资于 OpenACC,它可以粗略地描述为 GPU 的 OpenMP。它采用声明性方法,在更高的层次上解决 GPU 并行化问题。这就是我非常主观的对 Nvidia 计划的印象。"

拥有一个功能强大的GPU编程接口,配备一款智能库用于向GPU分配计算任务,这将是非常酷的。 - quant_dev
为什么?这个任务与编写BLAS实现并没有太大的区别。 - quant_dev
@OliCharlesworth 好的,我明白你的观点。我并不是说代码应该替我决定是否使用GPU,而是它应该决定如何使用GPU。即使效率降低了10%,能够轻松地为GPU编写代码也是很好的。 - quant_dev
@Pavan,很整洁。为什么我在你的网站上很难找到C++的例子? - quant_dev
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接