[gegl] gegl/buffer: make shape and offset of sampler prefetch adaptive



commit f606e8f961c86da0e867ca4920ab77efbef89bcd
Author: Øyvind Kolås <pippin gimp org>
Date:   Fri Jan 5 02:13:41 2018 +0100

    gegl/buffer: make shape and offset of sampler prefetch adaptive
    
    This makes reuse of prefetched data more likely, for the rotate test-case in
    perf it doubles the throughput.

 gegl/buffer/gegl-sampler.c |   97 ++++++++++----------------------------------
 gegl/buffer/gegl-sampler.h |   23 ++++++++---
 2 files changed, 39 insertions(+), 81 deletions(-)
---
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index 972b1fe..6c7062c 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -254,89 +254,36 @@ GeglRectangle _gegl_sampler_compute_rectangle (GeglSampler *sampler,
   GeglRectangle rectangle;
   GeglSamplerLevel *level = &sampler->level[level_no];
 
-  if (level->last_x || level->last_y)
-  {
-    gint x_delta = x - level->last_x;
-    gint y_delta = y - level->last_y;
-    gint max_delta_squared = 60 * 60;
-
-    if (x_delta * x_delta < max_delta_squared &&
-        y_delta * y_delta < max_delta_squared)
-    {
-      level->x_delta = level->x_delta * 0.99 + x_delta * 0.01;
-      level->y_delta = level->y_delta * 0.99 + y_delta * 0.01;
-      if (x_delta < 0) x_delta = -x_delta;
-      if (y_delta < 0) y_delta = -y_delta;
-      level->x_magnitude = level->x_magnitude  * 0.99 + x_delta * 0.01;
-      level->y_magnitude = level->y_magnitude  * 0.99 + y_delta * 0.01;
-    }
-  }
-  level->last_x = x;
-  level->last_y = y;
-
   rectangle.width  = level->context_rect.width + 2;
   rectangle.height = level->context_rect.height + 2;
 
+  /* grow in direction of prediction */
+  if (level->delta_x * level->delta_x >
+      level->delta_y * level->delta_y)
+  {
+    rectangle.width *= 2;
+  }
+  else
+  {
+    rectangle.height *= 2;
+  }
+
   rectangle.x = x + level->context_rect.x;
   rectangle.y = y + level->context_rect.y;
 
-  /* grow area slightly, maybe getting a couple of extra
-     hits out of cour cache
-   */
-  rectangle.x      -= 2;
-  rectangle.y      -= 2;
-  rectangle.width  += 4;
-  rectangle.height += 4;
-
-#if 0
-  /* XXX: FIXME: grow cached area based on sampling pattern profiling
-   * information, possibly with much bigger wins than the marginal wins the
-   * increase in size by 2 in each dir does.
-   */
-
-
-  if (level->x_magnitude > 0.001 || level->y_magnitude > 0.001)
-    {
-      gfloat magnitude = sqrtf (level->x_magnitude * level->x_magnitude +
-                                level->y_magnitude * level->y_magnitude);
-      gfloat new_magnitude;
-
-      if (level->x_magnitude > level->y_magnitude)
-        new_magnitude =
-          4 + 60 * (level->x_magnitude - level->y_magnitude) / level->x_magnitude;
-      else
-        new_magnitude =
-          4 + 60 * (level->y_magnitude - level->x_magnitude) / level->y_magnitude;
-
-      rectangle.width = 
-        (level->x_magnitude / magnitude) * new_magnitude
-        + level->context_rect.width + 2;
-      rectangle.height = 
-        (level->y_magnitude / magnitude) * new_magnitude
-        + level->context_rect.height + 2;
-
-      /* todo: if both xmag and ymag are small - but similar in magnitude 
-         we should increase the size of the cache if it would fit, thus
-         perhaps working better on small local non-linear access patterns
-       */
-
+  rectangle.x      -= 1;
+  rectangle.y      -= 1;
+  rectangle.width  += 2;
+  rectangle.height += 2;
 
-      /* align rectangle corner we've likely entered with sampled pixel
-       */
-      if (level->x_delta >=0)
-        rectangle.x = x + level->context_rect.x
-                        - (rectangle.width - level->context_rect.x)/10;
-      else
-        rectangle.x = x + level->context_rect.x
-                        - (rectangle.width - level->context_rect.width) * 9/10;
+  //fprintf (stderr, "{%f %f}", level->delta_x, level->delta_y);
 
-      if (level->y_delta >=0)
-        rectangle.y = y + level->context_rect.y
-                        - (rectangle.height - level->context_rect.y)/10;
-      else
-        rectangle.y = y + level->context_rect.y 
-                        - (rectangle.height - level->context_rect.height) * 9/10;
-    }
+#if 1
+  /* shift area based on prediction */
+  if (level->delta_x >=0.01)
+    rectangle.x -= rectangle.width * 0.3;
+  if (level->delta_y >=0.01)
+    rectangle.y -= rectangle.height * 0.3;
 #endif
 
   if (rectangle.width >= GEGL_SAMPLER_MAXIMUM_WIDTH)
diff --git a/gegl/buffer/gegl-sampler.h b/gegl/buffer/gegl-sampler.h
index f3464ff..efb9e08 100644
--- a/gegl/buffer/gegl-sampler.h
+++ b/gegl/buffer/gegl-sampler.h
@@ -20,6 +20,7 @@
 
 #include <glib-object.h>
 #include <babl/babl.h>
+#include <stdio.h>
 
 G_BEGIN_DECLS
 
@@ -52,13 +53,10 @@ typedef struct GeglSamplerLevel
   GeglRectangle  context_rect;
   gpointer       sampler_buffer;
   GeglRectangle  sampler_rectangle;
-
   gint           last_x;
   gint           last_y;
-  float          x_delta;
-  float          y_delta;
-  float          x_magnitude;
-  float          y_magnitude;
+  float          delta_x;
+  float          delta_y;
 } GeglSamplerLevel;
 
 struct _GeglSampler
@@ -126,6 +124,7 @@ gegl_sampler_get_ptr (GeglSampler    *sampler,
                       gint            y,
                       GeglAbyssPolicy repeat_mode)
 {
+  float delta_x, delta_y;
   gint dx, dy, sof;
   guchar *buffer_ptr;
 
@@ -137,7 +136,8 @@ gegl_sampler_get_ptr (GeglSampler    *sampler,
       (y + level->context_rect.y + level->context_rect.height >
        level->sampler_rectangle.y + level->sampler_rectangle.height))
     {
-      level->sampler_rectangle = _gegl_sampler_compute_rectangle (sampler, x, y, 0);
+      level->sampler_rectangle =
+         _gegl_sampler_compute_rectangle (sampler, x, y, 0);
 
       gegl_buffer_get (sampler->buffer,
                        &level->sampler_rectangle,
@@ -146,6 +146,10 @@ gegl_sampler_get_ptr (GeglSampler    *sampler,
                        level->sampler_buffer,
                        GEGL_SAMPLER_MAXIMUM_WIDTH * GEGL_SAMPLER_BPP,
                        repeat_mode);
+      level->last_x = x;
+      level->last_y = y;
+      level->delta_x = 0;
+      level->delta_y = 0;
     }
 
   dx         = x - level->sampler_rectangle.x;
@@ -153,6 +157,13 @@ gegl_sampler_get_ptr (GeglSampler    *sampler,
   sof        = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * GEGL_SAMPLER_BPP;
   buffer_ptr = (guchar *) level->sampler_buffer;
 
+  delta_x = level->last_x - x;
+  delta_y = level->last_y - y;
+  level->last_x = x;
+  level->last_y = y;
+  level->delta_x = (level->delta_x + delta_x) / 2;
+  level->delta_y = (level->delta_y + delta_y) / 2;
+
   return (gfloat *) (buffer_ptr + sof);
 }
 


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