繁体   English   中英

我们需要在 C++ 中进行矢量化,还是 for 循环已经足够快了?

[英]Do we need vectorization in C++ or are for loops already fast enough?

在 Matlab 中,我们使用矢量化来加速代码。 例如,这里有两种执行相同计算的方法:

% Loop
tic
i = 0;
for t = 0:.01:1e5
    i = i + 1;
    y(i) = sin(t);
end
toc

% Vectorization
tic
t = 0:.01:1e5;
y = sin(t);
toc

结果是:

Elapsed time is 1.278207 seconds. % For loop
Elapsed time is 0.099234 seconds. % Vectorization

所以向量化的代码几乎快了 13 倍。 实际上,如果我们再次运行它,我们会得到:

Elapsed time is 0.200800 seconds. % For loop
Elapsed time is 0.103183 seconds. % Vectorization

矢量化代码现在只有 2 倍而不是 13 倍。 所以看起来我们在第一次运行代码时得到了巨大的加速,但在以后的运行中,加速并没有那么大,因为 Matlab 似乎知道 for 循环没有改变并且正在对其进行优化。 在任何情况下,矢量化代码仍然是 for 循环代码的两倍。

现在我已经开始使用 C++ 我想知道这种语言的向量化。 我们是否需要对 C++ 中的循环进行矢量化,还是它们已经足够快了? 也许编译器会自动对它们进行矢量化? 实际上,我不知道 Matlab 类型矢量化是否甚至是 C++ 中的一个概念,也许它只是 Matlab 需要的,因为这是一种解释语言? 您将如何在 C++ 中编写上述 function 以使其尽可能高效?

我们是否需要在 C++ 中进行矢量化

矢量化不一定总是需要,但它可以使一些程序更快。

C++ 编译器支持自动矢量化,但如果您需要矢量化,那么您可能无法依赖这种优化,因为并非每个循环都可以自动矢量化。

[循环] 已经足够快了吗?

取决于循环、目标 CPU、编译器及其选项,关键是:它需要多快。


在标准 C++ 中,您可以采取一些措施来实现矢量化:

  • 启用执行自动矢量化的编译器优化。 (请参阅编译器的手册)
  • 指定在其指令集中具有向量操作的目标 CPU。 (请参阅编译器的手册)
  • 将标准算法与std::parallel_unsequenced_policystd::unsequenced_policy一起使用。
  • 确保正在操作的数据与 SIMD 指令充分对齐。 您可以使用alignas 请参阅目标 CPU 的手册了解您需要的 alignment。
  • 通过使用链接时间优化,确保优化器尽可能多地了解。
  • 部分展开你的循环。 这样做的限制是您对并行化的数量进行硬编码:
 for (int i = 0; i < count; i += 4) { operation(i + 0); operation(i + 1); operation(i + 2); operation(i + 3); }

除了标准的便携式 C++ 之外,还有一些具体的实现方式:

  • 一些编译器提供语言扩展来编写显式矢量化程序。 这可以跨不同的 CPU 移植,但不能移植到未实现扩展的编译器。
 using v4si = int __attribute__ ((vector_size (16))); v4si a, b, c; a = b + 1; /* a = b + {1,1,1,1}; */ a = 2 * b; /* a = {2,2,2,2} * b; */
  • 一些 编译器提供“内置”函数来调用可用于调用 SIMD 矢量指令的特定 CPU 指令。 使用这些不能跨不兼容的 CPU 移植。
  • 一些编译器支持具有#pragma omp simdOpenMP API。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM