通过计算复制 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 数组的更快方法的主要内容,如果未能解决你的问题,请参考以下文章