c++ - 我们是否需要在 C++ 中进行矢量化,或者 for 循环是否已经足够快?

标签 c++ optimization vectorization

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

% 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++ 中对 for 循环进行矢量化还是它们已经足够快了?也许编译器会自动矢量化它们?实际上,我不知道 Matlab 类型向量化是否是 C++ 中的一个概念,也许它只是 Matlab 需要的,因为这是一种解释型语言?您将如何用 C++ 编写上述函数以使其尽可能高效?

最佳答案

Do we need vectorization in C++


不一定总是需要矢量化,但它可以使某些程序更快。
C++ 编译器支持自动矢量化,但如果您需要矢量化,那么您可能无法依赖这种优化,因为并非每个循环都可以自动矢量化。

are [loops] already fast enough?


取决于循环、 objective-c PU、编译器及其选项,而且至关重要的是:它需要多快。

您可以做一些事情来潜在地在标准 C++ 中实现矢量化:
  • 启用执行自动矢量化的编译器优化。 (请参阅您的编译器手册)
  • 指定在其指令集中具有 vector 操作的 objective-c PU。 (请参阅您的编译器手册)
  • 使用标准算法 std::parallel_unsequenced_policystd::unsequenced_policy .
  • 确保正在操作的数据与 SIMD 指令充分对齐。您可以使用 alignas .请参阅 objective-c PU 的手册以了解您需要的对齐方式。
  • 通过使用链接时间优化,确保优化器尽可能多地了解。
  • 部分展开您的循环。这样做的限制是您对并行化数量进行了硬编码:

  • for (int i = 0; i < count; i += 4) {
        operation(i + 0);
        operation(i + 1);
        operation(i + 2);
        operation(i + 3);
    }
    

    在标准的、可移植的 C++ 之外,还有具体的实现方式:
  • 一些 compilers提供语言扩展来编写明确的矢量化程序。这可以跨不同的 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; */
    

  • 一些 compilers提供“内置”函数来调用可用于调用 SIMD vector 指令的特定 CPU 指令。使用这些在不兼容的 CPU 之间是不可移植的。
  • 一些 compilers支持 OpenMP具有 #pragma omp simd 的 API .
  • 关于c++ - 我们是否需要在 C++ 中进行矢量化,或者 for 循环是否已经足够快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66100349/

    相关文章:

    c++ - 工厂方法创建 shared_ptr 对象

    c++ - C++中的圆括号明显语法错误但编译器没有提示

    java - 寻找一种更快的方法来执行字符串搜索

    c++ - 具有数组分配的编译器的不同行为

    python - 使用 Numpy 逐元素矩阵的阶乘

    c++ - 为什么类的静态成员函数没有 "const-correctness"的概念?

    c++ - std::vector、成员访问运算符和 EXC_BAD_ACCESS

    c - 获得一个数字的所有倍数的更快方法?

    java - 如何在 Java 中不简单地使用 for 循环来执行 n 个数组的按元素加法

    matlab - 没有 "for loop"的normrnd()和norm()操作