首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SSE _mm_dp_ps大小结果

SSE _mm_dp_ps大小结果
EN

Stack Overflow用户
提问于 2020-11-08 10:16:53
回答 1查看 481关注 0票数 0

我开始使用SSE进行操作。我想用_mm_dp_ps制作两个点产品,并在aux_sse中保存第一个结果,在aux_sse中保存第二个结果。B是一个值为1的8元向量.

因为我每对只需要两个浮点数,所以我做了以下代码:

代码语言:javascript
复制
    printf("A  \n");
    for(i = 0; i < M; i++){
        for(j = 0; j < ele; j++){
            A[i*ele+j] = i*ele+j;
            printf(" %f ", A[i*ele+j]);
        }
        printf("\n");
    }
    
    float aux[ele*M];
    float aux2[ele*M];
    __m128 *A_sse = (__m128*) A;
    __m128 *B_sse = (__m128*) B;
    __m128 *aux_sse  = (__m128*) aux;
    __m128 *aux2_sse  = (__m128*) aux2;
    for(int i = 0; i < M; i++)
    {
        *aux_sse =  _mm_dp_ps (*A_sse, *B_sse,  0xFF);
        printf("%f \n", aux[i]);

        B_sse ++;
        A_sse++;
        *aux2_sse = _mm_dp_ps (*A_sse, *B_sse,  0xFF);
        printf("%f \n", aux2[i]);

        B_sse --;
        A_sse ++;

        aux_sse+= sizeof(char);
        aux2_sse+= sizeof(char);
    }

我得到了以下错误的输出:

代码语言:javascript
复制
A  
 0.000000  1.000000  2.000000  3.000000  4.000000  5.000000  6.000000  7.000000 
 8.000000  9.000000  10.000000  11.000000  12.000000  13.000000  14.000000  15.000000 
6.000000 
22.000000 
6.000000 
22.000000 

根据

使用imm8中的高4位,在a和b中有条件地将封装的单精度(32位)浮点元素相乘,将四个积之和相加,并使用imm8的低4位有条件地将和存储在dst中。

我理解在imm8中,我们在元素中指定要保存结果。

据我所知,即使结果在输出向量的4个元素中,如果我只使用aux_sse+= sizeof(char)增加一个元素,则结果应该被覆盖,并得到所需的结果。不过,我看到情况并非如此。

如果在打印aux和aux2的结果时进行以下修改,则输出是正确的。

代码语言:javascript
复制
printf("%f \n", aux[i*4]);
printf("%f \n", aux2[i*4]);

输出:

代码语言:javascript
复制
6.000000 
22.000000 
38.000000 
54.000000 

我正在使用gcc编译器。有人知道问题出在哪里吗?任何答案都会有帮助。

编辑:

我需要aux和aux2的元素对应于每个迭代:

auxi =在迭代1中执行的dot_product

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-08 10:29:09

aux_sse+= sizeof(char);是一种无意义的编写aux_sse+=1的方法,即前进16字节,也就是4个浮点数,即sizeof(__m128) == sizeof(*aux_sse) == 16

所以,如果你也是通过浮点索引访问数组,是的,如果你只对4个浮点数的每一个向量增加一个i,你就必须将它缩放4。

通常,使用_mm_store_ps(&aux[i], v);比跟踪__m128*变量来访问相同的数组更容易。然后执行i+=4,因此i实际上是对您拥有的4元素组的开始进行索引,而不是需要对其进行缩放。这使得编写像i < M-3这样的循环边界变得更容易。

还请注意,如果要对数组进行对齐所需的访问,则应该使用alignas(16) float aux[ele*M];。GCC注意到你在做什么,当数组可以看到它们是如何使用的时候,它会帮你对齐,但是一般不要指望它。

float 还是您只想存储一个结果,而不是为每组4个输入存储4个相同的点产品?在这种情况下,您应该提取低标量元素,例如_mm_store_ss (&aux[i], v)。或者_mm_cvtss_f32(v),将向量的低元素作为标量float

如果您想要这样做,您可以手工完成四个4元素点产品,产生一个向量的4个结果。_mm_mul_ps,然后可能是2x _mm_hadd_ps (SSE3),水平减少,一种转置和加。(由@mainactual建议)

dpps是Skylake和类似的英特尔CPU (https://uops.info)上的4 uop,所以如果你有多个点产品要做的话,那就不太好了。

为了避免SSE3,您可以使用_mm_shuffle_ps (舒夫斯)从两个向量中选择元素,或者一些_mm_unpacklo_ps / unpackhi可能会有用,或者可以使用pd版本来将元素对放在一起。

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

https://stackoverflow.com/questions/64736927

复制
相关文章

相似问题

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