c - Zig-zag 迭代数组 - 速度优化

标签 c arrays algorithm embedded

我有一个像这样的数组:

{
  1, 2, 3, 4,
  5, 6, 7, 8,
  9,10,11,12,
 13,14,15,16
}

我需要以锯齿形方式迭代它,例如1,2,3,4,8,7,6,5,9...

这很简单,但是开销空间很小,所以我需要它尽可能节省时间。每个额外的周期在这里都很重要。

这就是我现在拥有的:

#define send_colors_zigzag(io, colorz, width, height) do {                          \
    for(int8_t y = 0, uu=0, a=1; y < (height); y++, uu+=width, a *= -1) {           \
        uint8_t uup = uu + (a < 0 ? width : 0);                                     \
        for(uint8_t x = 0; x < (width); x++) {                                      \
            uint8_t pos = uup + a*x;                                                \
            const color_t clr = (colorz)[pos];                                      \
            send_one_color(io_pack(io), clr);                                       \
        }                                                                           \
    }                                                                               \
} while(0)

send_one_color 是一个宏,它扩展为各个位的循环,我不想在这个宏中重复它两次(需要保持它很小)。

我有理由将其作为宏来执行,ioio_pack 是引脚别名的一些魔法,这是常规函数无法完成的。

我相信它循环正确,但它不够快(因此无法使用)。

我正在开发 8 位微型处理器,16MHz。


仅供引用,此版本有效(但大型内部宏重复两次,我想避免):

#define send_colors_zigzag(io, colorz, width, height) do {                          \
    int8_t x;                                                                       \
    for(int8_t y = 0; y < (height); y++) {                                          \
        for(x = 0; x < (width); x++) {                                              \
            send_one_color(io_pack(io), (colorz)[y*width + x]);                     \
        }                                                                           \
        y++;                                                                        \
        for(x = width-1; x >=0; x--) {                                              \
            send_one_color(io_pack(io), (colorz)[y*width + x]);                     \
        }                                                                           \
    }                                                                               \
} while(0)

最佳答案

这是一种尽可能避免算术的方法,尤其是在内循环中。

color_t* p = (colorz);
for (int8_t y = 0; y < (height); y++) {
    int8_t inc = y & 1 ? -1 : 1;
    if (y) {
        p += (width) + inc;
    }
    for (int8_t x = 0; x < (width); x++) {
        send_one_color(io_pack(io), *p);
        p += inc;
    }
}

如果 height 是偶数,或者如果您不介意未定义的行为(因为 p 指向超出 的末尾),则可以使用此变体节省一些周期>colorz):

color_t* p = (colorz);
for (int8_t y = 0; y < (height); y++) {
    int8_t inc = y & 1 ? -1 : 1;
    for (int8_t x = 0; x < (width); x++) {
        send_one_color(io_pack(io), *p);
        p += inc;
    }
    p += (width) - inc;
}

关于c - Zig-zag 迭代数组 - 速度优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29193419/

相关文章:

javascript - 在 Javascript 中查找坏点的算法

java - 在 Java 中将一个数组中的特定元素添加到另一个数组中

c# - 如何在for循环中生成尽可能多的for循环?

c - 为什么这个程序在使用大字符串时不能给出正确的结果?

objective-c - 在 C 中使用 char,指针问题, Objective-C

c - 列出导入的PE文件的DLL

c - 从 C 中的多个整数创建 String(char*)

java - 如何检查数组的所有元素是否相同

arrays - 使用一组键拆分对象数组

c++ - 计算斯特林数的动态规划方法