简体   繁体   English

为什么一种方法比另一种慢

[英]Why is one method slower than the other one

I have these two variants of my code which one of them runs significantly slower then the other one, although I think it should not do it.我的代码有这两种变体,其中一种的运行速度比另一种慢得多,尽管我认为它不应该这样做。 Could somebody please explain me what takes it so long to run while doing it like this?有人可以解释一下这样做需要这么长时间才能运行吗? The code is a basic floodfill algorithm, the pos variable is declared previously as unsigned long Thank you代码是一个基本的floodfill算法,pos变量之前声明为unsigned long谢谢

This piece of code runs much slower than the second one.这段代码的运行速度比第二段慢得多。

void
flood(byte * array, unsigned long x, unsigned long y, byte value)
{
    node_t *head = NULL;

    queue(&head, x, y);
    while (head != NULL) {
        unsigned long *ret = dequeue(&head);

        pos = ret[0] + ret[1] * pgmWidth;
        if (pos >= 0 && pos < pgmSize && ret[1] < pgmHeight &&
            array[pos] == UCHAR_MAX) {
            array[pos] = value;

            queue(&head, ret[0] + 1, ret[1]);
            queue(&head, ret[0], ret[1] + 1);
            queue(&head, ret[0], ret[1] - 1);
            queue(&head, ret[0] - 1, ret[1]);
        }
        free(ret);
    }
}

This piece runs much faster although there is more conditions then in the first one这件作品跑得更快,虽然条件比第一件要多

void
flood(byte * array, unsigned long x, unsigned long y, byte value)
{
    node_t *head = NULL;

    queue(&head, x, y);
    while (head != NULL) {
        unsigned long *ret = dequeue(&head);

        pos = ret[0] + ret[1] * pgmWidth;
        if (ret[0] >= 0 && ret[0] < pgmWidth && ret[1] >= 0 &&
            ret[1] < pgmHeight && array[pos] == UCHAR_MAX) {
            array[pos] = value;

            queue(&head, ret[0] + 1, ret[1]);
            queue(&head, ret[0], ret[1] + 1);
            queue(&head, ret[0], ret[1] - 1);
            queue(&head, ret[0] - 1, ret[1]);
        }
        free(ret);
    }
}

The is a significant difference between the 2 functions: the second piece of code stops the flood at the left and right edges of the 2D array whereas the first does not.这是两个函数之间的显着区别:第二段代码在二维数组的左右边缘停止泛洪,而第一段代码没有。

The set of pixels that are explored is different: for example imagine the array is filled with UCHAR_MAX values except for a vertical line running from top to bottom.所探索的像素集是不同的:例如,假设数组填充了UCHAR_MAX值,除了一条从上到下的垂直线。 The first code will flood the array on both sides from any pixel not on the vertical line whereas the second will only flood half of the surface.第一个代码将从不在垂直线上的任何像素淹没阵列的两侧,而第二个代码只会淹没表面的一半。

This possibly explains the difference in running times, depending on the actual contents of the array at the call.这可能解释了运行时间的差异,具体取决于调用时数组的实际内容。

Both approaches may make sense, but have different semantics:这两种方法都可能有意义,但语义不同:

  • the first code floods the array as the surface of a cylinder with a one pixel misalignment along the junction.第一个代码将阵列作为圆柱体的表面泛滥,沿交界处有一个像素未对齐。
  • the second code floods the array as a flat rectangle, which seems more consistent.第二个代码将数组作为平面矩形填充,这看起来更一致。

There are ways to further improve the code:有一些方法可以进一步改进代码:

  • you should remove 2 redundant tests as the coordinates are unsigned, which are defined to have wrap around semantics,您应该删除 2 个冗余测试,因为坐标是无符号的,它们被定义为具有环绕语义,
  • you should only queue pixels that are actually reached,你应该只排队实际到达的像素,
  • you should change the pixel value before queueing the pixel coordinates to avoid queueing the same pixel multiple times.您应该在排队像素坐标之前更改像素值,以避免多次排队相同的像素。
void flood(byte *array, unsigned long x, unsigned long y, byte value)
{
    node_t *head = NULL;

    pos = x + y * pgmWidth;
    if (x < pgmWidth && y < pgmHeight && array[pos] == UCHAR_MAX) {
        array[pos] = value;
        queue(&head, x, y);
    }

    while (head != NULL) {
        unsigned long *ret = dequeue(&head);
        x = ret[0];
        y = ret[1];
        free(ret);

        pos = x + y * pgmWidth;
        
        if (x + 1 < pgmWidth && array[pos + 1] == UCHAR_MAX) {
            array[pos + 1] = value;
            queue(&head, x + 1, y);
        }
        if (y + 1 < pgmHeight && array[pos + pgmWidth] == UCHAR_MAX) {
            array[pos + pgmWidth] = value;
            queue(&head, x, y + 1);
        }
        if (y > 0 && array[pos - pgmWidth] == UCHAR_MAX) {
            array[pos - pgmWidth] = value;
            queue(&head, x, y - 1);
        }
        if (x > 0 && array[pos - 1] == UCHAR_MAX) {
            array[pos - 1] = value;
            queue(&head, x - 1, y);
        }
    }
}

Finally, using global variables for pos , pgmWidth and pgmHeight makes the code slower.最后,对pospgmWidthpgmHeight使用全局变量会使代码变慢。 There is no real value in using a global variable for pos anyway.无论如何,对pos使用全局变量并没有真正的价值。 Try this alternative:试试这个替代方案:

void flood(byte *array, unsigned long x, unsigned long y, byte value)
{
    node_t *head = NULL;
    unsigned long width = pgmWidth;
    unsigned long height = pgmHeight;
    unsigned long pos;

    p = x + y * width;
    if (x < width && y < height && array[pos] == UCHAR_MAX) {
        array[pos] = value;
        queue(&head, x, y);
    }

    while (head != NULL) {
        unsigned long *ret = dequeue(&head);
        x = ret[0];
        y = ret[1];
        free(ret);

        pos = x + y * width;
        
        if (x + 1 < width && array[pos + 1] == UCHAR_MAX) {
            array[pos + 1] = value;
            queue(&head, x + 1, y);
        }
        if (y + 1 < height && array[pos + width] == UCHAR_MAX) {
            array[pos + width] = value;
            queue(&head, x, y + 1);
        }
        if (y > 0 && array[pos - width] == UCHAR_MAX) {
            array[pos - width] = value;
            queue(&head, x, y - 1);
        }
        if (x > 0 && array[pos - 1] == UCHAR_MAX) {
            array[pos - 1] = value;
            queue(&head, x - 1, y);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM