Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GCC C向量扩展:如何检查任何元素级比较的结果是否为真,以及哪个为真?_C_Gcc_Comparison_Vectorization_Simd - Fatal编程技术网

GCC C向量扩展:如何检查任何元素级比较的结果是否为真,以及哪个为真?

GCC C向量扩展:如何检查任何元素级比较的结果是否为真,以及哪个为真?,c,gcc,comparison,vectorization,simd,C,Gcc,Comparison,Vectorization,Simd,我不熟悉GCC的C向量扩展。根据该手册,将一个向量与另一个向量进行比较(test=vec1>vec2;)的结果是,“test”在每个元素中包含一个0表示为假,在每个元素中包含一个-1表示为真 但是如何快速检查元素比较是否正确呢?此外,如何判断哪一个元素是第一个比较正确的元素 例如,使用: vec1 = {1,1,3,1}; vec2 = {1,2,2,2}; test = vec1 > vec2; 我想确定“test”是否包含任何真值(非零元素)。在本例中,我希望“test”减少为tru

我不熟悉GCC的C向量扩展。根据该手册,将一个向量与另一个向量进行比较(test=vec1>vec2;)的结果是,“test”在每个元素中包含一个0表示为假,在每个元素中包含一个-1表示为真

但是如何快速检查元素比较是否正确呢?此外,如何判断哪一个元素是第一个比较正确的元素

例如,使用:

vec1 = {1,1,3,1};
vec2 = {1,2,2,2};
test = vec1 > vec2;
我想确定“test”是否包含任何真值(非零元素)。在本例中,我希望“test”减少为true,因为存在一个vec1大于vec2的元素,因此test中的一个元素包含-1

另外,或者,我想快速发现哪个元素没有通过测试。在这种情况下,这只是数字2。换句话说,我想测试哪一个是第一个非零元素

int hasAnyTruth = ...; // should be non-zero. "bool" works too since C99
int whichTrue = ...; // should contain 2, because test[2] == -1
我想我们可以使用simd reduce addition命令(?)将向量中的所有内容求和为一个数字,并将其与0进行比较,但我不知道如何(或者是否有更快的方法)。我猜对于第二个问题,某种形式的argmax是必要的,但我也不知道如何指示GCC在向量上使用它

来自神秘:

\u mm\u movemask\u epi8()


它比GCC向量扩展更具可移植性。它是由英特尔标准化的,所以它将在每一个主要的编译器中工作:GCC、Clang、MSVC、ICC等


为此,我们可以使用内部函数,通过使用内部函数,我们可以提高代码的执行速度。

Clang的向量扩展对
任意
函数进行了一次修改

#if defined(__clang__)
typedef int64_t vli __attribute__ ((ext_vector_type(VLI_SIZE)));
typedef double  vdf __attribute__ ((ext_vector_type(VDF_SIZE)));
#else
typedef int32_t vsi __attribute__ ((vector_size (SIMD_SIZE)));
typedef int64_t vli __attribute__ ((vector_size (SIMD_SIZE)));
#endif

static bool any(vli const & x) {
  for(int i=0; i<VLI_SIZE; i++) if(x[i]) return true;
  return false;
}
虽然
pmovmskb
可能仍然是一个更好的选择
ptest
仍然比GCC有很大的改进

any(long __vector(4) const&):
  cmp QWORD PTR [rdi], 0
  jne .L5
  cmp QWORD PTR [rdi+8], 0
  jne .L5
  cmp QWORD PTR [rdi+16], 0
  jne .L5
  cmp QWORD PTR [rdi+24], 0
  setne al
  ret
.L5:
  mov eax, 1
  ret
GCC应该解决这个问题。叮当声很响


我想说的是一个关键的向量函数,因此编译器应该要么像对shuffle那样提供一个内置函数(例如,对于GCC来说是
\uuuuubuiltin\ushuffle
,对于clang来说是
\uubuiltin\ushufflevector
)或者,编译器应该足够聪明,能够像Clang那样找出最佳代码,至少对SSE和AVX是这样,但对AVX512不是这样。

以下是我在一个例子中使用的:

#define V_EQ(v1, v2) \
  ({ \
    __typeof__ (v1) v_d = (v1) != (v2); \
    __typeof__ (v_d) v_0 = { 0 }; \
    memcmp (&v_d, &v_0, sizeof v_d) == 0; \
  })

assert (V_EQ (v4ldblo, v4ldbli - 1));

\u mm\u movemask\u epi8()
哇,我喜欢这个。1) 它是便携式的吗?2) 与memcmp相比有什么优势吗?3) 它是否适用于256位寄存器(AVX)或具有不同元素数的向量?它比GCC向量扩展更具可移植性。它是由英特尔标准化的,所以它将在每一个主要的编译器中工作:GCC、Clang、MSVC、ICC等。。。x86上有这样一条指令:
ptest
。我怀疑在具有(至少)sse4_1的x86上实现
memcmp()
的最快方法将使用
ptest
。如果您想在gcc中使用它,它可以在x86微体系结构上使用,这些微体系结构支持它作为
\uuuuu builtin\u ia32\u ptestc128/ptestnzc128/ptestz128/256
。例如,这在ARM上是无用的。@Zboson我有点不得不求助于Mysticial,因为我最终只是在社区发布了他对这个问题的评论,作为对后代的回答,因为这个问题原本有很长一段时间没有答案,似乎是通过评论解决的——绝对不是硬件便携的。+1当你第一次访问时,我的选票用完了回答得很好!很抱歉,在从评论中复制Mysticial的答案之前,我在社区发布了一篇文章。那是在我全力以赴试图缓和和保护“网站后代”的时候。我会删除它,除非我不能,直到答案被切换。
#define V_EQ(v1, v2) \
  ({ \
    __typeof__ (v1) v_d = (v1) != (v2); \
    __typeof__ (v_d) v_0 = { 0 }; \
    memcmp (&v_d, &v_0, sizeof v_d) == 0; \
  })

assert (V_EQ (v4ldblo, v4ldbli - 1));