使用 constexpr 函数(而不是文字)构建 GCC SIMD 向量常量
Building GCC SIMD vector constants using constexpr functions (rather than literals)
我正在使用 GCC's vector extensions (__attribute__((vector_size(x)))
) 编写一段代码,需要几个常量掩码。这些掩码非常简单,可以按顺序填写,但将它们添加为向量文字既乏味又容易出错,更不用说限制向量大小的潜在变化了。
是否可以使用 constexpr 函数生成常量?
我试过生成这样的值:
using u8v = uint8_t __attribute__((vector_size(64)));
auto generate_mask = []() constexpr {
u8v ret;
for (size_t i = 0; i < sizeof(u8v); ++i) {
ret[i] = i & 0xff;
}
return ret;
};
constexpr auto mask = generate_mask();
但是 GCC 说 u8v
的修改不是常量表达式。
使用具有 C++20 功能的 G++ 是否有一些解决方法?
技术上可行,但复杂到无法使用的地步。 与 SIMD 无关。
不过,变通办法还不错。
SIMD 向量无论如何都不能嵌入到指令流中。不管你的代码说 constexpr auto mask
,实际上编译器会生成完整的向量,将数据放在二进制文件的只读段中,并根据需要从那里加载。
例外情况是您的向量生成速度快于 RAM 加载速度。可以使用 vpxor
在没有 RAM 访问的情况下生成全零向量,可以使用 vpcmpeqd
生成所有位设置的向量,并且可以使用广播指令生成所有通道中具有相同值的向量。任何其他内容都会导致从二进制文件加载全向量。
这意味着您可以将 constexpr
替换为 const
,二进制文件将相同。如果该代码在头文件中,理想情况下,在使用 VC++ 构建时,您还需要 __declspec(selectany)
,或者在您的情况下,GCC 的等价物是 __attribute__((weak))
我正在使用 GCC's vector extensions (__attribute__((vector_size(x)))
) 编写一段代码,需要几个常量掩码。这些掩码非常简单,可以按顺序填写,但将它们添加为向量文字既乏味又容易出错,更不用说限制向量大小的潜在变化了。
是否可以使用 constexpr 函数生成常量?
我试过生成这样的值:
using u8v = uint8_t __attribute__((vector_size(64)));
auto generate_mask = []() constexpr {
u8v ret;
for (size_t i = 0; i < sizeof(u8v); ++i) {
ret[i] = i & 0xff;
}
return ret;
};
constexpr auto mask = generate_mask();
但是 GCC 说 u8v
的修改不是常量表达式。
使用具有 C++20 功能的 G++ 是否有一些解决方法?
技术上可行,但复杂到无法使用的地步。
不过,变通办法还不错。
SIMD 向量无论如何都不能嵌入到指令流中。不管你的代码说 constexpr auto mask
,实际上编译器会生成完整的向量,将数据放在二进制文件的只读段中,并根据需要从那里加载。
例外情况是您的向量生成速度快于 RAM 加载速度。可以使用 vpxor
在没有 RAM 访问的情况下生成全零向量,可以使用 vpcmpeqd
生成所有位设置的向量,并且可以使用广播指令生成所有通道中具有相同值的向量。任何其他内容都会导致从二进制文件加载全向量。
这意味着您可以将 constexpr
替换为 const
,二进制文件将相同。如果该代码在头文件中,理想情况下,在使用 VC++ 构建时,您还需要 __declspec(selectany)
,或者在您的情况下,GCC 的等价物是 __attribute__((weak))