【问题标题】:Fastest way to multiply and add to an int array in C by an int?在 C 中用 int 乘以和添加到 int 数组的最快方法?
【发布时间】:2015-05-18 14:35:58
【问题描述】:

在用 C 编程时,我正在学习一些关于 pthread 和性能的知识,我想知道最好的方法是将单个 int 添加到数组中的所有元素(相当大的一个,大约 5000元素)以及将int 与数组中的所有元素相乘的最佳方法。

我尝试并行执行此操作,但没有太大改进。我的并行方法是传递一个struct,其中包含要相加/相乘的值以及指向数组的指针。我将此作为参数传递给pthread_create。在被调用的函数中,我将给定值添加/乘以数组中的所有元素。

我觉得好像有一种更好的方法可以将单个数字相乘或相加到数组中的所有 5000 个(或更多)元素。我也听说过那些 SIMD 命令。在这种情况下这可能会有所帮助吗?

【问题讨论】:

  • 5000 个元素对于简单的加法操作来说并没有那么多数据。
  • 确实,创建和删除线程所需的开销时间可能会消耗通过并行计算获得的任何性能。我会尽可能简单地编写这段代码,然后摆弄编译器优化设置。

标签: c arrays parallel-processing pthreads


【解决方案1】:

如果您可以假设使用 x86 CPU,那么您可以使用 Intel 的 SSE SIMD 扩展来一次处理 4 个元素。

例如为数组的所有元素添加一个值:

#include "emmintrin.h"

// ...

const __m128i vinc = _mm_set1_epi32(inc);  // init vector containing value to add
for (int i = 0; i < N; i += 4)
{
    __m128i v = _mm_loadu_si128(&a[i]);    // load 4 elements from array a
    v = _mm_add_epi32(v, vinc);            // add increment to each element
    _mm_storeu_si128(&a[i], v);            // save 4 modified elements back to a
}

在较新的 CPU 上,例如Haswell,您可以使用 AVX2 以类似的方式每次迭代处理 8 个元素。

请注意,一些编译器已经为您将此代码向量化,例如gcc、clang、ICC,甚至是最新版本的 Visual Studio(在美好的一天),因此您甚至可能不需要使用 SSE 内部函数显式编写代码。

还有一些优化的库可以为您执行诸如此类的操作,例如Intel 的 IPP 或 Apple 的 Accelerate 框架,以及许多其他开源库。

关于过早优化的常见警告当然适用:您应该首先对现有代码进行基准测试,并确定它是性能瓶颈,然后再尝试对其进行优化。

【讨论】:

  • 不应该是vincconst
  • @unwind:是的,它可能应该是 - 我实际上出于美观原因(线宽)省略了const,但我想如果它存在的话,它的意图会稍微清楚一些。
【解决方案2】:

您必须使用分而治之的方法拆分数组。创建多个线程并为每个线程分配数组的一部分。 所以创建 5 个线程并给线程元素 0..999 1000..1999 ...

你必须使用多个线程来解决你的问题,否则不会有性能提升。

附带说明:在我看来,该数组太小,无法显示多线程实现相对于直接实现的任何改进。

【讨论】:

  • 如果数组太小而无法显示线程的改进(确实如此),你为什么要告诉提问者他们“必须使用多个线程来解决 [他们的] 问题”?跨度>
  • 他说他正在学习多线程......所以我猜问题是教科书而不是现实世界
猜你喜欢
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 2016-12-28
相关资源
最近更新 更多