首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >确定__m256值在SIMD车道上的最小值

确定__m256值在SIMD车道上的最小值
EN

Stack Overflow用户
提问于 2017-04-07 00:16:18
回答 1查看 896关注 0票数 4

我知道,一般情况下,应避免跨SIMD车道作业。然而,有时必须这样做。

我使用的是AVX2本质,在一个__m256中有8个浮点值。

我想知道这个向量中的最低值,并使问题复杂化:这也是在哪个位置。

我目前的解决方案是往返记忆,但我不喜欢这样:

代码语言:javascript
运行
复制
float closestvals[8];
_mm256_store_ps( closestvals, closest8 );

float closest  = closestvals[0];
int closestidx = 0;
for ( int k=1; k<8; ++k )
{
    if ( closestvals[k] < closest )
    {
        closest = closestvals[ k ];
        closestidx = k;
    }
}

在没有记忆的情况下,怎样才能做到这一点呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-07 06:58:29

你可以试试这个:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <x86intrin.h>
#include <math.h>
/*  gcc -O3 -Wall -m64 -march=haswell hor_min.c   */
int print_vec_ps(__m256 x);

int main() {
    float x[8]={1.2f, 3.6f, 2.1f, 9.4f,   4.0f, 0.1f, 8.9f, 3.3f};

    /* Note that the results are not useful if one of the inputs is a 'not a number'. The input below leads to indx = 32 (!)     */
//    float x[8]={1.2f, 3.6f, 2.1f, NAN,  4.0f, 2.0f , 8.9f, 3.3f};

    __m256 v0    = _mm256_load_ps(x);                /* _mm256_shuffle_ps instead of _mm256_permute_ps is also possible, see Peter Cordes' comments */
    __m256 v1    = _mm256_permute_ps(v0,0b10110001); /* swap floats: 0<->1, 2<->3, 4<->5, 6<->7                         */    
    __m256 v2    = _mm256_min_ps(v0,v1);
    __m256 v3    = _mm256_permute_ps(v2,0b01001110); /* swap floats                                                     */    
    __m256 v4    = _mm256_min_ps(v2,v3);
    __m256 v5    = _mm256_castpd_ps(_mm256_permute4x64_pd(_mm256_castps_pd(v4),0b01001110)); /* swap 128-bit lanes      */
    __m256 v_min = _mm256_min_ps(v4,v5);
    __m256 mask  = _mm256_cmp_ps(v0,v_min,0);
    int    indx  = _tzcnt_u32(_mm256_movemask_ps(mask));


   printf("             7      6      5      4      3      2      1      0\n");
   printf("v0     = ");print_vec_ps(v0    );
   printf("v1     = ");print_vec_ps(v1    );
   printf("v2     = ");print_vec_ps(v2    );
   printf("\nv3     = ");print_vec_ps(v3    );
   printf("v4     = ");print_vec_ps(v4    );
   printf("\nv5     = ");print_vec_ps(v5    );
   printf("v_min  = ");print_vec_ps(v_min );
   printf("mask   = ");print_vec_ps(mask  );
   printf("indx   = ");printf("%d\n",indx);

   return 0;
}


int print_vec_ps(__m256 x){
   float v[8];
   _mm256_storeu_ps(v,x);
   printf("%5.2f  %5.2f  %5.2f  %5.2f  %5.2f  %5.2f  %5.2f  %5.2f\n",
          v[7],v[6],v[5],v[4],v[3],v[2],v[1],v[0]);
   return 0;
}

输出:

代码语言:javascript
运行
复制
./a.out
             7      6      5      4      3      2      1      0
v0     =  3.30   8.90   0.10   4.00   9.40   2.10   3.60   1.20
v1     =  8.90   3.30   4.00   0.10   2.10   9.40   1.20   3.60
v2     =  3.30   3.30   0.10   0.10   2.10   2.10   1.20   1.20

v3     =  0.10   0.10   3.30   3.30   1.20   1.20   2.10   2.10
v4     =  0.10   0.10   0.10   0.10   1.20   1.20   1.20   1.20

v5     =  1.20   1.20   1.20   1.20   0.10   0.10   0.10   0.10
v_min  =  0.10   0.10   0.10   0.10   0.10   0.10   0.10   0.10
mask   =  0.00   0.00   -nan   0.00   0.00   0.00   0.00   0.00
indx   = 5

在这个答案的前一个版本中,128位通道与_mm256_permute2f128_ps交换.在这个更新的答案中,_mm256_permute2f128_ps_mm256_permute4x64_pd取代,后者在AMD和Intel上速度更快,参见@Peter的评论。但是请注意,_mm256_permute4x64_pd需要AVX2,而AVX则足够_mm256_permute2f128_ps

还请注意,如果输入值之一是‘非数字’(NAN),则此代码的结果是无用的。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43267745

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档