Pet*_*des 6 c gcc simd clang intrinsics
我如何编写一个可移植的GNU C内置向量版本,它不依赖于x86 set1内在函数?
typedef uint16_t v8su __attribute__((vector_size(16)));
v8su set1_u16_x86(uint16_t scalar) {
return (v8su)_mm_set1_epi16(scalar); // cast needed for gcc
}
Run Code Online (Sandbox Code Playgroud)
当然必须有一个更好的方式
v8su set1_u16(uint16_t s) {
return (v8su){s,s,s,s, s,s,s,s};
}
Run Code Online (Sandbox Code Playgroud)
我不想写一个用于广播单个字节的AVX2版本!
对于你想要分配给变量而不是仅仅使用二元运算符的操作数(这与gcc一起工作,见下文),即使只对gcc-only或clang-only这一部分的答案也会很有趣.
如果我想使用广播标量作为二元运算符的一个操作数,则可以使用gcc(如手册中所述),但不能使用clang:
v8su vecdiv10(v8su v) { return v / 10; } // doesn't compile with clang
Run Code Online (Sandbox Code Playgroud)
有了clang,如果我只针对x86并且只使用本机向量语法来让编译器为我生成模数乘法逆常数和指令,我可以写:
v8su vecdiv_set1(v8su v) {
return v / (v8su)_mm_set1_epi16(10); // gcc needs the cast
}
Run Code Online (Sandbox Code Playgroud)
但是如果我加宽向量(to _mm256_set1_epi16),我必须改变内在,而不是通过改变到vector_size(32)一个地方(对于不需要改组的纯垂直SIMD )将整个代码转换为AVX2 .它也会破坏本机向量的部分目的,因为它不会为ARM或任何非x86目标编译.
丑陋的演员阵容是必需的,因为与clang不同,gcc不v8us {aka __vector(8) short unsigned int}兼容__m128i {aka __vector(2) long long int}.
顺便说一句,所有这些都与gcc和clang编译成好的asm(在Godbolt上看到它). 这只是一个如何优雅地编写的问题,可读语法不会重复标量N次.例如,v / 10它足够紧凑,甚至不需要将它放在自己的功能中.
与ICC有效编译是一个奖励,但不是必需的.GNU C本机向量显然是ICC的事后想法,甚至像这样的简单东西也无法有效编译. set1_u16编译为8个标量存储和向量加载,而不是MOVD/VPBROADCASTW(已-xHOST启用,因为它无法识别-march=haswell,但Godbolt在支持AVX2的服务器上运行).纯粹铸造_mm_内在函数的结果是可以的,但是除法称为SVML函数!
使用两个观察结果可以找到 GCC 和 Clang 的通用广播解决方案
scalar - vector操作。x - 0 = x(但x + 0由于签名零而不起作用)。这是四个浮点数向量的解决方案。
#if defined (__clang__)
typedef float v4sf __attribute__((ext_vector_type(4)));
#else
typedef float v4sf __attribute__ ((vector_size (16)));
#endif
v4sf broadcast4f(float x) {
return x - (v4sf){};
}
Run Code Online (Sandbox Code Playgroud)
相同的通用解决方案可用于不同的向量。这是一个由八个无符号短裤组成的向量的示例。
#if defined (__clang__)
typedef unsigned short v8su __attribute__((ext_vector_type(8)));
#else
typedef unsigned short v8su __attribute__((vector_size(16)));
#endif
v8su broadcast8us(short x) {
return x - (v8su){};
}
Run Code Online (Sandbox Code Playgroud)
ICC (17) 支持 GCC 向量扩展的一个子集,但不支持其中任何vector + scalar一个vector*scalar,因此广播仍然需要内在函数。MSVC 不支持任何向量扩展。
| 归档时间: |
|
| 查看次数: |
597 次 |
| 最近记录: |