10

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

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

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

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

4

1 回答 1

7

你的出发点应该是好旧的memcpy。来自长期痴迷于“复制性能”的人的一些提示。

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

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

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

于 2012-12-23T23:25:32.107 回答