我在使用 g++14.2 及之前的版本时遇到问题。
当我使用
g++ -march=native -g
编译程序时,二进制文件仅在具有 AVX 指令集的 Intel CPU 中创建 SIGSEGV。不在我的 ARM64 中,也不在 Core2Duo Intel 中。
当我使用
g++ -g
编译程序时,二进制文件可以在任何平台上正常运行。
当我使用
g++ -march=native -O3
编译程序时,二进制文件可以在任何平台上正常运行(优化代码?)。
SIGSEGV出现的地方,看起来是正确的。它就在从另一个成员函数调用成员函数之前。
SIGSEGV出现的汇编指令是:
=> 0x00007ff6074ea2b3 <+67>: vmovdqa %ymm0,-0x40(%rbp)
但是(rbp-0x40)似乎没有与32字节对齐:
rbp 0x5fec10
我认为这是特定于编译器的。但我尝试将
alignas(32)
应用于我的定义,例如:
alignas(32) band_matrix<const unsigned short*, 10, 2> res2{.....}
但无论如何,
rbp
都没有与 32 字节对齐。
我对我的程序进行了缩小,很多时候都可以工作(可能是当 rbp 正确对齐到 32 字节时),但很多时候会失败(没有输出)
#include <cstdint>
#include <iostream>
template<typename It>
struct container_view
{
typedef typename It::reference reference;
typedef std::remove_reference_t<reference> value_type;
typedef const reference const_reference;
constexpr container_view(It it, size_t s) noexcept : it(it), s(s) {}
constexpr It begin() const noexcept { return it; }
constexpr It end() const noexcept { return it + size(); }
constexpr reference operator[](size_t i) noexcept { return *(it + i); }
/// Size of container.
constexpr size_t size() const noexcept { return s; }
private:
It it;
size_t s;
};
template<typename T, typename S = const size_t>
struct shifted_vector
{
typedef std::remove_reference_t<T> vector_type; ///< The type of vector.
T vec; ///< DenseVector of sequential non-zero elements.
S offset; ///< Offset of first non-zero element.
};
struct band_matrix_jump_iterator
{
typedef short value_type;
typedef short* pointer;
typedef short& reference;
private:
size_t b; // matrix's bandwidth
size_t v; // matrix's column
size_t e; // matrix's column's element's index.
pointer p; // Pointer to current element.
public:
constexpr band_matrix_jump_iterator(pointer p, size_t b, size_t v, size_t e) noexcept
: b{b}, v{v}, e{e}, p{p} {}
constexpr band_matrix_jump_iterator &operator++() noexcept { ++e; ++p; return *this; }
constexpr band_matrix_jump_iterator &operator+=(ptrdiff_t i) noexcept { e += i; p += i; return *this; }
constexpr band_matrix_jump_iterator operator+(ptrdiff_t i) const noexcept
{ band_matrix_jump_iterator t(*this); t += i; return t; }
constexpr reference operator*() const noexcept { return *p; }
constexpr bool operator==(const band_matrix_jump_iterator &it) const noexcept { return e == it.e; }
};
struct band_matrix
{
typedef short value_type;
typedef value_type* pointer;
constexpr size_t columns() const noexcept { return 10; }
size_t b;
pointer elements;
//---------------------------------------------------------------- TYPEDEFS OF ITERATORS AND VECTORS
typedef band_matrix_jump_iterator column_iterator;
typedef shifted_vector<container_view<column_iterator>, const uint8_t> column_vector;
//--------------------------------------------------------------------------- CONSTRUCTORS / ASSIGNS
constexpr band_matrix(size_t b) : b{b}, elements(new value_type[10]) {}
constexpr ~band_matrix() noexcept { delete[] elements; }
//------------------------------------------ GET ROWS, COLUMNS, DIAGONAL AND CORRESPONDING ITERATORS
/// Return a beginning iterator to column \c i vector.
constexpr column_iterator column_begin(size_t i) noexcept
{ return column_iterator(elements + i, 0, i, 0); }
/// Return a vector view of column \c i.
constexpr column_vector column(size_t i) noexcept
{ return {typename column_vector::vector_type{column_begin(i), 1}, (uint8_t) i}; }
};
using namespace std;
int main()
{
band_matrix m(0);
for (size_t i = 0; i < 10; ++i) m.elements[i] = i;
// checking columns
for (size_t i = 0; i < m.columns(); ++i)
{
auto v = m.column(i);
cout << (int) v.offset << ": { ";
for (auto i : v.vec) cout << i << " ";
cout << "}\n";
}
}
这是一个 g++ bug 吗?我的代码(上面)有错误吗? 有什么建议吗? (当然第一个建议就是不要用
-march=native
)
更新
我的 CPU 是 Skylake 2016,我有一台配备 Ryzen 3 的笔记本电脑,并且具有:
-march=sandybridge -g
效果很好-march=native -g
我有SIGSEGV-march=skylake -g
我有SIGSEGV-march=haswell -g
我有SIGSEGV-mavx2 -mfma -mbmi -mbmi2 -mmovbe -mlzcnt -mpopcnt -mrdrnd -mf16c -g
,我认为-模仿-march=haswell -g
,它工作得很好。-g
但没有放置 -O3
SIGSEGV 也会出现,就像 -g
一样,这似乎 -O3
只是优化了一些代码。更新:
用 clang++ 编译效果很好。这可能使它成为一个 g++ bug。
我的 g++(有问题)和 clang++(工作正常!)版本是:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=C:/Program\ Files/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/14.2.0/lto-wrapper.exe
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs_staging_ucrt64/inst_gcc-14.2.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-offload-targets=nvptx-none --with-pkgversion='MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r2' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --disable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --disable-default-ssp --disable-rpath --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++ --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --enable-libstdcxx-time --enable-libstdcxx-pch --with-mpc=/c/Prog/winlibs_staging_ucrt/custombuilt64 --with-mpfr=/c/Prog/winlibs_staging_ucrt/custombuilt64 --with-gmp=/c/Prog/winlibs_staging_ucrt/custombuilt64 --with-isl=/c/Prog/winlibs_staging_ucrt/custombuilt64 --disable-libstdcxx-backtrace --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --enable-clocale=generic --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs_staging_ucrt64/gcc-14.2.0/build_mingw/mingw-w64 CFLAGS='-D__USE_MINGW_ANSI_STDIO=0 -I/c/Prog/winlibs_staging_ucrt/custombuilt64/include/libdl-win32 -march=nocona -msahf -mtune=generic -O2 -Wno-error=format' CXXFLAGS='-D__USE_MINGW_ANSI_STDIO=0 -Wno-int-conversion -march=nocona -msahf -mtune=generic -O2' LDFLAGS='-pthread -Wl,--no-insert-timestamp -Wl,--dynamicbase -Wl,--high-entropy-va -Wl,--nxcompat -Wl,--tsaware' LD=/c/Prog/winlibs_staging_ucrt/custombuilt64/share/binutils/bin/ld.exe
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.2.0 (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r2)
(built by Brecht Sanders, r2) clang version 19.1.1
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: C:/Program Files/mingw64/bin
我认为这是 GCC bug 54412,自 2012 年以来一直突出。它特定于 MinGW。
我在 godbolt 上使用 MinGW GCC 13.1.0 编译器和
-std=c++20 -march=x86-64-v4
复制了这个。 您无法在 godbolt 上执行代码,但在 asm 的第 182 行,您可以看到一个 vmovdqa [rbp-96], ymm0
,没有相关代码来对齐帧指针(ABI 仅保证具有 16 字节对齐)。
错误报告提到了一些可能的解决方法。 其中之一是
-Wa,-muse-unaligned-vector-move
,它应该告诉汇编器将所有对齐的移动指令转换为未对齐的。 另一种方法是更改 container_view
构造函数,以通过 const 引用获取其 it
参数。 或者,当然,-mno-avx2
。