C 对连续的跨步像素阵列重新排序最有效的方法是什么?

C 对连续的跨步像素阵列重新排序最有效的方法是什么?,c,optimization,neon,darknet,C,Optimization,Neon,Darknet,我正在Jetson TX2(带有ARM处理器)上开发一个高性能的关键图像处理管道,该管道涉及读取一组图像,然后通过执行基于深度学习的目标检测。用C编写的Darknet有自己的图像存储方式表示,这与OpenCV的IplImage或Python numpy数组存储图像的方式不同 在我的应用程序中,我需要通过Python与Darknet接口。因此,到目前为止,我正在将一批图像(通常为16)读入一个numpy数组,然后使用ctypes将其作为一个连续数组传递给Darknet。在Darknet中,我必须重

我正在Jetson TX2(带有ARM处理器)上开发一个高性能的关键图像处理管道,该管道涉及读取一组图像,然后通过执行基于深度学习的目标检测。用C编写的Darknet有自己的图像存储方式表示,这与OpenCV的IplImage或Python numpy数组存储图像的方式不同

在我的应用程序中,我需要通过Python与Darknet接口。因此,到目前为止,我正在将一批图像(通常为16)读入一个numpy数组,然后使用ctypes将其作为一个连续数组传递给Darknet。在Darknet中,我必须重新排列像素的顺序,从numpy格式到Darknet格式

虽然输入数组是按列、按行、按通道再按图像排列的一个连续块,但黑暗格式需要先按通道、按列、按行排列:并且在批处理中每个图像包含一行,而不是一个连续块。下面的图片试图说明这种差异。在本例中,我假设一个
ixj
图像。(0,0)、(0,1)等表示(行、列),而在顶部表示C0、C1、C2。。etc表示对应行中的列。请注意,对于作为批处理一部分的多个图像,输入格式将它们依次排列,但Darknet需要它们位于单独的行上:每行仅包含一个图像的数据

到目前为止,我用C编写的将输入数组转换为Darknet格式的代码如下所示,它迭代地命中每个通道中的每个像素,并将其放置在不同的位置,同时还对整个过程中的像素进行规格化

matrix ndarray_to_matrix(unsigned char* src, long* shape, long* strides)
{
int nb = shape[0];    // Batch size
int h = shape[1];     // Height of each image
int w = shape[2];     // Width of each image
int c = shape[3];     // No. of channels in each image
matrix X = make_matrix(nb, h*w*c);     // Output array format: 2D

int step_b = strides[0];
int step_h = strides[1];
int step_w = strides[2];
int step_c = strides[3];

int b, i, j, k;
int index1, index2 = 0;

for(b = 0; b < nb ; ++b) {
    for(i = 0; i < h; ++i) {
        for(k= 0; k < c; ++k) {
            for(j = 0; j < w; ++j) {
                index1 = k*w*h + i*w + j;
                index2 = step_b*b + step_h*i + step_w*j + step_c*k;
                X.vals[b][index1] = src[index2]/255.;
            }
        }
    }
}
return X;
}
矩阵ndarray\u to\u矩阵(无符号字符*src,长*形状,长*步幅)
{
int nb=shape[0];//批量大小
int h=形状[1];//每个图像的高度
int w=形状[2];//每个图像的宽度
int c=形状[3];//每个图像中的通道数
矩阵X=make_矩阵(nb,h*w*c);//输出数组格式:2D
int step_b=步幅[0];
int step_h=步幅[1];
int step_w=步幅[2];
int step_c=步幅[3];
int b,i,j,k;
int index1,index2=0;
对于(b=0;b
有没有更有效的方法在C语言中进行重新排列和规范化?

  • 我正在使用Jetson TX2:它包含一个ARM处理器和一个NVIDIA GPU,因此可以访问NEON和CUDA以及OpenMP
  • 图像尺寸是固定的,可以硬编码:只有批量大小可以更改
下面的功能几乎与
memcpy
一样快:
为了获得最大性能和最小功耗,您可能希望将源指针与32字节对齐,将目标指针与16字节对齐

功能原型为:

void alquimista_ndarray_to_矩阵(uint8_t*pDst,uint8_t*pSrc)


下面是一个函数,它可以动态转换为
float

我添加了批号作为参数,这样就不必对每个图像进行函数调用

/*
 *  Created on: 2018. 5. 5.
 *      Copyright: Jake 'Alquimista' Lee. All rights reserved
 */

    .arch   armv8-a
    .text
    .global alquimista_ndarray_to_matrix_float

// void alquimista_ndarray_to_matrix_float(float *pDst, uint8_t *pSrc, uint32_t batch);

pDst    .req    x0
pRed    .req    x1
batch   .req    w2
pGrn    .req    x3
pBlu    .req    x4
stride  .req    x5
count   .req    w7

.balign 64
.func
alquimista_ndarray_to_matrix_float:
    mov     stride, #((640*360)<<1) & 0xffff
    stp     q8, q15, [sp, #-32]!
    movk    stride, #((640*360)>>15), lsl #16
    mov     count, #(640*360)/32
    add     pGrn, pRed, stride, lsr #1
    add     pBlu, pRed, stride
    b       1f

.balign 64
1:
    ldp     q0, q1, [pRed], #32
    ldp     q2, q3, [pGrn], #32
    ldp     q4, q5, [pBlu], #32

    subs    count, count, #1

    ushll   v20.8h, v0.8b, #7
    ushll2  v23.8h, v0.16b, #7
    ushll   v26.8h, v1.8b, #7
    ushll2  v29.8h, v1.16b, #7
    ushll   v21.8h, v2.8b, #7
    ushll2  v24.8h, v2.16b, #7
    ushll   v27.8h, v3.8b, #7
    ushll2  v30.8h, v3.16b, #7
    ushll   v22.8h, v4.8b, #7
    ushll2  v25.8h, v4.16b, #7
    ushll   v28.8h, v5.8b, #7
    ushll2  v31.8h, v5.16b, #7

    ursra   v20.8h, v20.8h, #8
    ursra   v21.8h, v21.8h, #8
    ursra   v22.8h, v22.8h, #8
    ursra   v23.8h, v23.8h, #8
    ursra   v24.8h, v24.8h, #8
    ursra   v25.8h, v25.8h, #8
    ursra   v26.8h, v26.8h, #8
    ursra   v27.8h, v27.8h, #8
    ursra   v28.8h, v28.8h, #8
    ursra   v29.8h, v29.8h, #8
    ursra   v30.8h, v30.8h, #8
    ursra   v31.8h, v31.8h, #8

    uxtl    v0.4s, v20.4h
    uxtl    v1.4s, v21.4h
    uxtl    v2.4s, v22.4h
    uxtl2   v3.4s, v20.8h
    uxtl2   v4.4s, v21.8h
    uxtl2   v5.4s, v22.8h

    uxtl    v6.4s, v23.4h
    uxtl    v7.4s, v24.4h
    uxtl    v8.4s, v25.4h
    uxtl2   v15.4s, v23.8h
    uxtl2   v16.4s, v24.8h
    uxtl2   v17.4s, v25.8h

    uxtl    v18.4s, v26.4h
    uxtl    v19.4s, v27.4h
    uxtl    v20.4s, v28.4h
    uxtl2   v21.4s, v26.8h
    uxtl2   v22.4s, v27.8h
    uxtl2   v23.4s, v28.8h

    uxtl    v24.4s, v29.4h
    uxtl    v25.4s, v30.4h
    uxtl    v26.4s, v31.4h
    uxtl2   v27.4s, v29.8h
    uxtl2   v28.4s, v30.8h
    uxtl2   v29.4s, v31.8h

    ucvtf   v0.4s, v0.4s, #15
    ucvtf   v1.4s, v1.4s, #15
    ucvtf   v2.4s, v2.4s, #15

    ucvtf   v3.4s, v3.4s, #15
    ucvtf   v4.4s, v4.4s, #15
    ucvtf   v5.4s, v5.4s, #15

    ucvtf   v6.4s, v6.4s, #15
    ucvtf   v7.4s, v7.4s, #15
    ucvtf   v8.4s, v8.4s, #15

    ucvtf   v15.4s, v15.4s, #15
    ucvtf   v16.4s, v16.4s, #15
    ucvtf   v17.4s, v17.4s, #15

    ucvtf   v18.4s, v18.4s, #15
    ucvtf   v19.4s, v19.4s, #15
    ucvtf   v20.4s, v20.4s, #15

    ucvtf   v21.4s, v21.4s, #15
    ucvtf   v22.4s, v22.4s, #15
    ucvtf   v23.4s, v23.4s, #15

    ucvtf   v24.4s, v24.4s, #15
    ucvtf   v25.4s, v25.4s, #15
    ucvtf   v26.4s, v26.4s, #15

    ucvtf   v27.4s, v27.4s, #15
    ucvtf   v28.4s, v28.4s, #15
    ucvtf   v29.4s, v29.4s, #15

    st3     {v0.4s - v2.4s}, [pDst], #48
    st3     {v3.4s - v5.4s}, [pDst], #48
    st3     {v6.4s - v8.4s}, [pDst], #48
    st3     {v15.4s - v17.4s}, [pDst], #48
    st3     {v18.4s - v20.4s}, [pDst], #48
    st3     {v21.4s - v23.4s}, [pDst], #48
    st3     {v24.4s - v26.4s}, [pDst], #48
    st3     {v27.4s - v29.4s}, [pDst], #48
    b.gt    1b

    add     pRed, pRed, stride
    add     pGrn, pGrn, stride
    add     pGrn, pGrn, stride
    subs    batch, batch, #1
    mov     count, #(640*360)/32
    b.gt    1b

.balign 8
    ldp     q8, q15, [sp], #32
    ret
.endfunc
.end
/*
*创建日期:2018年。5.5.
*版权所有:Jake'Alquimista'Lee。版权所有
*/
.拱臂V8-a
.文本
.global alquimista_ndarray_to_matrix_float
//void alquimista_ndarray_to_matrix_float(float*pDst、uint8_t*pSrc、uint32_t批次);
pDst.req x0
预先请求x1
批次要求w2
pGrn.req x3
pBlu.req x4
步幅要求x5
计数要求w7
巴林格先生64
.func
alquimista_ndarray_to_matrix_float:
移动步幅,#((640*360)15),lsl#16
移动计数,#(640*360)/32
添加pGrn、pRed、步幅、lsr#1
添加pBlu、pRed、stride
b 1f
巴林格先生64
1:
ldp q0,q1,[pRed],#32
自民党第二季度、第三季度、[pGrn]、#32
自民党第四季度、第五季度、[pBlu]、#32
潜艇计数,计数,#1
USHL v20.8h,v0.8b,#7
USHL2 v23.8h,v0.16b,#7
USHL v26.8h,v1.8b,#7
USHL2v29.8h,v1.16b,#7
USHL v21.8h,v2.8b,#7
USHL2V24.8h,v2.16b,#7
USHL v27.8h,v3.8b,#7
USHL2V30.8h,v3.16b,#7
USHL v22.8h,v4.8b,#7
USHL2V25.8h,v4.16b,#7
USHL v28.8h,v5.8b,#7
USHL2v31.8h,v5.16b,#7
ursra v20.8h,v20.8h,#8
ursra v21.8h,v21.8h,#8
ursra v22.8h,v22.8h,#8
ursra v23.8h,v23.8h,#8
ursra v24.8h,v24.8h,#8
ursra v25.8h,v25.8h,#8
ursra v26.8h,v26.8h,#8
ursra v27.8h,v27.8h,#8
ursra v28.8h,v28.8h,#8
ursra v29.8h,v29.8h,#8
ursra v30.8h,v30.8h,#8
ursra v31.8h,v31.8h,#8
uxtl v0.4s,v20.4h
uxtl v1.4s,v21.4h
uxtl v2.4s,v22.4h
uxtl2 v3.4s,v20.8h
uxtl2 v4.4s,v21.8h
UXTL2V5.4s,v22.8h
uxtl v6.4s,v23.4h
uxtl v7.4s,v24.4h
uxtl v8.4s,v25.4h
UXTL2V15.4s,v23.8h
UXTL2V16.4s,v24.8h
UXTL2V17.4s,v25.8h
uxtl v18.4s,v26.4h
uxtl v19.4s,v27.4h
uxtl v20.4s,v28.4h
uxtl2 v21.4s,v26.8h
uxtl2 v22.4s,v27.8h
uxtl2 v23.4s,v28.8h
uxtl v24.4s,v29.4h
uxtl v25.4s,v30.4h
uxtl v26.4s,v31.4h
uxtl2 v27.4s,v29.8h
uxtl2 v28.4s,v30.8h
uxtl2 v29.4s,v31.8h
ucvtf v0.4s,v0.4s,#15
ucvtf v1.4s,v1.4s,#15
ucvtf v2.4s,v2.4s,#15
ucvtf v3.4s,v3.4s,#15
ucvtf v4.4s,v4.4s,#15
ucvtf v5.4s,v5.4s,#15
ucvtf v6.4s,v6.4s,#15
ucvtf v7.4s,v7.4s,#15
ucvtf v8.4s,v8.4s,#15
ucvtf v15.4s,v15.4s,#15
ucvtf v16.4s,v16.4s,#15
ucvtf v17.4s,
/*
 *  Created on: 2018. 5. 5.
 *      Copyright: Jake 'Alquimista' Lee. All rights reserved
 */

    .arch   armv8-a
    .text
    .global alquimista_ndarray_to_matrix_float

// void alquimista_ndarray_to_matrix_float(float *pDst, uint8_t *pSrc, uint32_t batch);

pDst    .req    x0
pRed    .req    x1
batch   .req    w2
pGrn    .req    x3
pBlu    .req    x4
stride  .req    x5
count   .req    w7

.balign 64
.func
alquimista_ndarray_to_matrix_float:
    mov     stride, #((640*360)<<1) & 0xffff
    stp     q8, q15, [sp, #-32]!
    movk    stride, #((640*360)>>15), lsl #16
    mov     count, #(640*360)/32
    add     pGrn, pRed, stride, lsr #1
    add     pBlu, pRed, stride
    b       1f

.balign 64
1:
    ldp     q0, q1, [pRed], #32
    ldp     q2, q3, [pGrn], #32
    ldp     q4, q5, [pBlu], #32

    subs    count, count, #1

    ushll   v20.8h, v0.8b, #7
    ushll2  v23.8h, v0.16b, #7
    ushll   v26.8h, v1.8b, #7
    ushll2  v29.8h, v1.16b, #7
    ushll   v21.8h, v2.8b, #7
    ushll2  v24.8h, v2.16b, #7
    ushll   v27.8h, v3.8b, #7
    ushll2  v30.8h, v3.16b, #7
    ushll   v22.8h, v4.8b, #7
    ushll2  v25.8h, v4.16b, #7
    ushll   v28.8h, v5.8b, #7
    ushll2  v31.8h, v5.16b, #7

    ursra   v20.8h, v20.8h, #8
    ursra   v21.8h, v21.8h, #8
    ursra   v22.8h, v22.8h, #8
    ursra   v23.8h, v23.8h, #8
    ursra   v24.8h, v24.8h, #8
    ursra   v25.8h, v25.8h, #8
    ursra   v26.8h, v26.8h, #8
    ursra   v27.8h, v27.8h, #8
    ursra   v28.8h, v28.8h, #8
    ursra   v29.8h, v29.8h, #8
    ursra   v30.8h, v30.8h, #8
    ursra   v31.8h, v31.8h, #8

    uxtl    v0.4s, v20.4h
    uxtl    v1.4s, v21.4h
    uxtl    v2.4s, v22.4h
    uxtl2   v3.4s, v20.8h
    uxtl2   v4.4s, v21.8h
    uxtl2   v5.4s, v22.8h

    uxtl    v6.4s, v23.4h
    uxtl    v7.4s, v24.4h
    uxtl    v8.4s, v25.4h
    uxtl2   v15.4s, v23.8h
    uxtl2   v16.4s, v24.8h
    uxtl2   v17.4s, v25.8h

    uxtl    v18.4s, v26.4h
    uxtl    v19.4s, v27.4h
    uxtl    v20.4s, v28.4h
    uxtl2   v21.4s, v26.8h
    uxtl2   v22.4s, v27.8h
    uxtl2   v23.4s, v28.8h

    uxtl    v24.4s, v29.4h
    uxtl    v25.4s, v30.4h
    uxtl    v26.4s, v31.4h
    uxtl2   v27.4s, v29.8h
    uxtl2   v28.4s, v30.8h
    uxtl2   v29.4s, v31.8h

    ucvtf   v0.4s, v0.4s, #15
    ucvtf   v1.4s, v1.4s, #15
    ucvtf   v2.4s, v2.4s, #15

    ucvtf   v3.4s, v3.4s, #15
    ucvtf   v4.4s, v4.4s, #15
    ucvtf   v5.4s, v5.4s, #15

    ucvtf   v6.4s, v6.4s, #15
    ucvtf   v7.4s, v7.4s, #15
    ucvtf   v8.4s, v8.4s, #15

    ucvtf   v15.4s, v15.4s, #15
    ucvtf   v16.4s, v16.4s, #15
    ucvtf   v17.4s, v17.4s, #15

    ucvtf   v18.4s, v18.4s, #15
    ucvtf   v19.4s, v19.4s, #15
    ucvtf   v20.4s, v20.4s, #15

    ucvtf   v21.4s, v21.4s, #15
    ucvtf   v22.4s, v22.4s, #15
    ucvtf   v23.4s, v23.4s, #15

    ucvtf   v24.4s, v24.4s, #15
    ucvtf   v25.4s, v25.4s, #15
    ucvtf   v26.4s, v26.4s, #15

    ucvtf   v27.4s, v27.4s, #15
    ucvtf   v28.4s, v28.4s, #15
    ucvtf   v29.4s, v29.4s, #15

    st3     {v0.4s - v2.4s}, [pDst], #48
    st3     {v3.4s - v5.4s}, [pDst], #48
    st3     {v6.4s - v8.4s}, [pDst], #48
    st3     {v15.4s - v17.4s}, [pDst], #48
    st3     {v18.4s - v20.4s}, [pDst], #48
    st3     {v21.4s - v23.4s}, [pDst], #48
    st3     {v24.4s - v26.4s}, [pDst], #48
    st3     {v27.4s - v29.4s}, [pDst], #48
    b.gt    1b

    add     pRed, pRed, stride
    add     pGrn, pGrn, stride
    add     pGrn, pGrn, stride
    subs    batch, batch, #1
    mov     count, #(640*360)/32
    b.gt    1b

.balign 8
    ldp     q8, q15, [sp], #32
    ret
.endfunc
.end