【问题标题】:What's the fastest way to copy and manipulate large, dense 2D arrays in c++在 C++ 中复制和操作大型密集二维数组的最快方法是什么
【发布时间】:2012-12-10 09:56:30
【问题描述】:

我正在尝试优化我的代码,利用多核处理器来复制任何可操作的大型密集数组。

对于复制:我有一个大的密集数组(大约 6000x100000),我需要从中拉出 15x100000 个子数组来执行多个计算。管道由许多由多核 blas 处理的线性代数函数组成。与线性代数相比,提取数据的时间是否真的很重要是一个悬而未决的问题,但我想谨慎起见并确保数据复制得到优化。

对于操作:我有许多不同的函数可以通过元素或行来操作数组。最好是每一个都是多核的。

我的问题是:最好使用正确的框架(OpenML、OpenCL)并让所有的魔法发生在编译器上,还是有更好的函数/库可以更快地做到这一点?

【问题讨论】:

  • 我最初的想法之一是,如果您的矩阵以行优先顺序存储,那么您可以在不进行任何复制的情况下引用 15 行部分。
  • 是的,但最终还是需要复制,因为我不想更改数据。
  • 子数组为 15x1000000,初始为 6000x100000。 1000000 vs 100000,错字在哪里?
  • 1000000 是错字。应该是 100000
  • 对于在 GPU 上处理非常大的矩阵是可行的方法,请查看 ViennaCL 项目。

标签: c++ arrays performance parallel-processing opencl


【解决方案1】:

你的出发点应该是古老的memcpy。长期痴迷于“复制性能”的一些小贴士。

  1. 阅读What Every Programmer Should Know About Memory
  2. 对您的系统进行基准测试memcpy 性能,例如memcpy_bench 功能here
  3. 基准测试memcpy 在多个内核上运行时的可扩展性,例如multi_memcpy_bench here。 (除非您使用一些多插槽 NUMA 硬件,否则我认为您不会看到多线程复制有太多好处)。
  4. 深入了解系统的 memcpy 实现并了解它们。你会发现大部分时间都在一个单独的rep movsd 中度过的日子已经一去不复返了。上次我查看 gcc 和 Intel 编译器的 CRT 时,它们都根据相对于 CPU 缓存大小的副本大小来改变策略。
  5. 在 Intel 上,了解非缓存污染存储指令(例如 movntps)的优势,因为与传统方法相比,这些指令可以实现 significant throughput improvements(您将在 4 中看到这些指令的使用)
  6. 有权访问并知道如何使用采样分析器来确定您的应用程序有多少时间用于复制操作。还有更高级的工具可以查看 CPU 性能计数器,并告诉您各种缓存正在做什么等各种事情。
  7. (高级主题)注意 TLB 和 when huge pages can help

但我的期望是,与任何 linalg 繁重的工作相比,您的副本将是相当小的开销。很高兴知道这些数字是多少。我不希望 OpenCL 或任何 for CPU 在这里神奇地提供任何改进(除非您的系统的 memcpy 实现不佳);恕我直言,最好更详细地研究这些东西,深入了解在指令、寄存器、缓存行和页面级别实际发生的事情的基础,而不是通过在顶部分层另一个抽象级别来摆脱这些.

当然,如果您正在考虑将您当前使用的任何多核 BLAS 库中的代码移植到 GPU 加速的线性代数版本,这将成为一个完全不同(而且更加复杂)的问题(请参阅下面的 JayC 评论)。如果您想要显着性能提升,您当然应该考虑它。

【讨论】:

  • memcpy 是类型不安全且不好的。使用std::copy。不,与 memcpy 相比,它没有运行时开销。
  • @Zoidberg:std::copy 开销为零的原因是任何体面的编译器都会用 memcpy/memmove 替换它,至少是 POD 类型(有没有现代主流编译器不这样做吗?并非总是如此),因此无论您如何理解,了解 memcpy 性能仍然很重要。但是是的,在这种情况下使用 std::copy 是一个很好的建议。另见例如这个答案stackoverflow.com/a/4707028/24283
  • 我认为这个答案对于 CPU(仅)问题来说非常好。但是,如果 OpenCL(通常)是一个选项,正如 OP 所建议的那样,我们可能还需要了解与主内存和 GPU 内存之间的内存传输相关的成本。我知道 OpenCL 的目的是让代码可以在 CPU 或 GPU 上运行,只要有 OpenCL SDK 用于其中任何一个,因此如果他/她选择 OpenCL,OP 就不必在 GPU 上运行代码。我只是有一种感觉,虽然这个答案非常详尽,而且比我想象的要深入得多,但并不能完全涵盖整个选项的成本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-11
  • 2011-01-31
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多