[gegl] Made the number of threads configurable.



commit e3e11f3f9d72daf377d1b1e88fee7e83bc60356a
Author: �yvind Kolås <pippin gimp org>
Date:   Sun Nov 22 16:11:32 2009 +0000

    Made the number of threads configurable.
    
    Added a threads member to GeglConfig which is picked up by
    environment variable or commandline. Default value 2.

 gegl/buffer/gegl-cache.c            |    1 +
 gegl/gegl-config.c                  |   26 +++++++++++++++++++++++++-
 gegl/gegl-config.h                  |    3 +++
 gegl/gegl-init.c                    |   19 ++++++++++++++++++-
 gegl/gegl-instrument.c              |    2 --
 gegl/graph/gegl-node.c              |    6 +++++-
 gegl/operation/gegl-operation.c     |   12 +++++++++++-
 gegl/process/gegl-eval-mgr.c        |    4 +++-
 gegl/process/gegl-have-visitor.c    |    6 ++++++
 gegl/process/gegl-prepare-visitor.c |   12 ++++++++++++
 gegl/property-types/gegl-path.c     |    2 +-
 operations/external/path.c          |    4 +++-
 12 files changed, 88 insertions(+), 9 deletions(-)
---
diff --git a/gegl/buffer/gegl-cache.c b/gegl/buffer/gegl-cache.c
index 356330a..4b4be21 100644
--- a/gegl/buffer/gegl-cache.c
+++ b/gegl/buffer/gegl-cache.c
@@ -33,6 +33,7 @@
 #include "gegl-cache.h"
 #include "gegl-region.h"
 
+#undef ENABLE_MT
 #if ENABLE_MT
 static GStaticRecMutex mutex = G_STATIC_REC_MUTEX_INIT;
 #endif
diff --git a/gegl/gegl-config.c b/gegl/gegl-config.c
index 5f61a02..74a5365 100644
--- a/gegl/gegl-config.c
+++ b/gegl/gegl-config.c
@@ -19,7 +19,7 @@
 #include <glib-object.h>
 #include <string.h>
 #include <glib/gprintf.h>
-
+#include "config.h"
 #include "gegl.h"
 #include "gegl-types-internal.h"
 #include "gegl-config.h"
@@ -38,6 +38,9 @@ enum
   PROP_BABL_TOLERANCE,
   PROP_TILE_WIDTH,
   PROP_TILE_HEIGHT
+#if ENABLE_MT
+  ,PROP_THREADS
+#endif
 };
 
 static void
@@ -78,6 +81,12 @@ get_property (GObject    *gobject,
         g_value_set_string (value, config->swap);
         break;
 
+#if ENABLE_MT
+      case PROP_THREADS:
+        g_value_set_int (value, config->threads);
+        break;
+#endif
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
@@ -126,6 +135,11 @@ set_property (GObject      *gobject,
          g_free (config->swap);
         config->swap = g_value_dup_string (value);
         break;
+#if ENABLE_MT
+      case PROP_THREADS:
+        config->threads = g_value_get_int (value);
+        return;
+#endif
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
@@ -190,6 +204,13 @@ gegl_config_class_init (GeglConfigClass *klass)
   g_object_class_install_property (gobject_class, PROP_SWAP,
                                    g_param_spec_string ("swap", "Swap", "where gegl stores it's swap files", NULL,
                                                      G_PARAM_READWRITE));
+
+#if ENABLE_MT
+  g_object_class_install_property (gobject_class, PROP_TILE_HEIGHT,
+                                   g_param_spec_int ("threads", "Number of concurrent evaluation threads", "default tile height for created buffers.",
+                                                     0, 16, 2,
+                                                     G_PARAM_READWRITE));
+#endif
 }
 
 static void
@@ -201,4 +222,7 @@ gegl_config_init (GeglConfig *self)
   self->chunk_size  = 512 * 512;
   self->tile_width  = 64;
   self->tile_height = 128;
+#if ENABLE_MT
+  self->threads = 2;
+#endif
 }
diff --git a/gegl/gegl-config.h b/gegl/gegl-config.h
index 4ec92d1..f7bbd46 100644
--- a/gegl/gegl-config.h
+++ b/gegl/gegl-config.h
@@ -44,6 +44,9 @@ struct _GeglConfig
   gdouble  babl_tolerance;
   gint     tile_width;
   gint     tile_height;
+#if ENABLE_MT
+  gint     threads;
+#endif
 };
 
 struct _GeglConfigClass
diff --git a/gegl/gegl-init.c b/gegl/gegl-init.c
index 81e0fba..950f27a 100644
--- a/gegl/gegl-init.c
+++ b/gegl/gegl-init.c
@@ -205,6 +205,9 @@ static gchar   *cmd_gegl_chunk_size=NULL;
 static gchar   *cmd_gegl_quality=NULL;
 static gchar   *cmd_gegl_tile_size=NULL;
 static gchar   *cmd_babl_tolerance =NULL;
+#if ENABLE_MT
+static gchar   *cmd_gegl_threads=NULL;
+#endif
 
 static const GOptionEntry cmd_entries[]=
 {
@@ -238,6 +241,13 @@ static const GOptionEntry cmd_entries[]=
      G_OPTION_ARG_STRING, &cmd_gegl_quality,
      N_("The quality of rendering a value between 0.0(fast) and 1.0(reference)"), "<quality>"
     },
+#if ENABLE_MT
+    {
+     "gegl-threads", 0, 0,
+     G_OPTION_ARG_STRING, &cmd_gegl_threads,
+     N_("The number of concurrent processing threads to use."), "<threads>"
+    },
+#endif
     { NULL }
 };
 
@@ -284,6 +294,10 @@ GeglConfig *gegl_config (void)
           if (str)
             config->tile_height = atoi(str+1);
         }
+#if ENABLE_MT
+      if (g_getenv ("GEGL_THREADS"))
+        config->threads = atoi(g_getenv("GEGL_THREADS"));
+#endif
       if (gegl_swap_dir())
         config->swap = g_strdup(gegl_swap_dir ());
     }
@@ -476,7 +490,10 @@ gegl_post_parse_hook (GOptionContext *context,
       if (str)
         config->tile_height = atoi(str+1);
     }
-
+#if ENABLE_MT
+  if (cmd_gegl_threads)
+    config->threads = atoi (cmd_gegl_threads);
+#endif
   if (cmd_babl_tolerance)
     g_object_set (config, "babl-tolerance", atof(cmd_babl_tolerance), NULL);
 
diff --git a/gegl/gegl-instrument.c b/gegl/gegl-instrument.c
index 2683274..1292b67 100644
--- a/gegl/gegl-instrument.c
+++ b/gegl/gegl-instrument.c
@@ -104,8 +104,6 @@ gegl_instrument (const gchar *parent_name,
   Timing *iter;
   Timing *parent;
 
-  return;
-
   if (root == NULL)
     {
       root       = g_slice_new0 (Timing);
diff --git a/gegl/graph/gegl-node.c b/gegl/graph/gegl-node.c
index d0f9df8..37e5470 100644
--- a/gegl/graph/gegl-node.c
+++ b/gegl/graph/gegl-node.c
@@ -33,6 +33,7 @@
 #include "gegl-pad.h"
 #include "gegl-utils.h"
 #include "gegl-visitable.h"
+#include "gegl-config.h"
 
 #include "operation/gegl-operation.h"
 #include "operation/gegl-operations.h"
@@ -916,12 +917,15 @@ gegl_node_blit (GeglNode            *self,
                 gint                 rowstride,
                 GeglBlitFlags        flags)
 {
+#if ENABLE_MT
   gint threads;
+#endif
   g_return_if_fail (GEGL_IS_NODE (self));
   g_return_if_fail (roi != NULL);
 
-  threads = 2; /* tunable here for now, should be picked up through GeglConfig */
 #if ENABLE_MT
+  threads = gegl_config ()->threads;
+  
   if (pool == NULL)
     {
       pool = g_thread_pool_new (spawnrender, NULL, threads, TRUE, NULL);
diff --git a/gegl/operation/gegl-operation.c b/gegl/operation/gegl-operation.c
index 8df8e70..caf0fc0 100644
--- a/gegl/operation/gegl-operation.c
+++ b/gegl/operation/gegl-operation.c
@@ -276,7 +276,17 @@ gegl_operation_source_get_bounding_box (GeglOperation  *operation,
   GeglNode *node = gegl_operation_get_source_node (operation, input_pad_name);
 
   if (node)
-    return &node->have_rect;
+    {
+      GeglRectangle *ret;
+#if ENABLE_MT
+      g_mutex_lock (node->mutex);
+#endif
+      ret = &node->have_rect;
+#if ENABLE_MT
+      g_mutex_unlock (node->mutex);
+#endif
+      return ret;
+    }
 
   return NULL;
 }
diff --git a/gegl/process/gegl-eval-mgr.c b/gegl/process/gegl-eval-mgr.c
index b8a4ab7..9c96ff0 100644
--- a/gegl/process/gegl-eval-mgr.c
+++ b/gegl/process/gegl-eval-mgr.c
@@ -163,6 +163,7 @@ gegl_eval_mgr_apply (GeglEvalMgr *self)
         gegl_visitor_reset (self->have_visitor);
         gegl_visitor_dfs_traverse (self->have_visitor, GEGL_VISITABLE (root));
       case NEED_CONTEXT_SETUP_TRAVERSAL:
+
         gegl_visitor_reset (self->prepare_visitor);
         gegl_visitor_dfs_traverse (self->prepare_visitor, GEGL_VISITABLE (root));      
         self->state = NEED_CONTEXT_SETUP_TRAVERSAL;
@@ -209,7 +210,8 @@ gegl_eval_mgr_apply (GeglEvalMgr *self)
     { /* pull on the input of our sink if no pad of the given pad-name
          was available, we take this as an indication that we're in fact
          doing processing on a sink (and the ROI inidcates the data to
-         be written.
+         be written, note that GEGL might subdivide this roi
+         in its processing.
        */
       GeglPad *pad = gegl_node_get_pad (root, "input");
       gegl_visitor_dfs_traverse (self->eval_visitor, GEGL_VISITABLE (pad));
diff --git a/gegl/process/gegl-have-visitor.c b/gegl/process/gegl-have-visitor.c
index 850e7b2..28e9cac 100644
--- a/gegl/process/gegl-have-visitor.c
+++ b/gegl/process/gegl-have-visitor.c
@@ -64,9 +64,15 @@ gegl_have_visitor_visit_node (GeglVisitor *self,
   if (!node)
     return;
   operation = node->operation;
+#if ENABLE_MT
+  g_mutex_lock (node->mutex);
+#endif
   rect = gegl_operation_get_bounding_box (operation);
 
   node->have_rect = rect;
+#if ENABLE_MT
+  g_mutex_unlock (node->mutex);
+#endif
 
   time = gegl_ticks () - time;
   gegl_instrument ("process", gegl_node_get_operation (node), time);
diff --git a/gegl/process/gegl-prepare-visitor.c b/gegl/process/gegl-prepare-visitor.c
index 91be7f5..e430c49 100644
--- a/gegl/process/gegl-prepare-visitor.c
+++ b/gegl/process/gegl-prepare-visitor.c
@@ -80,15 +80,27 @@ gegl_prepare_visitor_visit_node (GeglVisitor *self,
         g_assert (graph);
         if (GEGL_NODE (graph)->operation)
           {
+#if ENABLE_MT
+            g_mutex_lock (GEGL_NODE (graph)->mutex);
+#endif
             /* issuing a prepare on the graph, FIXME: we might need to do
              * a cycle of prepares as deep as the nesting of graphs,.
              * (or find a better way to do this) */
             gegl_operation_prepare (GEGL_NODE (graph)->operation);
+#if ENABLE_MT
+            g_mutex_unlock (GEGL_NODE (graph)->mutex);
+#endif
           }
       }
   }
 
+#if ENABLE_MT
+  g_mutex_lock (node->mutex);
+#endif
   gegl_operation_prepare (operation);
+#if ENABLE_MT
+  g_mutex_unlock (node->mutex);
+#endif
   {
     /* initialise the "needed rectangle" to an empty one */
     GeglRectangle empty ={0,};
diff --git a/gegl/property-types/gegl-path.c b/gegl/property-types/gegl-path.c
index 88c8a9a..7d94c4a 100644
--- a/gegl/property-types/gegl-path.c
+++ b/gegl/property-types/gegl-path.c
@@ -1961,7 +1961,7 @@ static void gegl_path_stamp (GeglBuffer *buffer,
                              gdouble     opacity)
 {
   gfloat col[4];
-  static StampStatic s = {FALSE,}; /* XXX: 
+  StampStatic s = {FALSE,}; /* XXX: 
                                       we will ultimately leak the last valid
                                       cached brush. */
 
diff --git a/operations/external/path.c b/operations/external/path.c
index d689bfa..30b63ff 100644
--- a/operations/external/path.c
+++ b/operations/external/path.c
@@ -187,10 +187,11 @@ process (GeglOperation       *operation,
       a *= o->fill_opacity;
       if (a>0.001)
         {
+          GStaticMutex mutex = G_STATIC_MUTEX_INIT;
           cairo_t *cr;
           cairo_surface_t *surface;
+          g_static_mutex_lock (&mutex);
           guchar *data = (void*)gegl_buffer_linear_open (output, result, NULL, babl_format ("B'aG'aR'aA u8"));
-
           surface = cairo_image_surface_create_for_data (data,
                                                          CAIRO_FORMAT_ARGB32,
                                                          result->width,
@@ -220,6 +221,7 @@ process (GeglOperation       *operation,
       }
 #endif
 
+          g_static_mutex_unlock (&mutex);
           gegl_buffer_linear_close (output, data);
         }
     }



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