【发布时间】:2021-02-17 23:17:03
【问题描述】:
我正在使用此代码查找热图像中温度最高的像素和像素的坐标。
void _findMax(uint16_t *image, int sz, sPixelData *returnPixel)
{
int temp = 0;
for (int i = sz; i > 0; i--)
{
if (returnPixel->temperature < *image)
{
returnPixel->temperature = *image;
temp = i;
}
image++;
}
returnPixel->x_location = temp % IMAGE_HORIZONTAL_SIZE;
returnPixel->y_location = temp / IMAGE_HORIZONTAL_SIZE;
}
图像大小为 640x480,运行此函数大约需要 35 毫秒,这对于我需要它来说太慢了(理想情况下不到 10 毫秒)。
这是在运行 Linux 的 ARM A9 处理器上执行的。
我使用的编译器是 ARM v8 32-Bit Linux gcc 编译器。
我正在使用优化 -O3 和以下编译选项:-march=armv7-a+neon -mcpu=cortex-a9 -mfpu=neon-fp16 -ftree-vectorize。
这是编译器的输出:
000127f4 <_findMax>:
for(int i = sz; i > 0; i--)
127f4: e3510000 cmp r1, #0
{
127f8: e52de004 push {lr} ; (str lr, [sp, #-4]!)
for(int i = sz; i > 0; i--)
127fc: da000014 ble 12854 <_findMax+0x60>
12800: e1d2c0b0 ldrh ip, [r2]
12804: e2400002 sub r0, r0, #2
int temp = 0;
12808: e3a0e000 mov lr, #0
if(returnPixel->temperature < *image)
1280c: e1f030b2 ldrh r3, [r0, #2]!
12810: e153000c cmp r3, ip
returnPixel->temperature = *image;
12814: 81a0c003 movhi ip, r3
12818: 81a0e001 movhi lr, r1
1281c: 81c230b0 strhhi r3, [r2]
for(int i = sz; i > 0; i--)
12820: e2511001 subs r1, r1, #1
12824: 1afffff8 bne 1280c <_findMax+0x18>
12828: e30c3ccd movw r3, #52429 ; 0xcccd
1282c: e34c3ccc movt r3, #52428 ; 0xcccc
12830: e0831e93 umull r1, r3, r3, lr
12834: e1a034a3 lsr r3, r3, #9
12838: e0831103 add r1, r3, r3, lsl #2
1283c: e6ff3073 uxth r3, r3
12840: e04ee381 sub lr, lr, r1, lsl #7
12844: e6ffe07e uxth lr, lr
returnPixel->x_location = temp % IMAGE_HORIZONTAL_SIZE;
12848: e1c2e0b4 strh lr, [r2, #4]
returnPixel->y_location = temp / IMAGE_HORIZONTAL_SIZE;
1284c: e1c230b6 strh r3, [r2, #6]
}
12850: e49df004 pop {pc} ; (ldr pc, [sp], #4)
for(int i = sz; i > 0; i--)
12854: e3a03000 mov r3, #0
12858: e1a0e003 mov lr, r3
1285c: eafffff9 b 12848 <_findMax+0x54>
为了清楚起见,在 cmets 之后:
每个像素都是一个无符号的 16 位整数,image[0] 是坐标为 0,0 的像素,数组中最后一个像素的坐标为 639,479。
【问题讨论】:
-
您可以每隔一行和一列检查一次,这将使其大约快 4 倍。您失去了精度,但它可能足以满足您的需求。
-
a) 稍微展开 for 循环。例如每次迭代处理几个像素。参见:duffs device -> en.wikipedia.org/wiki/Duff%27s_device, b) 使用一些梯度路径算法:en.wikipedia.org/wiki/Gradient_descent
-
你如何读取像素?找到当时最热门的可能是微不足道的。
-
@pqans -我添加了选项 -funroll-loops 将其缩短到 13 毫秒
-
是的,所以算法没有用,除非你能找到一种方法将图像分割成几个“热点方块”。如果你能做到这一点,那么梯度下降比当前算法的“蛮力”快得多。
标签: c gcc optimization arm neon