【发布时间】:2026-02-10 00:55:02
【问题描述】:
我有一些 C 代码在带有 ARM-Cortex-A9 的开发板上运行,它执行我需要加速的图像处理。我所拥有的是读取 8 个 RGB 像素的代码,其中每种颜色都表示为 uint8_t。这些像素需要进行颜色校正,因此使用查找表来查找像素的单个通道的颜色校正值。颜色校正通道使用 16 位类型,但实际使用的位可能因output_color_depth 参数而异。
在此预处理步骤之后,我需要提取每个像素的每个通道的每个有效位并将其存储在输出缓冲区中。
下面的代码是有问题的函数:
struct Pixel {
uint8_t r;
uint8_t g;
uint8_t b;
};
static const uint16_t colorLookup[256] = { ... };
void postProcessImage(const struct Pixel* img, const uint16_t imgWidth, const uint16_t imgHeight,
uint8_t** output, const uint8_t output_color_depth)
{
const uint8_t input_color_depth = 8;
for (uint16_t y = 0; y < imgHeight; ++y)
{
const uint16_t top_offset = y * imgWidth;
for (uint16_t x = 0; x < imgWidth; x += 8)
{
const uint16_t offset = top_offset + x;
// Get 8 pixels to use. This is done since 8 pixels
// means 24 color channels which can fit exactly into
// 3 bytes
const uint16_t r0 = colorLookup[img[offset + 0].r];
const uint16_t g0 = colorLookup[img[offset + 0].g];
const uint16_t b0 = colorLookup[img[offset + 0].b];
const uint16_t r1 = colorLookup[img[offset + 1].r];
const uint16_t g1 = colorLookup[img[offset + 1].g];
const uint16_t b1 = colorLookup[img[offset + 1].b];
const uint16_t r2 = colorLookup[img[offset + 2].r];
const uint16_t g2 = colorLookup[img[offset + 2].g];
const uint16_t b2 = colorLookup[img[offset + 2].b];
const uint16_t r3 = colorLookup[img[offset + 3].r];
const uint16_t g3 = colorLookup[img[offset + 3].g];
const uint16_t b3 = colorLookup[img[offset + 3].b];
const uint16_t r4 = colorLookup[img[offset + 4].r];
const uint16_t g4 = colorLookup[img[offset + 4].g];
const uint16_t b4 = colorLookup[img[offset + 4].b];
const uint16_t r5 = colorLookup[img[offset + 5].r];
const uint16_t g5 = colorLookup[img[offset + 5].g];
const uint16_t b5 = colorLookup[img[offset + 5].b];
const uint16_t r6 = colorLookup[img[offset + 6].r];
const uint16_t g6 = colorLookup[img[offset + 6].g];
const uint16_t b6 = colorLookup[img[offset + 6].b];
const uint16_t r7 = colorLookup[img[offset + 7].r];
const uint16_t g7 = colorLookup[img[offset + 7].g];
const uint16_t b7 = colorLookup[img[offset + 7].b];
for (uint8_t c = 0; c < output_color_depth; ++c)
{
// For each significant bit we create the resulting byte
// and store it into the output buffer.
output[c][offset + 0] = (((g2 >> c) & 1) << 7) | (((r2 >> c) & 1) << 6)
| (((b1 >> c) & 1) << 5) | (((g1 >> c) & 1) << 4)
| (((r1 >> c) & 1) << 3) | (((b0 >> c) & 1) << 2)
| (((g0 >> c) & 1) << 1) | ((r0 >> c) & 1);
output[c][offset + 1] = (((r5 >> c) & 1) << 7) | (((b4 >> c) & 1) << 6)
| (((g4 >> c) & 1) << 5) | (((r4 >> c) & 1) << 4)
| (((b3 >> c) & 1) << 3) | (((g3 >> c) & 1) << 2)
| (((r3 >> c) & 1) << 1) | ((b2 >> c) & 1);
output[c][offset + 2] = (((b7 >> c) & 1) << 7) | (((g7 >> c) & 1) << 6)
| (((r7 >> c) & 1) << 5) | (((b6 >> c) & 1) << 4)
| (((g6 >> c) & 1) << 3) | (((r6 >> c) & 1) << 2)
| (((b5 >> c) & 1) << 1) | ((g5 >> c) & 1);
}
}
}
}
现在这个函数执行太慢了,我需要优化它。我正在考虑使用 NEON 指令来优化它。我很难在网上找到示例,但直观地说,这是我认为应该能够被矢量化的东西。有人可以给我一些指示,我怎样才能实现这样的目标?我也愿意接受有关如何优化此代码的其他建议!
感谢任何帮助。
【问题讨论】:
-
强制性问题:您是否在启用编译器优化的情况下编译代码?如果没有,请按照步骤 1 进行操作。
-
优化 #1:使用单个数组,而不是指向数组的指针数组。索引为
img[y*imgWidth+x]。因为您遍历整个数组,您可以简单地将索引为img[index],index从 0 运行到imgWidth*imgHeight。不仅索引更便宜,而且您将拥有更少的内存碎片和更好的缓存局部性。 -
为什么要连续分配给
output[c][offset]3次? -
请显示您使用的编译/链接命令以及 GCC 版本。
-
尝试添加
-march=native
标签: c++ c image-processing optimization simd