代码之家  ›  专栏  ›  技术社区  ›  wangt13

未能使用GNU MIPS内置的向量函数(SIMD)

  •  0
  • wangt13  · 技术社区  · 6 月前

    我正在为MIPS CPU开发一个嵌入式Linux系统(kernel-5.10.24)。现在,我想测试中列出的MIPS SIMD的GNU内置函数 https://gcc.gnu.org/onlinedocs/gcc/MIPS-SIMD-Architecture-Built-in-Functions.html

    我测试过了 v4f32 __builtin_msa_fsqrt_w (v4f32); 如下所述。

    #define _GNU_SOURCE
    #include <msa.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <math.h>
    #include <time.h>
    
    #define ALIGN16 __attribute__((aligned(16)))
    ALIGN16 uint32_t a[] = {64, 128, 256, 512};
    ALIGN16 uint32_t r[] = {64, 128, 256, 512};
    ALIGN16 uint32_t sr[] = {64, 128, 256, 512};
    
    static int verification_test(void)
    {
        int i = 0;
        v4i32 va, fr;
    
        for (i = 0; i < sizeof(a)/sizeof(a[0]); i++) {
            sr[i] = sqrt(a[i]);
        }
        // Get SQRT with MSA builtin functions
        va = __builtin_msa_ld_w(a, 0);
        fr = (v4i32)__builtin_msa_fsqrt_w((v4f32)va);
        __builtin_msa_st_w(fr, r, 0); // Save result in fr to array of r.
    
        for (i = 0; i < sizeof(r)/sizeof(r[0]); i++) {
            printf("%d: %f\n", i, (double)sr[i]);
            printf("%d: %f\n", i, (double)r[i]);
        }
        return 0;
    }
    int main()
    {
        verification_test();
        return 0;
    }
    

    它计算了4个数的平方,但我发现内置函数的结果与从 sqrt() ,如下。

    0: 8.000000
    0: 464848115.000000
    1: 11.000000
    1: 469762048.000000
    2: 16.000000
    2: 473236723.000000
    3: 22.000000
    3: 478150656.000000
    

    那么,我的代码有什么问题,如何修复它?

    根据答案更新代码

    我把台词改成了

    fr = __builtin_msa_ftint_s_w(__builtin_msa_fsqrt_w(__builtin_msa_ffint_s_w(va)));
    

    我得到的结果如下,

    0: 8.000000
    0: 8.000000
    1: 11.000000
    1: 11.000000
    2: 16.000000
    2: 16.000000
    3: 22.000000
    3: 23.000000 <<??
    

    最后一个来自MSA指令,有点来自 sqrt() ,这有道理吗?

    1 回复  |  直到 6 月前
        1
  •  1
  •   Simon Goater    6 月前

    这里有经过教育的猜测,因为我并不真正了解MIPS,但在整数和浮点向量类型之间转换向量类型需要使用适当的内部函数。尝试更改

    (v4i32)__builtin_msa_fsqrt_w((v4f32)va) 
    

    builtin_msa_ftint_u_w(__builtin_msa_fsqrt_w(__builtin_msa_ffint_u_w(va)))
    

    如果你能找到一些文档,你可能应该检查一下它是如何循环的,以确保它符合你的期望。