簡體   English   中英

為什么一種方法比另一種慢

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

我的代碼有這兩種變體,其中一種的運行速度比另一種慢得多,盡管我認為它不應該這樣做。 有人可以解釋一下這樣做需要這么長時間才能運行嗎? 代碼是一個基本的floodfill算法,pos變量之前聲明為unsigned long謝謝

這段代碼的運行速度比第二段慢得多。

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);
    }
}

這件作品跑得更快,雖然條件比第一件要多

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);
    }
}

這是兩個函數之間的顯着區別:第二段代碼在二維數組的左右邊緣停止泛洪,而第一段代碼沒有。

所探索的像素集是不同的:例如,假設數組填充了UCHAR_MAX值,除了一條從上到下的垂直線。 第一個代碼將從不在垂直線上的任何像素淹沒陣列的兩側,而第二個代碼只會淹沒表面的一半。

這可能解釋了運行時間的差異,具體取決於調用時數組的實際內容。

這兩種方法都可能有意義,但語義不同:

  • 第一個代碼將陣列作為圓柱體的表面泛濫,沿交界處有一個像素未對齊。
  • 第二個代碼將數組作為平面矩形填充,這看起來更一致。

有一些方法可以進一步改進代碼:

  • 您應該刪除 2 個冗余測試,因為坐標是無符號的,它們被定義為具有環繞語義,
  • 你應該只排隊實際到達的像素,
  • 您應該在排隊像素坐標之前更改像素值,以避免多次排隊相同的像素。
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);
        }
    }
}

最后,對pospgmWidthpgmHeight使用全局變量會使代碼變慢。 無論如何,對pos使用全局變量並沒有真正的價值。 試試這個替代方案:

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