C++ 类 用于高性能计算

C++ Classes for High Performance Computing

根据this Quora forum

One of the simplest rules of thumb is to remember that hardware loves arrays, and is highly optimized for iteration over arrays. A simple optimization for many problems is just to stop using fancy data structures and just use plain arrays (or std::vectors in C++). This can take some getting used to.

C++ 类 是那些“花哨的数据结构”之一,即一种可以用数组替换以在 C++ 程序中实现更高性能的数据类型吗?

Are C++ classes one of those "fancy data structures,"

我认为他们特别指的是像 std::mapstd::dequestd::list 等容器,它们在许多不同的堆分配中保存数据,因此迭代容器在某种程度上要求 CPU 在 RAM 地址 space 中“跳来跳去”,而不是仅仅按顺序读取 RAM。 hopping-around 通常会限制性能,因为 CPU 的 on-board 内存缓存在避免 execution-stalls 方面效果较差,因为当未来的 RAM 访问位置不是时,RAM 延迟容易预测。

C++ class 本身可能会也可能不会鼓励 non-sequential RAM 访问;它是否完全取决于 class 是如何实现的(特别是它是否通过多个堆分配来保存其数据)。 std::vector class(在论坛文本中提到)是 C++ class 的一个示例,当您遍历其内容时不需要任何 non-sequential 内存访问。

如果您的 class 看起来像这样:

struct Person {
  double age;
  double income;
  size_t location;
};

那么您可能受益于重新排列为

std::vector<double> ages;
std::vector<double> incomes;
std::vector<size_t> locations;

但这取决于您的访问模式。如果您经常一次访问一个人的多个元素,那么将这些元素放在一起是有意义的。

如果您的 class 看起来像这样:

struct Population {
  std::vector<double> many_ages;
  std::vector<double> many_incomes;
  std::vector<size_t> many_locations;
};

那么您正在使用资源推荐的表单。单独使用这些数组中的任何一个都比使用第一个 class 快,但同时使用所有三个数组中的元素可能比第二个 class.

最终,您应该将代码结构设计得尽可能简洁直观。速度的最大来源将是对算法的深刻理解和适当使用,而不是内存布局。我建议忽略这一点,除非您已经具备强大的 HPC 技能并且需要从您的机器中榨取最大性能。在几乎所有其他情况下,您的开发时间和理智都比节省几个时钟周期更有价值。

更广泛

  1. 一篇与此相关的有趣论文是 SLIDE: In Defense of Smart Algorithms over Hardware Acceleration for Large-Scale Deep Learning Systems。在将 ML 算法映射到 GPU 方面做了大量工作,对于 ML 应用程序,正确的内存布局确实产生了真正的影响,因为训练花费了大量时间,而且 GPU 专门针对 contiguous-array 处理进行了优化。但是,该论文的作者认为,即使在这里,如果你很好地理解算法,你也可以通过优化的内存布局击败专用硬件,他们通过让他们的 CPU 训练速度比他们的 GPU 快 3.5 倍来证明这一点。

  2. 更广泛地说,您的问题涉及 cache misses. Since a cache miss is 200x more expensive than an L1 reference (link), if your data layout is optimized to your computation, then you can really save time. However, as the above suggests, it is rarely the case that simply rearranging your data magically makes everything faster. Consider matrix multiplication. It's the perfect example because the data is laid out in a single array, as requested by your resource. However, for a simple triple-loop matmult GEMM implementation there are still 6 ways to arrange your loops. Some of these ways are much more efficient than others, but none of them give you anywhere near peak performance. Read through this step-by-step explanation of matmult 的想法,以便更好地了解获得良好性能所需的所有算法优化。

以上应该说明的是,即使在我们只有几个数组完全按照您的资源建议布局的情况下,布局本身并不能给我们带来速度。好的算法可以。数据布局注意事项(如果有的话)来自我们选择的算法和 higher-level 硬件限制。

如果对于简单的数组和矩阵乘法之类的操作是这样,那么通过扩展,您也应该期望它对于“奇特的数据结构”也是如此。

Are C++ classes one of those "fancy data structures," i.e. a kind of data type that can be replaced by arrays to achieve a higher performance in a C++ program?

计算机时间和您的开发时间都很宝贵。

除非您确定它占用了大部分 CPU 时间,否则不要优化代码。

所以先用一个profiler (e.g. Gprof) and read the documentation of your C or C++ compiler (e.g. GCC)。编译器能够进行花哨的优化。

如果您真的关心 HPC,请学习 GPGPU 编程,例如OpenCL or OpenACC.

如果您碰巧使用 Linux(HPC 世界中常见的 OS),请阅读 Advanced Linux Programming, then syscalls(2), then time(7)

Are C++ classes one of those "fancy data structures,

C++ class 是一种可用于创建数据类型的结构。它可用于创建数据结构,如列表、队列等。

i.e. a kind of data type

一个class是一种数据类型

that can be replaced by arrays

A class 和数组不可互换。数组是数据结构。你在拿苹果和橙子做比较。

to achieve a higher performance in a C++ program?

这取决于您如何实施 class