如何使用内在函数对 double 执行绝对值? [复制]
Posted
技术标签:
【中文标题】如何使用内在函数对 double 执行绝对值? [复制]【英文标题】:How do I perform absolute value on double using intrinsics? [duplicate] 【发布时间】:2014-08-31 09:23:15 【问题描述】:我们正在尝试创建一个包含不同操作的向量内在库,其中之一是获取数字的绝对值。但是,我的教授将其限制为仅限double
。
我对 x86 内部指令集相当陌生,所以我希望有人能启发我。
这是我目前所拥有的:
void vectorAbs(double *x, double *y, unsigned int N);
int main()
double x[] = -1, -2, -3, -4, -5, -6 ;
double y[] = 2, 2, 2, 2, 2, 2 ;
double *pX = x, *pY = y;
vectorAbs(pX, pY, 6);
void vectorAbs(double *x, double *y, unsigned int N)
__m128d xVar;
__m128d yVar;
printf("\nSquare of x : \n");
for (int i = 0; i < N; i += 2)
xVar = _mm_loadu_pd(&x[i]); // load *x[i] to xVar
yVar = _mm_abs_epi16(xVar); // abs of x
_mm_storeu_pd(&y[i], yVar); // store yVar to y[i]
printf("%lf, %lf, ", y[i], y[i + 1]);
system("pause");
我得到的错误是:
没有操作符“=”匹配这些操作数
操作数类型为:__m128d = __m128i
【问题讨论】:
_mm_abs_epi16
计算16位整数的绝对值
哦,根据我的备忘单,它最多只能处理 32 位整数。但我们需要使用 128 位。这会是个问题吗?因为我的主要问题是如何将我的 double 转换为 int 以便它可以获得绝对值。或者如何获得双精度数的绝对值。
它将 128 位视为 8 个带符号的 16 位整数并计算每个整数的绝对值 - 这绝对不是您想要的。转换为整数显然会丢失大量信息。您可能应该在更基本的操作中自己实现绝对值 - 与零比较,然后如果小于零,则从零取反/减去,等等。
【参考方案1】:
您需要做的就是清除向量中两个双精度值的符号位。每个双精度的符号位位于向量位位置 63 和 127。这可以通过使用内部函数 _mm_and_pd 使用单个指令 (andpd) 来完成。另一种方法是将两个双打逻辑左移一位,然后右移一位。可以使用 _mm_slli_epi64 和 _mm_srli_epi64 内部函数并行移动这两个值。这是一个例子:
#include <stdio.h>
#include <stdlib.h>
#include <intrin.h>
void vectorAbs(double *x, double *y, unsigned int N);
int main()
double x[] = -1, -2, -3, -4, -5, -6 ;
double y[] = 2, 2, 2, 2, 2, 2 ;
double *pX = x, *pY = y;
vectorAbs(pX, pY, 6);
__m128d abs_sample1 (__m128d val)
return _mm_castsi128_pd (_mm_srli_epi64 (_mm_slli_epi64 (_mm_castpd_si128 (val), 1), 1));
__m128d abs_sample2 (__m128d val)
const __m128d mask = _mm_castsi128_pd (_mm_set1_epi64x (0x7FFFFFFFFFFFFFFF));
return _mm_and_pd (mask, val);
void vectorAbs(double *x, double *y, unsigned int N)
__m128d xVar;
__m128d yVar;
printf("\nSquare of x : \n");
for (int i = 0; i < N; i += 2)
xVar = _mm_loadu_pd(&x[i]); // load *x[i] to xVar
yVar = abs_sample1(xVar); // abs of x
_mm_storeu_pd(&y[i], yVar); // store yVar to y[i]
printf("%lf, %lf, ", y[i], y[i + 1]);
system("pause");
【讨论】:
__m128d mask = _mm_castsi128_pd(_mm_setr_epi32(-1,0x7FFFFFFF,-1,0x7FFFFFFF)); yVar = _mm_and_pd(xVar,mask);
以上是关于如何使用内在函数对 double 执行绝对值? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
英特尔 SIMD 内在函数:_mm256_i64scatter_pd