[gegl/wip/threaded-dup-input: 2/4] operation, transform: use separate input buffers for different threads



commit 7318fa3ba1c4710e0a469fbe60ddf5f8dd726821
Author: Ell <ell_se yahoo com>
Date:   Wed Dec 13 03:24:28 2017 -0500

    operation, transform: use separate input buffers for different threads
    
    Use gegl_operation_context_dup_input_maybe_copy(), added in the
    previous commit, in GimpOperationFilter, GimpOperationComposer,
    GimpOperationComposer3, and OpTransform (however, *not* in the
    corresponding point ops), to (potentially) create a separate copy
    of the input buffer for each thread, to avoid lock contention over
    the input buffer's tile-storage lock.  Use the input buffer
    directly only for the first chunk, which is processed by the caller
    thread.
    
    This significantly improves performance of operations that randomly
    access the input buffer (e.g., using a sampler), and seems not to
    pessimize operations with a more regular access pattern (e.g.,
    using an iterator, or scan rows).

 gegl/operation/gegl-operation-composer.c  |   21 ++++++++++++++++-----
 gegl/operation/gegl-operation-composer3.c |   22 ++++++++++++++++------
 gegl/operation/gegl-operation-filter.c    |   20 +++++++++++++++-----
 operations/transform/transform-core.c     |   21 +++++++++++++++------
 4 files changed, 62 insertions(+), 22 deletions(-)
---
diff --git a/gegl/operation/gegl-operation-composer.c b/gegl/operation/gegl-operation-composer.c
index b67a745..c971baa 100644
--- a/gegl/operation/gegl-operation-composer.c
+++ b/gegl/operation/gegl-operation-composer.c
@@ -101,7 +101,7 @@ typedef struct ThreadData
 {
   GeglOperationComposerClass *klass;
   GeglOperation              *operation;
-  GeglBuffer                 *input;
+  GeglOperationContext       *context;
   GeglBuffer                 *aux;
   GeglBuffer                 *output;
   gint                       *pending;
@@ -110,12 +110,23 @@ typedef struct ThreadData
   GeglRectangle               roi;
 } ThreadData;
 
-static void thread_process (gpointer thread_data, gpointer unused)
+static void thread_process (gpointer thread_data, gpointer input)
 {
   ThreadData *data = thread_data;
+
+  if (! input)
+    {
+      input = gegl_operation_context_dup_input_maybe_copy (data->context,
+                                                           "input", &data->roi);
+    }
+
   if (!data->klass->process (data->operation,
-                       data->input, data->aux, data->output, &data->roi, data->level))
+                             input, data->aux, data->output,
+                             &data->roi, data->level))
     data->success = FALSE;
+
+  g_object_unref (input);
+
   g_atomic_int_add (data->pending, -1);
 }
 
@@ -197,7 +208,7 @@ gegl_operation_composer_process (GeglOperation        *operation,
         {
           thread_data[i].klass = klass;
           thread_data[i].operation = operation;
-          thread_data[i].input = input;
+          thread_data[i].context = context;
           thread_data[i].aux = aux;
           thread_data[i].output = output;
           thread_data[i].pending = &pending;
@@ -207,7 +218,7 @@ gegl_operation_composer_process (GeglOperation        *operation,
 
         for (gint i = 1; i < threads; i++)
           g_thread_pool_push (pool, &thread_data[i], NULL);
-        thread_process (&thread_data[0], NULL);
+        thread_process (&thread_data[0], g_object_ref (input));
 
         while (g_atomic_int_get (&pending)) {};
 
diff --git a/gegl/operation/gegl-operation-composer3.c b/gegl/operation/gegl-operation-composer3.c
index 5e660e7..9fbbfbc 100644
--- a/gegl/operation/gegl-operation-composer3.c
+++ b/gegl/operation/gegl-operation-composer3.c
@@ -110,7 +110,7 @@ typedef struct ThreadData
 {
   GeglOperationComposer3Class *klass;
   GeglOperation               *operation;
-  GeglBuffer                  *input;
+  GeglOperationContext        *context;
   GeglBuffer                  *aux;
   GeglBuffer                  *aux2;
   GeglBuffer                  *output;
@@ -120,13 +120,23 @@ typedef struct ThreadData
   GeglRectangle                roi;
 } ThreadData;
 
-static void thread_process (gpointer thread_data, gpointer unused)
+static void thread_process (gpointer thread_data, gpointer input)
 {
   ThreadData *data = thread_data;
+
+  if (! input)
+    {
+      input = gegl_operation_context_dup_input_maybe_copy (data->context,
+                                                           "input", &data->roi);
+    }
+
   if (!data->klass->process (data->operation,
-        data->input, data->aux, data->aux2, 
-        data->output, &data->roi, data->level))
+                             input, data->aux, data->aux2, 
+                             data->output, &data->roi, data->level))
     data->success = FALSE;
+
+  g_object_unref (input);
+
   g_atomic_int_add (data->pending, -1);
 }
 
@@ -219,7 +229,7 @@ gegl_operation_composer3_process (GeglOperation        *operation,
         {
           thread_data[i].klass = klass;
           thread_data[i].operation = operation;
-          thread_data[i].input = input;
+          thread_data[i].context = context;
           thread_data[i].aux = aux;
           thread_data[i].aux2 = aux2;
           thread_data[i].output = output;
@@ -230,7 +240,7 @@ gegl_operation_composer3_process (GeglOperation        *operation,
 
         for (gint i = 1; i < threads; i++)
           g_thread_pool_push (pool, &thread_data[i], NULL);
-        thread_process (&thread_data[0], NULL);
+        thread_process (&thread_data[0], g_object_ref (input));
 
         while (g_atomic_int_get (&pending)) {};
         
diff --git a/gegl/operation/gegl-operation-filter.c b/gegl/operation/gegl-operation-filter.c
index 2d26610..5c63381 100644
--- a/gegl/operation/gegl-operation-filter.c
+++ b/gegl/operation/gegl-operation-filter.c
@@ -109,7 +109,7 @@ typedef struct ThreadData
 {
   GeglOperationFilterClass *klass;
   GeglOperation            *operation;
-  GeglBuffer               *input;
+  GeglOperationContext     *context;
   GeglBuffer               *output;
   gint                     *pending;
   gint                      level;
@@ -117,12 +117,22 @@ typedef struct ThreadData
   GeglRectangle             roi;
 } ThreadData;
 
-static void thread_process (gpointer thread_data, gpointer unused)
+static void thread_process (gpointer thread_data, gpointer input)
 {
   ThreadData *data = thread_data;
+
+  if (! input)
+    {
+      input = gegl_operation_context_dup_input_maybe_copy (data->context,
+                                                           "input", &data->roi);
+    }
+
   if (!data->klass->process (data->operation,
-                       data->input, data->output, &data->roi, data->level))
+                             input, data->output, &data->roi, data->level))
     data->success = FALSE;
+
+  g_object_unref (input);
+
   g_atomic_int_add (data->pending, -1);
 }
 
@@ -219,7 +229,7 @@ gegl_operation_filter_process (GeglOperation        *operation,
     {
       thread_data[i].klass = klass;
       thread_data[i].operation = operation;
-      thread_data[i].input = input;
+      thread_data[i].context = context;
       thread_data[i].output = output;
       thread_data[i].pending = &pending;
       thread_data[i].level = level;
@@ -228,7 +238,7 @@ gegl_operation_filter_process (GeglOperation        *operation,
 
     for (gint i = 1; i < threads; i++)
       g_thread_pool_push (pool, &thread_data[i], NULL);
-    thread_process (&thread_data[0], NULL);
+    thread_process (&thread_data[0], g_object_ref (input));
 
     while (g_atomic_int_get (&pending)) {};
 
diff --git a/operations/transform/transform-core.c b/operations/transform/transform-core.c
index e31ddd9..34c6606 100644
--- a/operations/transform/transform-core.c
+++ b/operations/transform/transform-core.c
@@ -749,7 +749,7 @@ typedef struct ThreadData
 
 
   GeglOperation            *operation;
-  GeglBuffer               *input;
+  GeglOperationContext     *context;
   GeglBuffer               *output;
   gint                     *pending;
   GeglMatrix3              *matrix;
@@ -758,16 +758,25 @@ typedef struct ThreadData
   GeglRectangle             roi;
 } ThreadData;
 
-static void thread_process (gpointer thread_data, gpointer unused)
+static void thread_process (gpointer thread_data, gpointer input)
 {
   ThreadData *data = thread_data;
+
+  if (! input)
+    {
+      input = gegl_operation_context_dup_input_maybe_copy (data->context,
+                                                           "input", &data->roi);
+    }
+
   data->func (data->operation,
               data->output,
-              data->input,
+              input,
               data->matrix,
               &data->roi,
               data->level);
-    data->success = FALSE;
+
+  g_object_unref (input);
+
   g_atomic_int_add (data->pending, -1);
 }
 
@@ -1255,7 +1264,7 @@ gegl_transform_process (GeglOperation        *operation,
           thread_data[i].func = func;
           thread_data[i].matrix = &matrix;
           thread_data[i].operation = operation;
-          thread_data[i].input = input;
+          thread_data[i].context = context;
           thread_data[i].output = output;
           thread_data[i].pending = &pending;
           thread_data[i].level = level;
@@ -1264,7 +1273,7 @@ gegl_transform_process (GeglOperation        *operation,
 
         for (gint i = 1; i < threads; i++)
           g_thread_pool_push (pool, &thread_data[i], NULL);
-        thread_process (&thread_data[0], NULL);
+        thread_process (&thread_data[0], g_object_ref (input));
 
         while (g_atomic_int_get (&pending)) {};
       }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]