Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用ARM指令查找数组的最小值和最大值_Arm_Neon - Fatal编程技术网

使用ARM指令查找数组的最小值和最大值

使用ARM指令查找数组的最小值和最大值,arm,neon,Arm,Neon,我有下面的代码,我想使用ARM NEON指令对其进行优化。我如何实现它? 谢谢你的回答 unsigned char someVector[] = {1, 2, 4, 1, 2, 0, 8, 100}; unsigned char maxVal = 0, minVal = 255; for (int i = 0; i < sizeof(someVector); i++) { if (someVector[i] < minVal) { minVal = s

我有下面的代码,我想使用ARM NEON指令对其进行优化。我如何实现它? 谢谢你的回答

unsigned char someVector[] = {1, 2, 4, 1, 2, 0, 8, 100};
unsigned char maxVal = 0, minVal = 255;
for (int i = 0; i < sizeof(someVector); i++)
{
    if (someVector[i] < minVal)
    {
        minVal = someVector[i];
    }
    else if (someVector[i] > maxVal)
    {
        maxVal = someVector[i];
    }
}
unsigned char someVector[]={1,2,4,1,2,0,8,100};
无符号字符maxVal=0,minVal=255;
对于(int i=0;imaxVal)
{
maxVal=someVector[i];
}
}

下面是一个高度优化的示例,介绍如何在大型数组中查找最小值和最大值。如果大小小于128,则函数仅返回:

/*
 * minmax.S
 *
 *  Created on: 2014. 10. 29.
 *      Author: Jake Lee
 */


// unsigned int minmax(unsigned char *pSrc, unsigned int size);

    .text
    .arm
    .global minmax

    pSrc    .req    r0
    size    .req    r1

    qmin1   .req    q0
        dmina   .req    d0
        dminb   .req    d1

    qmax1   .req    q1
        dmaxa   .req    d2
        dmaxb   .req    d3

    qmin2   .req    q2
    qmax2   .req    q3

    .align 5
    .func
minmax:
    subs    size, size, #128
    bxmi    lr
    vmov.i8     qmin1, #0xff
    vmov.i8     qmax1, #0
    vmov.i8     qmin2, #0xff
    vmov.i8     qmax2, #0

    .align 5
1:
    vld1.8      {q8, q9}, [pSrc]!
    vld1.8      {q10, q11}, [pSrc]!
    vld1.8      {q12, q13}, [pSrc]!
    vld1.8      {q14, q15}, [pSrc]!
    subs    size, size, #128
    pld     [pSrc, #64*3]
    pld     [pSrc, #64*4]
    vmin.u8     qmin1, q8
    vmax.u8     qmax1, q8
    vmin.u8     qmin2, q9
    vmax.u8     qmax2, q9
    vmin.u8     qmin1, q10
    vmax.u8     qmax1, q10
    vmin.u8     qmin2, q11
    vmax.u8     qmax2, q11
    vmin.u8     qmin1, q12
    vmax.u8     qmax1, q12
    vmin.u8     qmin2, q13
    vmax.u8     qmax2, q13
    vmin.u8     qmin1, q14
    vmax.u8     qmax1, q14
    vmin.u8     qmin2, q15
    vmax.u8     qmax2, q15
    bpl     1b

// deal width residuals (size % 128)
    cmp     size, #-128
    addgt   pSrc, pSrc, size
    bgt     1b

// shrink to sixteen
    vmin.u8     qmin1, qmin2
    vmax.u8     qmax1, qmax2
// shrink to eight
    vpmin.u8    dmina, dmina, dminb
    vpmax.u8    dmaxa, dmaxa, dmaxb
// shrink to four
    vpmin.u8    dmina, dmina, dminb
    vpmax.u8    dmaxa, dmaxa, dmaxb
// shrink to two
    vpmin.u8    dmina, dmina, dminb
    vpmax.u8    dmaxa, dmaxa, dmaxb
// shrink to one
    vpmin.u8    dmina, dmina, dminb
    vpmax.u8    dmaxa, dmaxa, dmaxb

    vmov    r0, dmina[0]
    vmov    r1, dmaxa[0]

    and     r0, r0, #0xff
    and     r1, r1, #0xff
    orr     r0, r0, r1, lsl #16
    bx      lr
    .endfunc
    .end
返回值为无符号整数。低16位包含最小值,高16位包含最大值:

result = minmax(pSrc, size);
min = result & 0xff;
max = result >> 16;

GCC将自动对其进行矢量化,只需稍加修改

unsigned char someVector[256] = { 1, 2, 4, 1, 2, 0, 8, 100 };
unsigned char maxVal = 0, minVal = 255;

void f(void)
{
    unsigned char mn = 255, mx = 0;
    for (int i = 0; i < sizeof(someVector); i++) {
        if (someVector[i] < mn) {
            mn = someVector[i];
        }
        if (someVector[i] > mx) {
            mx = someVector[i];
        }
    }
    maxVal = mx;
    minVal = mn;
}


如果您编写NEON Intrinsic或assembler,您可以比GCC做得更好。

您可以在infocenter.arm.com下载组装手册。然后您可以查看说明“vmin”和“vmax”,谢谢您的评论。我知道vmin和vmax,但它们在两个寄存器中比较每个通道。然后我将有8个值的最小值和最大值成对,但不是所有的值,剩下的将是三个连续的vpmin和vpmax。但是,最好使用ARM integer core执行此操作,因为指令延迟将严重削弱性能。NEON一开始并不打算处理这么小的数据。谢谢Jake。实际上我的数组是图像,someVector只是一个例子,很抱歉混淆了。因此,阵列要长得多。对于一个图像,你会在8像素的基础上调用vmin和vmax,最后调用三次vpmin和vpmax吗?我的代码一次调用16字节。(q寄存器),每次迭代执行128字节。看起来您正试图让它与intrinsic一起工作,但速度甚至不及上述汇编版本的一半。@Jake'Alquimista'LEE为什么您的PLD+64*3和+64*4?“pSrc”不是下一个要加载的地址吗?为什么不预加载pSrc本身呢?我可以连续使用两个不同寄存器的pld来提高速度吗?这里没有任何有用的文档。谢谢查尔斯,不幸的是我和WinCE工作,而不是GCC。@ Zoli认为自己是幸运的:MS的ARM编译器比GCC更好。
$ arm-unknown-linux-gnueabihf-gcc -O3 -std=c11 -mfpu=neon -c test.c
$ arm-unknown-linux-gnueabihf-gcc -O2 -ftree-vectorize -std=c11 -mfpu=neon -c test.c