我试图了解一些关于如何将代码向量化以提高性能的基本知识。
问题: With -O0 I尝试使用OpenMP SIMD指令如下:
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等等?在我(不知情的)自己看来,更准确地了解我的编译器是一个更好的主意。
发布于 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实现(请参阅生成的代码的这里 )。
https://stackoverflow.com/questions/70591015
复制相似问题