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
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. 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:
There are ways to further improve the code:
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. There is no real value in using a global variable for pos
anyway. 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);
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.