【问题标题】:Efficient way to add two float arrays in C?在 C 中添加两个浮点数组的有效方法?
【发布时间】:2023-03-07 01:57:01
【问题描述】:

我的 macOS 音频应用程序使用 for 循环添加两个浮点数组。当size 很大时,有没有更有效的方法?

int size = 5;
float array1[size] = {0.0, 0.1, 0.2, 0.3, 0.4};
float array2[size] = {0.5, 0.6, 0.7, 0.8, 0.9};
float sum[size];

for (int i = 0; i < size; i ++)
{
    sum[i] = array1[i] + array2[i];
}

【问题讨论】:

  • 你有一个非常奇怪的数组索引,你知道吗?
  • 哎呀,你完全正确。我应该编辑它。在我的应用程序中,我正在处理指针和 memcpy,这就是我采用这种方式的原因。我会编辑它。
  • Here's a discussion on how to optimize this kind of code using SIMD. 底线:您只需要使用正确的编译器选项,然后让优化器完成工作。
  • 这样的优化很大程度上取决于环境。你的目标是什么处理器?程序还围绕这个做什么——它是否对这些相同的数据进行其他操作?数组有多大?现代处理器通常具有快速添加阵列的功能,但如何以及是否使用它们取决于具体情况。非便携式解决方案是否可接受,例如使用英特尔 AVX 指令的解决方案?使用编译器扩展可以吗?你的编译器会自动向量化循环吗?
  • @EricPostpischil 这是专门针对 macOS 的。所以英特尔酷睿 i5 和 i7s。数组大小最大为 524,288。我正在执行的唯一操作是总和。我不确定其他的东西,因为我以前从未深入过。

标签: c performance audio


【解决方案1】:

您可以做的最重要的技巧:如果这些数组实际上是 指针,并且您将它们传递给函数,请确保 restrict-限定总和指针,如果它确实应该指向一个独立于 2 的数组:

void do_sum(size_t size,
            float * restrict sum,
            float * array1,
            float * array2)

或带有尺寸提示

void do_sum(size_t size,
            float sum[restrict static size],
            float array1[static size],
            float array2[static size])

这将使编译器能够生成更高效的代码,因为它保证对于函数中使用的任何 nkarray1[n]array2[n] 都不能访问与 sum[k] 相同的内存

在 Godbolt 上亲自查看差异:with restrictwithout

【讨论】:

    【解决方案2】:

    如果它在功率超过几瓦的硬件上运行(除了没有内置 FPU 且没有知道如何利用 CPU 奇异指令的编译器的十年旧手机之外的任何硬件),效率将取决于内存缓存和总线带宽,所以聪明的 C 技巧并不重要。唯一有意义的加速是覆盖其中一个数组:
    ... array1[i] += array2[i];

    【讨论】:

      【解决方案3】:

      对于 macOS(如评论中所述),解决方案很简单,至少对于单个添加操作。在代码中插入#include &lt;Accelerate/Accelerate.h&gt;,将Accelerate framework 添加到您的项目中,并将循环更改为对vDSP_vadd(sum, 1, array1, 1, array2, 1, size); 的单个调用。它使用 Apple 为其支持的每个平台定制的高性能矢量化例程。

      1 参数是数组的步长,以元素为单位。1 表示处理每个元素,是性能的最佳情况。)

      由于您要处理多达 524,288 个元素,因此您还应该考虑您的应用程序如何与高速缓存交互。高性能设计不能孤立地进行,只能单独查看每个例程。

      【讨论】:

      • 甜蜜。感谢您的提示。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-23
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 2017-05-30
      • 1970-01-01
      相关资源
      最近更新 更多