dsd*_*dsd 5 c x86 simd intrinsics avx
我想通过省略每64位双精度的上半部分,将两个256位向量(__m256d)包含掩码作为比较操作(例如_mm256_cmp_pd)到一个256位向量的结果.
因此,如果在下面,a_i, b_i, ...是32位字,我有两个256位(4 x双)矢量具有以下结构:
a_0, a_0, b_0, b_0, c_0, c_0, d_0, d_0,和a_1, a_1, b_1, b_1, c_1, c_1, d_1, d_1.
我想要一个具有以下结构的256位向量:
a_0, b_0, c_0, d_0, a_1, b_1, c_1, d_1.
如何使用英特尔内在函数有效地完成此操作?可用的指令集是AVX的一切.
看起来您可以利用以下事实:全 1 的位模式NaN在单精度和双精度中都是 a,类似地,全 0 的位模式在这两种情况下都是 0.0。因此,要将两个双掩码向量打包到单个浮点向量中,您可以这样做:
__m256 v = _mm256_set_m128(_mm256_cvtpd_ps(v0), _mm256_cvtpd_ps(v1));
Run Code Online (Sandbox Code Playgroud)
请注意,如果您没有_mm256_set_m128,则可以将其定义为:
#define _mm256_set_m128(va, vb) \
_mm256_insertf128_ps(_mm256_castps128_ps256(vb), va, 1)
Run Code Online (Sandbox Code Playgroud)
这是一个演示:
#include <stdio.h>
#include <immintrin.h>
#define _mm256_set_m128(va, vb) \
_mm256_insertf128_ps(_mm256_castps128_ps256(vb), va, 1)
static void printvd(const char * label, __m256d v)
{
int64_t a[4];
_mm256_storeu_pd((double *)a, v);
printf("%s = %lld %lld %lld %lld\n", label, a[0], a[1], a[2], a[3]);
}
static void printvf(const char * label, __m256 v)
{
int32_t a[8];
_mm256_storeu_ps((float *)a, v);
printf("%s = %d %d %d %d %d %d %d %d\n", label, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
}
int main()
{
__m256d v0 = _mm256_set_pd(0.0, 1.0, 2.0, 3.0);
__m256d v1 = _mm256_set_pd(3.0, 2.0, 1.0, 0.0);
__m256d vcmp0 = _mm256_cmp_pd(v0, v1, 1);
__m256d vcmp1 = _mm256_cmp_pd(v1, v0, 1);
__m256 vcmp = _mm256_set_m128(_mm256_cvtpd_ps(vcmp0), _mm256_cvtpd_ps(vcmp1));
printvd("vcmp0", vcmp0);
printvd("vcmp1", vcmp1);
printvf("vcmp ", vcmp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
测试:
$ gcc -Wall -mavx so_avx_test.c && ./a.out
vcmp0 = 0 0 -1 -1
vcmp1 = -1 -1 0 0
vcmp = -1 -1 0 0 0 0 -1 -1
Run Code Online (Sandbox Code Playgroud)