immintrin.h的替代方案

7
在c/c++中,immintrin.h提供的显式向量化内嵌函数可以说是一种权宜之计。也就是说,对于每个CPU指令集(如SSE、AVX2、AVX512等)和每种数字类型(即float、double、int等),都有唯一的函数可用于相同的基本操作,例如_mm_add_epi8_mm_add_epi16_mm256_add_epi8_mm256_add_epi16,所有这些函数都是基于基本运算符+。因此,如果您使用AVX内嵌函数编码,当您升级到AVX2时,您需要重新编码,然后再升级到AVX512,以此类推。
另一方面,一些编译器的基本内置运算符(如'+'、'-'等)似乎在所有类型(向量和非向量)上都能很好地工作(前提是数据对齐),并且一些混合类型操作(如下面的代码片段所示)可以实现更好的可读性和可扩展性(使用simd指令集)。
// no need for #include "immintrin.h"

#ifndef __AVX2__
#define SIMD_LEN 16
#else
#define SIMD_LEN 32
#endif

typedef int num_t;

num_t a[N], b[N];

// for any num_t and SIMD_LEN, explicitly vectorize b[n] = 2*a[n] + 4 

typedef num_t    vec_t __attribute__ ((__vector_size__ (SIMD_LEN)));

vec_t *vA = (vec_t*)a;
vec_t *vB = (vec_t*)b;

int nNums = SIMD_LEN/sizeof(num_t);

for (int n=0; n < (N/nNums); n++) 
    vB[n] = 2*vA[n] + 4;

显然,这样的灵活性/可扩展性并不适用于所有操作,但似乎immintrin.h的结构不如它本可以允许自然表达。
为此,是否有一种替代“intrinsic”头文件与immintrin.h家族相比,允许更自然的表达,如上所示?至少有一个涵盖许多通用、可扩展操作,如横向加法、非对齐加载、比较等吗?
至于这个问题的目的,我不感兴趣“只需让编译器矢量化”。那只是回答是否使用内部函数的问题。

2
https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html 部分是 GCC 特有的,但使用起来相当不错。 - EOF
1
GCC向量扩展的一些有趣内容 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68123 - user3528438
我知道内置的向量扩展,就像在https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html中所示。实际上,`immintrin.h`只是基于它们构建的宏和函数。我正在寻找一种替代`immintrin.h`的方法,它基于相同的向量扩展,但使用不同的语法,在从SSE迁移到AVX、AVX2、AVX512或其他时不会出现问题。 - codechimp
2
有的。使用#include "vectorclass.h"。那是用于C++的。 - Z boson
Yeppp! 支持 C 语言。 - Z boson
1个回答

5
使用带有__attribute__ ((__vector_size__...的typedef的主要原因是,它可以产生更容易理解的源代码。
使用immintrin.h的主要原因是,它与编译器的兼容性更好。
您可以通过搜索immintringcc向量扩展的组合来了解每个选项的限制。
无论如何,您的应用程序的其余部分都几乎不会注意到您使用的是哪个选项!:
我建议您尽可能推迟决策,通过将所有内容抽象成一个mathvector类/结构体。它可以首先拥有一个简单的非向量化实现。首先开发应用程序的所有其他部分。然后,您随时可以使mathvector类在未来变为向量化。

1
虽然immintrin.h本身可能不太依赖于特定的编译器,但它非常依赖于CPU和变量类型,这并不是一个好的折衷方案。但无论如何,我并没有提倡使用__attribute__...。事实上,我倾向于不使用它。但是我正在寻找比那个实际上只是一组内联函数和宏定义更好的东西,它通过使用编译器特定的__attribute__...来定义显式矢量化的标准语法。我只是对所谓的“语法”不满意。 - codechimp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接