[Bf-blender-cvs] [12518c12bc3] cycles-x: Cycles X: Extend multi-device rebalancing scheduler API

Sergey Sharybin noreply at git.blender.org
Tue Jul 13 12:10:23 CEST 2021


Commit: 12518c12bc349a092f31519af9c5dc1299eccbae
Author: Sergey Sharybin
Date:   Tue Jul 13 10:39:46 2021 +0200
Branches: cycles-x
https://developer.blender.org/rB12518c12bc349a092f31519af9c5dc1299eccbae

Cycles X: Extend multi-device rebalancing scheduler API

Communicate more information about whether rebalancing is needed,
whether balance across device did change. Currently no functional
changes, but this change allows to make the logic smarter and get
more performance out of a compute.

No functional changes, just exposing extra things and making
statistics more usable for a more elaborate logic.

===================================================================

M	intern/cycles/integrator/path_trace.cpp
M	intern/cycles/integrator/render_scheduler.cpp
M	intern/cycles/integrator/render_scheduler.h

===================================================================

diff --git a/intern/cycles/integrator/path_trace.cpp b/intern/cycles/integrator/path_trace.cpp
index 34fa56691dc..1b170cdf567 100644
--- a/intern/cycles/integrator/path_trace.cpp
+++ b/intern/cycles/integrator/path_trace.cpp
@@ -66,6 +66,8 @@ PathTrace::PathTrace(Device *device, DeviceScene *device_scene, RenderScheduler
 
   work_balance_infos_.resize(path_trace_works_.size());
   work_balance_do_initial(work_balance_infos_);
+
+  render_scheduler.set_need_schedule_rebalance(path_trace_works_.size() > 1);
 }
 
 void PathTrace::load_kernels()
@@ -563,6 +565,7 @@ void PathTrace::rebalance(const RenderWork &render_work)
 
   if (!did_rebalance) {
     VLOG(kLogLevel) << "Balance in path trace works did not change.";
+    render_scheduler_.report_rebalance_time(render_work, time_dt() - start_time, false);
     return;
   }
 
@@ -576,7 +579,7 @@ void PathTrace::rebalance(const RenderWork &render_work)
 
   copy_from_render_buffers(big_tile_cpu_buffers.buffers.get());
 
-  render_scheduler_.report_rebalance_time(render_work, time_dt() - start_time);
+  render_scheduler_.report_rebalance_time(render_work, time_dt() - start_time, true);
 }
 
 void PathTrace::cancel()
diff --git a/intern/cycles/integrator/render_scheduler.cpp b/intern/cycles/integrator/render_scheduler.cpp
index d6da5cfabfa..76331d8618a 100644
--- a/intern/cycles/integrator/render_scheduler.cpp
+++ b/intern/cycles/integrator/render_scheduler.cpp
@@ -35,6 +35,11 @@ RenderScheduler::RenderScheduler(bool headless, bool background, int pixel_size)
   use_progressive_noise_floor_ = !background_;
 }
 
+void RenderScheduler::set_need_schedule_rebalance(bool need_schedule_rebalance)
+{
+  need_schedule_rebalance_works_ = need_schedule_rebalance;
+}
+
 bool RenderScheduler::is_background() const
 {
   return background_;
@@ -116,6 +121,9 @@ void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples)
   state_.last_display_update_sample = -1;
 
   state_.last_rebalance_time = 0.0;
+  state_.num_rebalance_requested = 0;
+  state_.num_rebalance_changes = 0;
+  state_.last_rebalance_changed = false;
 
   /* TODO(sergey): Choose better initial value. */
   /* NOTE: The adaptive sampling settings might not be available here yet. */
@@ -230,6 +238,13 @@ RenderWork RenderScheduler::get_render_work()
 
   render_work.init_render_buffers = (render_work.path_trace.start_sample == get_start_sample());
 
+  /* NOTE: Rebalance scheduler requires current number of samples to not be advanced forward. */
+  render_work.rebalance = work_need_rebalance();
+  if (render_work.rebalance) {
+    state_.last_rebalance_time = time_now;
+    ++state_.num_rebalance_requested;
+  }
+
   /* NOTE: Advance number of samples now, so that filter and denoising check can see that all the
    * samples are rendered. */
   state_.num_rendered_samples += render_work.path_trace.num_samples;
@@ -250,11 +265,6 @@ RenderWork RenderScheduler::get_render_work()
     state_.last_display_update_sample = state_.num_rendered_samples;
   }
 
-  render_work.rebalance = work_need_rebalance();
-  if (render_work.rebalance) {
-    state_.last_rebalance_time = time_now;
-  }
-
   return render_work;
 }
 
@@ -362,7 +372,9 @@ void RenderScheduler::report_display_update_time(const RenderWork &render_work,
   state_.last_display_update_time = time_dt();
 }
 
-void RenderScheduler::report_rebalance_time(const RenderWork &render_work, double time)
+void RenderScheduler::report_rebalance_time(const RenderWork &render_work,
+                                            double time,
+                                            bool balance_changed)
 {
   rebalance_time_.add_wall(time);
 
@@ -372,6 +384,12 @@ void RenderScheduler::report_rebalance_time(const RenderWork &render_work, doubl
 
   rebalance_time_.add_average(time);
 
+  if (balance_changed) {
+    ++state_.num_rebalance_changes;
+  }
+
+  state_.last_rebalance_changed = balance_changed;
+
   VLOG(4) << "Average rebalance time: " << rebalance_time_.get_average() << " seconds.";
 }
 
@@ -424,6 +442,14 @@ string RenderScheduler::full_report() const
     result += "  Passes: " + passes + "\n";
   }
 
+  if (state_.num_rebalance_requested) {
+    result += "\nRebalancer:\n";
+    result += "  Number of requested rebalances: " + to_string(state_.num_rebalance_requested) +
+              "\n";
+    result += "  Number of performed rebalances: " + to_string(state_.num_rebalance_changes) +
+              "\n";
+  }
+
   result += "\nTime (in seconds):\n";
   result += string_printf("  %20s %20s %20s\n", "", "Wall", "Average");
   result += string_printf("  %20s %20f %20f\n",
@@ -448,8 +474,7 @@ string RenderScheduler::full_report() const
                           display_update_time_.get_wall(),
                           display_update_time_.get_average());
 
-  const int num_rebalance_observations = rebalance_time_.get_num_observations();
-  if (num_rebalance_observations) {
+  if (state_.num_rebalance_requested) {
     result += string_printf("  %20s %20f %20f\n",
                             "Rebalance",
                             rebalance_time_.get_wall(),
@@ -460,10 +485,6 @@ string RenderScheduler::full_report() const
                             denoise_time_.get_wall() + display_update_time_.get_wall();
   result += "\n  Total: " + to_string(total_time) + "\n";
 
-  if (num_rebalance_observations) {
-    result += "\nNumber of performed rebalances: " + to_string(num_rebalance_observations) + "\n";
-  }
-
   result += string_printf(
       "\nRendered %d samples in %f seconds\n", num_rendered_samples, render_wall_time);
 
@@ -756,6 +777,10 @@ bool RenderScheduler::work_need_rebalance()
    * work. */
   static const double kRebalanceIntervalInSeconds = 1;
 
+  if (!need_schedule_rebalance_works_) {
+    return false;
+  }
+
   if (state_.resolution_divider != pixel_size_) {
     /* Don't rebalance at a non-final resolution divider. Some reasons for this:
      *  - It will introduce unnecessary during navigation.
@@ -763,7 +788,7 @@ bool RenderScheduler::work_need_rebalance()
     return false;
   }
 
-  if (state_.num_rendered_samples == 1) {
+  if (state_.num_rendered_samples == 0) {
     return true;
   }
 
diff --git a/intern/cycles/integrator/render_scheduler.h b/intern/cycles/integrator/render_scheduler.h
index 2c7c72ba9b6..622ad8ada39 100644
--- a/intern/cycles/integrator/render_scheduler.h
+++ b/intern/cycles/integrator/render_scheduler.h
@@ -70,6 +70,10 @@ class RenderScheduler {
  public:
   RenderScheduler(bool headless, bool background, int pixel_size);
 
+  /* Allows to disable work re-balancing works, allowing to schedule as much to a single device
+   * as possible. */
+  void set_need_schedule_rebalance(bool need_schedule_rebalance);
+
   bool is_background() const;
 
   void set_denoiser_params(const DenoiseParams &params);
@@ -136,7 +140,7 @@ class RenderScheduler {
   void report_adaptive_filter_time(const RenderWork &render_work, double time, bool is_cancelled);
   void report_denoise_time(const RenderWork &render_work, double time);
   void report_display_update_time(const RenderWork &render_work, double time);
-  void report_rebalance_time(const RenderWork &render_work, double time);
+  void report_rebalance_time(const RenderWork &render_work, double time, bool balance_changed);
 
   /* Generate full multi-line report of the rendering process, including rendering parameters,
    * times, and so on. */
@@ -258,11 +262,6 @@ class RenderScheduler {
       num_average_times_ = 0;
     }
 
-    inline int get_num_observations() const
-    {
-      return num_average_times_;
-    }
-
    protected:
     double total_wall_time_ = 0.0;
 
@@ -284,6 +283,17 @@ class RenderScheduler {
     /* Point in time at which last rebalance has been performed. */
     double last_rebalance_time = 0.0;
 
+    /* Number of rebalance works which has been requested to be performed.
+     * The path tracer might ignore the work if there is a single device rendering. */
+    int num_rebalance_requested = 0;
+
+    /* Number of rebalance works handled which did change balance across devices. */
+    int num_rebalance_changes = 0;
+
+    /* Denotes whether the latest performed rebalance work cause an actual rebalance of work across
+     * devices. */
+    bool last_rebalance_changed = false;
+
     /* Threshold for adaptive sampling which will be scheduled to work when not using progressive
      * noise floor. */
     float adaptive_sampling_threshold = 0.0f;
@@ -311,6 +321,12 @@ class RenderScheduler {
   TimeWithAverage display_update_time_;
   TimeWithAverage rebalance_time_;
 
+  /* Whether to schedule device load rebalance works.
+   * Rebalancing requires some special treatment for update intervals and such, so if it's known
+   * that the rebalance will be ignored (due to single-device rendering i.e.) is better to fully
+   * ignore rebalancing logic. */
+  bool need_schedule_rebalance_works_ = false;
+
   /* Path tracing work will be scheduled for samples from within
    * [start_sample_, start_sample_ + num_samples_ - 1] range, inclusively. */
   int start_sample_ = 0;



More information about the Bf-blender-cvs mailing list