Optimization 如何使用ARM NEON优化此代码?

Optimization 如何使用ARM NEON优化此代码?,optimization,arm,neon,Optimization,Arm,Neon,我试图优化一些代码,以尽可能减少执行时间。 代码如下: int shifter=0; // now iterate through all the pairings UINT32_ALIAS* ptr2=(UINT32_ALIAS*)ptr; const BriskShortPair* max=shortPairs_+noShortPairs_; for(BriskShortPair* iter=shortPairs_; iter<max;++it

我试图优化一些代码,以尽可能减少执行时间。 代码如下:

    int shifter=0;

    // now iterate through all the pairings
    UINT32_ALIAS* ptr2=(UINT32_ALIAS*)ptr;
    const BriskShortPair* max=shortPairs_+noShortPairs_;
    for(BriskShortPair* iter=shortPairs_; iter<max;++iter){
        t1=*(_values+iter->i);
        t2=*(_values+iter->j);
        if(t1>t2){
            *ptr2|=((1)<<shifter);

        } // else already initialized with zero
        // take care of the iterators:
        ++shifter;
        if(shifter==32){
            shifter=0;
            ++ptr2;
        }
    }
int移位器=0;
//现在遍历所有配对
UINT32_别名*ptr2=(UINT32_别名*)ptr;
常量BriskShortPair*max=短对+无短对;
用于(BriskShortPair*iter=shortPairs;iteri);
t2=*(_值+iter->j);
如果(t1>t2){

*ptr2 |=((1)EDIT:我最初误解了原始源代码。 这是正确的版本,完全重写。(55个周期/迭代)

虽然不像下面的初始版本那样简单,但NEON可以非常好地处理这一问题,与最初的C实现相比,它带来了令人瞠目结舌的性能提升

通过正确的调整,您可能会获得额外的性能增益(少于50个周期/迭代)。但是可读性将受到严重影响

玩得开心

    AREA    BRISK_ASM_NEON, CODE, READNOLY
    EXPORT  yourFunction
    CODE32

yourFunction    FUNCTION

loop
    pld     [r0, #192]
    vld2.32     {q8, q9}, [r0]!
    vld2.32     {q10, q11}, [r0]!
    pld     [r0, #192]
    vld2.32     {q12, q13}, [r0]!
    vld2.32     {q14, q15}, [r0]!

    vcgt.u32    q8, q8, q9
    vcgt.u32    q9, q10, q11
    vcgt.u32    q10, q12, q13
    vcgt.u32    q11, q14, q15

    pld     [r0, #192]
    vld2.32     {q12, q13}, [r0]!
    vld2.32     {q14, q15}, [r0]!
    pld     [r0, #192]
    vld2.32     {q0, q1}, [r0]!
    vld2.32     {q2, q3}, [r0]!

    vcgt.u32    q12, q12, q13
    vcgt.u32    q13, q14, q15
    vcgt.u32    q14, q0, q1
    vcgt.u32    q15, q2, q3

    vsli.32     q8, q10, #8
    vsli.32     q9, q11, #8
    vsli.32     q8, q12, #16
    vsli.32     q9, q13, #16
    vsli.32     q8, q14, #24
    vsli.32     q9, q15, #24

    vsli.8      d16, d17, #2
    vsli.8      d18, d19, #2
    vsli.8      d16, d18, #4

    vbic.i8     d16, #0xaa
    vshr.u64    d17, d16, #31
    vorr        d16, d16, d17

    vst1.32     {d16[0]}, [r1]!

    subs        r2, r2, #32
    bgt     loop

    bx  lr

    ENDFUNC
    END
=============================================================================

!!!!!!!!!下面的代码无效!!!!!!!! =============================================================================

有霓虹灯是小菜一碟

这是你的“奇迹”:

原型: void yourFunc(无符号整数*pPair,无符号整数*ptr2,无符号整数计数)

AREA BRISK\u ASM\u霓虹灯,代码,就绪
导出你的函数
代码32
你的功能
adr r12,换档操纵台
vpush{q4-q7}
vldmia r12,{q0-q7}
环
vld1.32{q8,q9}[r1]
vorr q10、q8、q0
vorr q11、q9、q1
vld2.32{q12,q13},[r0]!
vld2.32{q14,q15},[r0]!
vcgt.u32 q12、q12、q13
vcgt.u32 q13、q14、q15
vbsl q12、q10、q8
vbsl q13、q11、q9
vst1.32{q12,q13},[r1]!
vld1.32{q8,q9}[r1]
vorr q10、q8、q2
vorr q11、q9、q3
vld2.32{q12,q13},[r0]!
vld2.32{q14,q15},[r0]!
vcgt.u32 q12、q12、q13
vcgt.u32 q13、q14、q15
vbsl q12、q10、q8
vbsl q13、q11、q9
vst1.32{q12,q13},[r1]!
vld1.32{q8,q9}[r1]
vorr q10、q8、q4
vorr q11、q9、q5
vld2.32{q12,q13},[r0]!
vld2.32{q14,q15},[r0]!
vcgt.u32 q12、q12、q13
vcgt.u32 q13、q14、q15
vbsl q12、q10、q8
vbsl q13、q11、q9
vst1.32{q12,q13},[r1]!
vld1.32{q8,q9}[r1]
vorr q10、q8、q6
vorr q11、q9、q7
vld2.32{q12,q13},[r0]!
vld2.32{q14,q15},[r0]!
vcgt.u32 q12、q12、q13
vcgt.u32 q13、q14、q15
vbsl q12、q10、q8
vbsl q13、q11、q9
vst1.32{q12,q13},[r1]!
潜艇r2#32
bgt环路
vpop{q4-q7}
bx-lr
ENDFUNC
换档操纵台

DCD(1我不是在要求代码,我只是想了解是否有办法通过NEON优化原始代码。因为我不是NEON专家,我甚至不知道我所要求的是否可能。如果可能,我将自己实现。我需要的只是一些关于可行性的一般性建议。不再需要上下文/可编译的code,在这一点上,我唯一能建议的是向编译器提示这应该是矢量化的/将从矢量化中受益。有关选项,请参阅。我编辑了答案,添加了更多上下文。从标量代码的外观来看,这当然是可行的,但如果您没有执行任何SIMD程序,则需要处理陡峭的学习曲线我之前已经说过了。看起来你只是在生成一个位数组,它的值取决于两个向量的比较。我建议先看一些霓虹灯的答案。顺便问一下,
iter->I
iter->j
的类型是什么?@PaulR这些类型是int。“看起来您只是在生成一个位数组,其值取决于两个向量的比较。".这正是代码所做的。你认为我可以显著提高性能吗?因为这对我来说不是一件容易的事,我想知道这是否值得。谢谢!我真的很想现在就理解代码,然后再试一次。这些说明有好的手册吗?访问我的博客armneon.blogspot.com除了我自己的教程之外,还有一些链接。@user2696208我在错误解释你的代码时犯了一个严重的错误。我正在用“修订”版本更新我的答案。好的,再次感谢你。这肯定会提高性能。我现在将试着理解代码。1)由两个整数组成的结构在内部只不过是一个大小为2的整数数组,而这种结构的数组又是一个整体的整数数组。简单的类型转换就可以了。如果它包含其他元素,明智的做法是在另一个结构中将它们分开(2)在ARMv7上,缓存线通常由64个字节组成。建议您提前读取三行。由于此函数中的单个迭代相当长,因此提前读取两行而不是三行可能会产生更好的性能(128而不是192)
    AREA    BRISK_ASM_NEON, CODE, READNOLY
    EXPORT  yourFunction
    CODE32

yourFunction    FUNCTION
    adr r12, shifter_table
    vpush   {q4-q7}
    vldmia  r12, {q0-q7}

loop
    vld1.32 {q8, q9}, [r1]
    vorr    q10, q8, q0
    vorr    q11, q9, q1
    vld2.32 {q12, q13}, [r0]!
    vld2.32 {q14, q15}, [r0]!
    vcgt.u32    q12, q12, q13
    vcgt.u32    q13, q14, q15
    vbsl    q12, q10, q8
    vbsl    q13, q11, q9
    vst1.32 {q12, q13}, [r1]!

    vld1.32 {q8, q9}, [r1]
    vorr    q10, q8, q2
    vorr    q11, q9, q3
    vld2.32 {q12, q13}, [r0]!
    vld2.32 {q14, q15}, [r0]!
    vcgt.u32    q12, q12, q13
    vcgt.u32    q13, q14, q15
    vbsl    q12, q10, q8
    vbsl    q13, q11, q9
    vst1.32 {q12, q13}, [r1]!

    vld1.32 {q8, q9}, [r1]
    vorr    q10, q8, q4
    vorr    q11, q9, q5
    vld2.32 {q12, q13}, [r0]!
    vld2.32 {q14, q15}, [r0]!
    vcgt.u32    q12, q12, q13
    vcgt.u32    q13, q14, q15
    vbsl    q12, q10, q8
    vbsl    q13, q11, q9
    vst1.32 {q12, q13}, [r1]!

    vld1.32 {q8, q9}, [r1]
    vorr    q10, q8, q6
    vorr    q11, q9, q7
    vld2.32 {q12, q13}, [r0]!
    vld2.32 {q14, q15}, [r0]!
    vcgt.u32    q12, q12, q13
    vcgt.u32    q13, q14, q15
    vbsl    q12, q10, q8
    vbsl    q13, q11, q9
    vst1.32 {q12, q13}, [r1]!

    subs    r2, #32
    bgt loop

    vpop    {q4-q7}
    bx  lr

    ENDFUNC

shifter_table
    DCD (1<<00), (1<<01), (1<<02), (1<<03), (1<<04), (1<<05), (1<<06), (1<<07), (1<<08), (1<<09), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15)
    DCD (1<<16), (1<<17), (1<<18), (1<<19), (1<<20), (1<<21), (1<<22), (1<<23), (1<<24), (1<<25), (1<<26), (1<<27), (1<<28), (1<<29), (1<<30), (1<<31)

    END