[gegl] operations: make gegl:distance-transform multi-thread.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operations: make gegl:distance-transform multi-thread.
- Date: Mon, 12 Nov 2018 14:11:19 +0000 (UTC)
commit 8c79a82fe219dd53127a09eec54fb3d7cebc078b
Author: Jehan <jehan girinstud io>
Date: Mon Nov 12 13:36:30 2018 +0100
operations: make gegl:distance-transform multi-thread.
This replaces my previous request !10. Now we can use the new
gegl_parallel_*() API. Not using some generic API was the only thing
which annoyed me in my previous implementation.
Similarly to the gegl:warp parallelization, make this C++ so we can use
lambda functions.
operations/common-cxx/Makefile.am | 1 +
.../distance-transform.cc} | 181 +++++++++++----------
operations/common/Makefile.am | 1 -
po/POTFILES.in | 2 +-
4 files changed, 100 insertions(+), 85 deletions(-)
---
diff --git a/operations/common-cxx/Makefile.am b/operations/common-cxx/Makefile.am
index 356cf9911..ea665469c 100644
--- a/operations/common-cxx/Makefile.am
+++ b/operations/common-cxx/Makefile.am
@@ -14,6 +14,7 @@ op_LTLIBRARIES = \
gegl_common_cxx_la_SOURCES =\
module.c \
+ distance-transform.cc \
warp.cc
module.c: Makefile $(gegl_common_cxx_la_SOURCES)
diff --git a/operations/common/distance-transform.c b/operations/common-cxx/distance-transform.cc
similarity index 71%
rename from operations/common/distance-transform.c
rename to operations/common-cxx/distance-transform.cc
index fdfa97a0d..bb5d46699 100644
--- a/operations/common/distance-transform.c
+++ b/operations/common-cxx/distance-transform.cc
@@ -25,6 +25,8 @@
#include "config.h"
#include <glib/gi18n-lib.h>
+#define MIN_PARALLEL_SUB_SIZE 64
+
#ifdef GEGL_PROPERTIES
property_enum (metric, _("Metric"),
@@ -50,7 +52,7 @@ property_boolean (normalize, _("Normalize"), TRUE)
#define GEGL_OP_FILTER
#define GEGL_OP_NAME distance_transform
-#define GEGL_OP_C_SOURCE distance-transform.c
+#define GEGL_OP_C_SOURCE distance-transform.cc
#include "gegl-op.h"
#include <math.h>
#include <stdio.h>
@@ -150,10 +152,6 @@ binary_dt_2nd_pass (GeglOperation *operation,
gfloat *src,
gfloat *dest)
{
- gint u, y;
- gint q, w, *t, *s;
- gfloat *g, *row_copy;
-
gfloat (*dt_f) (gfloat, gfloat, gfloat);
gint (*dt_sep) (gint, gint, gfloat, gfloat);
@@ -173,73 +171,81 @@ binary_dt_2nd_pass (GeglOperation *operation,
break;
}
- /* sorry for the variable naming, they are taken from the paper */
-
- s = gegl_calloc (sizeof (gint), width);
- t = gegl_calloc (sizeof (gint), width);
- row_copy = gegl_calloc (sizeof (gfloat), width);
-
- /* this could be parallelized */
- for (y = 0; y < height; y++)
+ /* Parallelize the loop. We don't even need a mutex as we edit data per
+ * lines (i.e. each thread will work on a given range of lines without
+ * needing to read data updated by other threads).
+ */
+ gegl_parallel_distribute_range (height, MIN_PARALLEL_SUB_SIZE,
+ [&] (gint y0, gint size)
{
- q = 0;
- s[0] = 0;
- t[0] = 0;
- g = dest + y * width;
+ gfloat *g, *row_copy;
+ gint q, w, *t, *s;
+ gint u, y;
- dest[0 + y * width] = MIN (dest[0 + y * width], 1.0);
- dest[width - 1 + y * width] = MIN (dest[width - 1 + y * width], 1.0);
+ /* sorry for the variable naming, they are taken from the paper */
- for (u = 1; u < width; u++)
+ s = (gint *) gegl_calloc (sizeof (gint), width);
+ t = (gint *) gegl_calloc (sizeof (gint), width);
+ row_copy = (gfloat *) gegl_calloc (sizeof (gfloat), width);
+
+ for (y = y0; y < y0 + size; y++)
{
- while (q >= 0 &&
- dt_f (t[q], s[q], g[s[q]]) >= dt_f (t[q], u, g[u]) + EPSILON)
- {
- q --;
- }
+ q = 0;
+ s[0] = 0;
+ t[0] = 0;
+ g = dest + y * width;
- if (q < 0)
- {
- q = 0;
- s[0] = u;
- }
- else
+ dest[0 + y * width] = MIN (dest[0 + y * width], 1.0);
+ dest[width - 1 + y * width] = MIN (dest[width - 1 + y * width], 1.0);
+
+ for (u = 1; u < width; u++)
{
- /* function Sep from paper */
- w = dt_sep (s[q], u, g[s[q]], g[u]);
- w += 1;
+ while (q >= 0 &&
+ dt_f (t[q], s[q], g[s[q]]) >= dt_f (t[q], u, g[u]) + EPSILON)
+ {
+ q --;
+ }
- if (w < width)
+ if (q < 0)
{
- q ++;
- s[q] = u;
- t[q] = w;
+ q = 0;
+ s[0] = u;
+ }
+ else
+ {
+ /* function Sep from paper */
+ w = dt_sep (s[q], u, g[s[q]], g[u]);
+ w += 1;
+
+ if (w < width)
+ {
+ q ++;
+ s[q] = u;
+ t[q] = w;
+ }
}
}
- }
-
- memcpy (row_copy, g, width * sizeof (gfloat));
- for (u = width - 1; u >= 0; u--)
- {
- if (u == s[q])
- g[u] = row_copy[u];
- else
- g[u] = dt_f (u, s[q], row_copy[s[q]]);
+ memcpy (row_copy, g, width * sizeof (gfloat));
- if (q > 0 && u == t[q])
+ for (u = width - 1; u >= 0; u--)
{
- q--;
+ if (u == s[q])
+ g[u] = row_copy[u];
+ else
+ g[u] = dt_f (u, s[q], row_copy[s[q]]);
+
+ if (q > 0 && u == t[q])
+ {
+ q--;
+ }
}
}
- gegl_operation_progress (operation,
- (gdouble) y / (gdouble) height / 2.0 + 0.5, "");
- }
-
- gegl_free (t);
- gegl_free (s);
- gegl_free (row_copy);
+ gegl_free (t);
+ gegl_free (s);
+ gegl_free (row_copy);
+ });
}
@@ -251,32 +257,37 @@ binary_dt_1st_pass (GeglOperation *operation,
gfloat *src,
gfloat *dest)
{
- int x, y;
-
- /* this loop could be parallelized */
- for (x = 0; x < width; x++)
+ /* Parallelize the loop. We don't even need a mutex as we edit data per
+ * columns (i.e. each thread will work on a given range of columns without
+ * needing to read data updated by other threads).
+ */
+ gegl_parallel_distribute_range (width, MIN_PARALLEL_SUB_SIZE,
+ [&] (gint x0, gint size)
{
- /* consider out-of-range as 0, i.e. the outside is "empty" */
- dest[x + 0 * width] = src[x + 0 * width] > thres_lo ? 1.0 : 0.0;
+ gint x;
+ gint y;
- for (y = 1; y < height; y++)
+ for (x = x0; x < x0 + size; x++)
{
- if (src[x + y * width] > thres_lo)
- dest[x + y * width] = 1.0 + dest[x + (y - 1) * width];
- else
- dest[x + y * width] = 0.0;
- }
+ /* consider out-of-range as 0, i.e. the outside is "empty" */
+ dest[x + 0 * width] = src[x + 0 * width] > thres_lo ? 1.0 : 0.0;
- dest[x + (height - 1) * width] = MIN (dest[x + (height - 1) * width], 1.0);
- for (y = height - 2; y >= 0; y--)
- {
- if (dest[x + (y + 1) * width] + 1.0 < dest[x + y * width])
- dest [x + y * width] = dest[x + (y + 1) * width] + 1.0;
- }
+ for (y = 1; y < height; y++)
+ {
+ if (src[x + y * width] > thres_lo)
+ dest[x + y * width] = 1.0 + dest[x + (y - 1) * width];
+ else
+ dest[x + y * width] = 0.0;
+ }
- gegl_operation_progress (operation,
- (gdouble) x / (gdouble) width / 2.0, "");
- }
+ dest[x + (height - 1) * width] = MIN (dest[x + (height - 1) * width], 1.0);
+ for (y = height - 2; y >= 0; y--)
+ {
+ if (dest[x + (y + 1) * width] + 1.0 < dest[x + y * width])
+ dest [x + y * width] = dest[x + (y + 1) * width] + 1.0;
+ }
+ }
+ });
}
@@ -314,10 +325,10 @@ process (GeglOperation *operation,
metric = o->metric;
averaging = o->averaging;
- src_buf = gegl_malloc (width * height * bytes_per_pixel);
- dst_buf = gegl_calloc (width * height, bytes_per_pixel);
+ src_buf = (gfloat *) gegl_malloc (width * height * bytes_per_pixel);
+ dst_buf = (gfloat *) gegl_calloc (width * height, bytes_per_pixel);
- gegl_operation_progress (operation, 0.0, "");
+ gegl_operation_progress (operation, 0.0, (gchar *) "");
gegl_buffer_get (input, result, 1.0, input_format, src_buf,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
@@ -326,6 +337,7 @@ process (GeglOperation *operation,
{
binary_dt_1st_pass (operation, width, height, threshold_lo,
src_buf, dst_buf);
+ gegl_operation_progress (operation, 0.5, (gchar *) "");
binary_dt_2nd_pass (operation, width, height, threshold_lo, metric,
src_buf, dst_buf);
}
@@ -334,7 +346,7 @@ process (GeglOperation *operation,
gfloat *tmp_buf;
gint i, j;
- tmp_buf = gegl_malloc (width * height * bytes_per_pixel);
+ tmp_buf = (gfloat *) gegl_malloc (width * height * bytes_per_pixel);
for (i = 0; i < averaging; i++)
{
@@ -345,8 +357,11 @@ process (GeglOperation *operation,
binary_dt_1st_pass (operation, width, height, thres,
src_buf, tmp_buf);
+ gegl_operation_progress (operation, (i + 1) / averaging - 1 / (2 * averaging),
+ (gchar *) "");
binary_dt_2nd_pass (operation, width, height, thres, metric,
src_buf, tmp_buf);
+ gegl_operation_progress (operation, (i + 1) / averaging, (gchar *) "");
for (j = 0; j < width * height; j++)
dst_buf[j] += tmp_buf[j];
@@ -376,7 +391,7 @@ process (GeglOperation *operation,
gegl_buffer_set (output, result, 0, input_format, dst_buf,
GEGL_AUTO_ROWSTRIDE);
- gegl_operation_progress (operation, 1.0, "");
+ gegl_operation_progress (operation, 1.0, (gchar *) "");
gegl_free (dst_buf);
gegl_free (src_buf);
@@ -390,7 +405,7 @@ gegl_op_class_init (GeglOpClass *klass)
{
GeglOperationClass *operation_class;
GeglOperationFilterClass *filter_class;
- gchar *composition =
+ const gchar *composition =
"<?xml version='1.0' encoding='UTF-8'?>"
"<gegl>"
"<node operation='gegl:distance-transform'>"
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index 3cc6975b5..6630bb125 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -37,7 +37,6 @@ gegl_common_la_SOURCES =\
copy-buffer.c \
difference-of-gaussians.c \
display.c \
- distance-transform.c \
dropshadow.c \
edge-neon.c \
edge-sobel.c \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index dc3d90a00..4194c45d6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -28,7 +28,7 @@ operations/common/convolution-matrix.c
operations/common/copy-buffer.c
operations/common/difference-of-gaussians.c
operations/common/display.c
-operations/common/distance-transform.c
+operations/common/distance-transform.cc
operations/common/dither.c
operations/common/dropshadow.c
operations/common/edge-neon.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]