阵列切片的效率

计算科学 矩阵 表现
2021-12-10 03:55:04

我组织了大量数据,以便可以使用数组处理库有效地处理它。但是,有时我只需要处理数组的切片,其中切片可能是由一组选定的索引值定义的任意、非连续子集。

例如

result = someArrayProcess(objects)
result = result(chosenSet)

可能被替换为

result = someArrayProcess(objects(chosenSet),t)

在没有实际运行测试的情况下,有没有办法让我对第二个示例的效率更高或更低有信心?我会在数组包中寻找什么来确定它们是否有效地处理这种切片(不运行基线测试)?到目前为止,我一直使用数组切片作为开发可读和可管理代码的便捷方式,但现在我想将它用于生产,在那里效率将是一个问题。

在我写这篇文章时,我正在处理一些类似的问题。我看到跨步是一种有效访问非连续数组元素的方法。我假设一些数组包会利用这样的方法,而有些则不会。哪些软件包可以最大限度地使用此类方法?

这可能会用 C++ 编码。我对这种语言和其他语言(包括 Python)中的数组包如何处理带有任意子集的切片很感兴趣。

动机

我正在考虑进行一些利用阵列处理的架构修订(并最终将其转移到 GPU 处理中)。目标是使用数组表达式而不是元素级处理来提供架构简化(以便于设计管理)。

由于这将是对当前方法的彻底转变,因此我将不得不解决对效率权衡的担忧。当前的解决方案牺牲了性能的准确性以获得效率,同时由于其复杂的元素而极难管理。考虑到自最初开发以来在处理硬件方面取得的进步,它们现在已经过时了。

我更喜欢设计简化和性能准确性而不是效率,但实时要求也要求我考虑效率。

1个回答

首先,如果没有“实际运行基线测试”,就很难确定地进行。因为你的困境可以总结如下:

可读性和便利性与性能和效率

虽然代码的可读性、便利性和可维护性非常重要,但仍然必须高效地完成繁重的计算并尽可能多地使用计算能力。数组在这方面非常特殊,因为它们连续存储在内存中(按列或按行);因此,如果按照它们存储的顺序访问它们,它可以最大限度地减少缓存未命中的数量,从而提高 CPU 的使用率。此外,向量化指令可以更容易地应用(取决于编译器及其设置)。

现在,随着切片数组的引入,过度使用步幅,肯定会牺牲一些效率。多少钱?取决于数组计算的繁重程度、周围的逻辑、其他代码的基本质量、编译器、CPU、RAM 等。因此,实际的基准测试对于决定如何组织数据流非常重要。

下图(IT Hare)包含更多信息,但您可能会查看 L1-、L2-、L3-、RAM 读取所需时间之间的差异。通过引入对数组的非连续访问,您将增加代码执行 L2 读取而不是 L1 和 L3 而不是 L2 的时间。或者,如果您的数组非常大并且访问是完全随机的,那么每次都会从 RAM 中执行大多数读取,这是非常可怕的。

在此处输入图像描述