通过计算复制 C 数组的更快方法

Posted

技术标签:

【中文标题】通过计算复制 C 数组的更快方法【英文标题】:Faster way to copy C array with calculation between 【发布时间】:2014-12-18 19:17:20 【问题描述】:

我想将一个 C 数组数据复制到另一个,但需要在两者之间进行计算(即不仅仅是将相同的内容从一个复制到另一个,而是对数据进行修改):

int aaa;
int src[ARRAY_SIZE];
int dest[ARRAY_SIZE];

//fill src with data

for (aaa = 0; aaa < ARRAY_SIZE; aaa++)

    dest[aaa] = src[aaa] * 30;

这是在大小为 520 或更大的缓冲区中完成的,因此 for 循环相当可观。

有什么方法可以提高编码方面的性能吗?

我对该主题进行了一些研究,但我找不到关于这个案例的任何具体内容,只有简单的缓冲区复制到缓冲区(例如:here、here 和 here)。

环境:使用嵌入式 Linux 的 ARM GCC。不过,上面的特定代码用于在专用处理器内运行的 C 项目中,用于 DSP 计算。通用处理器是 OMAP L138(DSP 处理器包含在 L138 中)。

【问题讨论】:

OpenMP/线程可以加速它的因素。 对于这样一个简单的情况,任何半体面的编译器都应该为您优化它。它将展开循环并使用 SIMD。除此之外是核心级别的并行化。例如上面提到的 OpenMP。 @EugeneSh。这是一个简单的复制和乘法循环。我认为 Duff 的设备只会混淆编译器,并减慢实际执行速度。 如果 ARRAY_SIZE 是固定的,您可以尝试手动展开循环。我假设你已经在编译器中打开了优化。 有很多可能的优化,具有不同程度的可移植性(例如 SIMD 可能是一个选项)和复杂性(尽管使用多核不太可能为 520 个整数带来回报)。有些,比如简单的展开,编译器可能会为你做。然而,对所有平台/编译器组合上所有可能的优化的调查过于广泛。如果你有一个实际的性能问题,也许你可以描述你的约束、平台和编译器。 【参考方案1】:

您可以尝试诸如循环展开或 duff 的设备之类的技术,但如果您打开编译器优化,它可能会在任何情况下为您做到这一点,如果这样做是有利的,而且不会使您的代码不可读。

依赖编译器优化的优势在于它是特定于架构的;适用于一个目标的源级技术在另一个目标上可能效果不佳,但编译器生成的优化将特定于目标。例如,没有办法专门为 C 中的 SIMD 指令编写代码,但编译器可能会生成代码来利用它们,为此,最好保持代码简单直接,以便编译器能够识别成语.编写奇怪的代码来“手动优化”可能会破坏优化器并阻止它完成工作。

另一种可能对某些目标有利的可能性(如果您只为桌面 x86 目标编码,这可能无关紧要)是通过使用移位来避免乘法指令:

鉴于x * 30等价于x * 32 - x * 2,循环中的表达式可以替换为:

input[aaa] = (output[aaa] << 5) - (output[aaa] << 1) ;

但优化器可能会再次为您做到这一点;它也将避免重复评估output[aaa],但如果不是这样,以下可能是有益的:

int i = output[aaa] ;
input[aaa] = (i << 5) - (i << 1) ;

移位技术可能对除法运算更有利,因为在大多数目标上成本要高得多,并且它仅适用于常量

这些技术可能会提高未优化代码的性能,但编译器优化可能会做得更好,并且原始代码可能会比“手动优化”的代码优化得更好。

最后,如果它很重要,您必须进行实验并执行时序测试或分析。

【讨论】:

以上是关于通过计算复制 C 数组的更快方法的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中复制数组的任何更快的方法?

在C中创建一个没有重复的新数组

如何通过Angular JS计算数组中过滤的数据? [复制]

如何在C中“通过引用”传递数组? [复制]

为啥数组在通过其他更改数组的方法时打印不同? [复制]

有没有更快的方法来达到相同的结果? [复制]