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++ 语法,添加一些额外的概念,并生成将跨处理器阵列运行的代码。它有可能提供超过 10 倍的加速比,例如多核 x86。
编辑 - 计划:我不为 NVIDIA 工作
为了获得最佳性能,CUDA 需要在编译时获得信息。
所以模板机制是最有用的,因为它为开发人员提供了一种在编译时表达事物的方式,CUDA 编译器可以使用这种方式。举个简单的例子,如果在编译时将矩阵定义(实例化)为 2D 和 4 x 8,那么 CUDA 编译器可以使用它来跨处理器组织程序。如果该大小是动态的,并且在程序运行时发生变化,那么编译器或运行时系统就很难完成一项非常有效的工作。
编辑:
CUDA 有类和函数模板。
如果人们读到这篇文章说 CUDA 没有,我深表歉意。我同意我不清楚。
我相信 CUDA GPU 端的模板实现并不完整 w.r.t。 C++。
用户 harrism 评论说我的回答具有误导性。 harrism 适用于 NVIDIA,所以我会等待建议。希望这已经更清楚了。
跨多个处理器高效地做的最困难的事情是动态地向下分支许多替代路径,因为这可以有效地序列化代码;在最坏的情况下,一次只能执行一个处理器,这浪费了 GPU 的优势。所以虚函数似乎很难做好。
有一些非常智能的整体程序分析工具可以推断出比开发人员可能理解的更多的类型信息。现有工具可能会推断出足以消除虚函数,从而将分支分析转移到编译时间。还有一些用于检测程序执行的技术,这些技术直接反馈到程序的重新编译中,这可能会达到更好的分支决策。
AFAIK(模反馈)CUDA 编译器在这些领域还不是最先进的。
(恕我直言,任何有兴趣的人都值得花几天时间,使用支持 CUDA 或 OpenCL 的系统来调查它们,并做一些实验。我也认为,对于对这些领域感兴趣的人,值得付出努力用 Haskell 做实验,看看Data Parallel Haskell)