如何使用内在函数对 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

fabs(double) 如何在 x86 上实现?这是一项昂贵的手术吗?

用 sse 执行内在函数

c++常用库函数用法总结

iOS 常用的几个math函数

获得两个双精度数组绝对差之和的有效方法