首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法仅使用OpenMP矢量化

无法仅使用OpenMP矢量化
EN

Stack Overflow用户
提问于 2022-01-05 10:06:12
回答 1查看 169关注 0票数 1

我试图了解一些关于如何将代码向量化以提高性能的基本知识。

问题: With -O0 I尝试使用OpenMP SIMD指令如下:

代码语言:javascript
复制
    struct aligned_free
    {
        inline void operator()(double* ptr)
        {
            if (ptr != nullptr)
            {
                std::free(ptr);
            }
        }
    };
    using unique_ptr_aligned_double = std::unique_ptr<double, aligned_free>;
    auto result = unique_ptr_aligned_double(static_cast<double*>(std::aligned_alloc(64, n * sizeof(double))), aligned_free());
    const auto list_a = unique_ptr_aligned_double(static_cast<double*>(std::aligned_alloc(64, n * sizeof(double))), aligned_free());
    const auto list_b = unique_ptr_aligned_double(static_cast<double*>(std::aligned_alloc(64, n * sizeof(double))), aligned_free());
    const auto list_c = unique_ptr_aligned_double(static_cast<double*>(std::aligned_alloc(64, n * sizeof(double))), aligned_free());
    const auto list_d = unique_ptr_aligned_double(static_cast<double*>(std::aligned_alloc(64, n * sizeof(double))), aligned_free());

    auto* r = result.get();
    const auto* a = list_a.get();
    const auto* b = list_b.get();
    const auto* c = list_c.get();
    const auto* d = list_d.get();

    auto k_index = std::size_t{};
    #pragma omp simd safelen(4) linear(k_index:1)
    for (; k_index < n; ++k_index)
    {
        r[k_index] = a[k_index] * b[k_index];
    }

令我失望的是,上面的代码没有矢量化。我在这里错过了什么?我应该手动展开循环还是以其他方式帮助编译器?或者我应该开始使用编译器本质,而不是OpenMP?

侧主题问题:在这样做时,我问自己一个问题:使用编译器标志-O2/O3更好还是更好地手工选择我希望得到的优化,例如-xHost-faggressive-loop-optimizations等等?在我(不知情的)自己看来,更准确地了解我的编译器是一个更好的主意。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-05 17:39:53

在GCC、ICC和Clang上,omp simd影响了auto-vectorization优化步骤(通过向循环提供元信息)。但是,只有在启用优化的情况下,才启用。因此,对于三个编译器来说,使用-O0简单地忽略了语用注释。这是一种预期的行为。这里是您可以从三个编译器获得的结果。

有的编译器在-O2中实现了自动矢量化,有的在-O3 (GCC,可能还有Clang)中实现了自动矢量化。因为-On (与n一起使用整数)只是一组定义良好的优化(它从一个编译器更改到另一个编译器)。您可以指定循环矢量化所需的优化标志(例如,GCC的-ftree-vectorize )。虽然如果您使用一个特定的编译器(更确定和更细粒度的控制),这可能会更好,但这对可移植性并不是很好(对于所有编译器来说,选项并不相同,并且可能在不同版本之间发生变化)。

此外,请注意,您不应该忘记使用-fopenmp-simd的GCC/Clang和-qopenmp-simd的国际商会。这对克郎来说特别重要。还请注意,循环中需要k_index = 0

最后,编译器默认情况下不使用x86/x86-64平台上的AVX、AVX2和AVX-512指令,因为它不是在所有处理器上都可用(而是使用旧的SSE指令)。例如,使用-mavx/-mavx2可以使GCC/Clang生成更宽的SIMD指令(通常速度更快)。如果计划不分发生成的二进制文件或在另一台计算机上执行它们,使用-march=native更好(否则,如果目标机器上不支持指令,生成的二进制文件就会崩溃)。或者,您可以指定一个特定的体系结构,比如-march=skylake。国际商会也有类似的选择/标志。

有了所有这些,Clang、GCC和ICC都能够生成适当的SIMD实现(请参阅生成的代码的这里 )。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70591015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档