aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-05-04 03:07:07 -0400
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2019-05-07 05:46:19 -0400
commit2564fe708b580c1ef12b2b527ab6e8afe11ad444 (patch)
treef960f2d11cce237fe776d2c0974ea28b3012957a
parente766fde6511e2be83acbca1d603035e08de23f3b (diff)
drm/i915: Disable semaphore busywaits on saturated systems
Asking the GPU to busywait on a memory address, perhaps not unexpectedly in hindsight for a shared system, leads to bus contention that affects CPU programs trying to concurrently access memory. This can manifest as a drop in transcode throughput on highly over-saturated workloads. The only clue offered by perf, is that the bus-cycles (perf stat -e bus-cycles) jumped by 50% when enabling semaphores. This corresponds with extra CPU active cycles being attributed to intel_idle's mwait. This patch introduces a heuristic to try and detect when more than one client is submitting to the GPU pushing it into an oversaturated state. As we already keep track of when the semaphores are signaled, we can inspect their state on submitting the busywait batch and if we planned to use a semaphore but were too late, conclude that the GPU is overloaded and not try to use semaphores in future requests. In practice, this means we optimistically try to use semaphores for the first frame of a transcode job split over multiple engines, and fail if there are multiple clients active and continue not to use semaphores for the subsequent frames in the sequence. Periodically, we try to optimistically switch semaphores back on whenever the client waits to catch up with the transcode results. With 1 client, on Broxton J3455, with the relative fps normalized by %cpu: x no semaphores + drm-tip * patched +------------------------------------------------------------------------+ | * | | *+ | | **+ | | **+ x | | x * +**+ x | | x x * * +***x xx | | x x * * *+***x *x | | x x* + * * *****x *x x | | + x xx+x* + *** * ********* x * | | + x xx+x* * *** +** ********* xx * | | * + ++++* + x*x****+*+* ***+*************+x* * | |*+ +** *+ + +* + *++****** *xxx**********x***+*****************+*++ *| | |__________A_____M_____| | | |_______________A____M_________| | | |____________A___M________| | +------------------------------------------------------------------------+ N Min Max Median Avg Stddev x 120 2.60475 3.50941 3.31123 3.2143953 0.21117399 + 120 2.3826 3.57077 3.25101 3.1414161 0.28146407 Difference at 95.0% confidence -0.0729792 +/- 0.0629585 -2.27039% +/- 1.95864% (Student's t, pooled s = 0.248814) * 120 2.35536 3.66713 3.2849 3.2059917 0.24618565 No difference proven at 95.0% confidence With 10 clients over-saturating the pipeline: x no semaphores + drm-tip * patched +------------------------------------------------------------------------+ | ++ ** | | ++ ** | | ++ ** | | ++ ** | | ++ xx *** | | ++ xx *** | | ++ xxx*** | | ++ xxx*** | | +++ xxx*** | | +++ xx**** | | +++ xx**** | | +++ xx**** | | +++ xx**** | | ++++ xx**** | | +++++ xx**** | | +++++ x x****** | | ++++++ xxx******* | | ++++++ xxx******* | | ++++++ xxx******* | | ++++++ xx******** | | ++++++ xxxx******** | | ++++++ xxxx******** | | ++++++++ xxxxx********* | |+ + + + ++++++++ xxx*xx**********x* *| | |__A__| | | |__AM__| | | |__A_| | +------------------------------------------------------------------------+ N Min Max Median Avg Stddev x 120 2.47855 2.8972 2.72376 2.7193402 0.074604933 + 120 1.17367 1.77459 1.71977 1.6966782 0.085850697 Difference at 95.0% confidence -1.02266 +/- 0.0203502 -37.607% +/- 0.748352% (Student's t, pooled s = 0.0804246) * 120 2.57868 3.00821 2.80142 2.7923878 0.058646477 Difference at 95.0% confidence 0.0730476 +/- 0.0169791 2.68622% +/- 0.624383% (Student's t, pooled s = 0.0671018) Indicating that we've recovered the regression from enabling semaphores on this saturated setup, with a hint towards an overall improvement. Very similar, but of smaller magnitude, results are observed on both Skylake(gt2) and Kabylake(gt4). This may be due to the reduced impact of bus-cycles, where we see a 50% hit on Broxton, it is only 10% on the big core, in this particular test. One observation to make here is that for a greedy client trying to maximise its own throughput, using semaphores is the right choice. It is only the holistic system-wide view that semaphores of one client impacts another and reduces the overall throughput where we would choose to disable semaphores. The most noticeable negactive impact this has is on the no-op microbenchmarks, which are also very notable for having no cpu bus load. In particular, this increases the runtime and energy consumption of gem_exec_whisper. Fixes: e88619646971 ("drm/i915: Use HW semaphores for inter-engine synchronisation on gen8+") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Dmitry Rogozhkin <dmitry.v.rogozhkin@intel.com> Cc: Dmitry Ermilov <dmitry.ermilov@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190504070707.30902-1-chris@chris-wilson.co.uk (cherry picked from commit ca6e56f654e7b241256ffba78cd2abb22aa3bc97) Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/i915_request.c40
-rw-r--r--drivers/gpu/drm/i915/intel_context.c1
-rw-r--r--drivers/gpu/drm/i915/intel_context_types.h3
3 files changed, 43 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 20c7c77b3768..ce342f7f7ddb 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -425,6 +425,26 @@ void __i915_request_submit(struct i915_request *request)
425 if (i915_gem_context_is_banned(request->gem_context)) 425 if (i915_gem_context_is_banned(request->gem_context))
426 i915_request_skip(request, -EIO); 426 i915_request_skip(request, -EIO);
427 427
428 /*
429 * Are we using semaphores when the gpu is already saturated?
430 *
431 * Using semaphores incurs a cost in having the GPU poll a
432 * memory location, busywaiting for it to change. The continual
433 * memory reads can have a noticeable impact on the rest of the
434 * system with the extra bus traffic, stalling the cpu as it too
435 * tries to access memory across the bus (perf stat -e bus-cycles).
436 *
437 * If we installed a semaphore on this request and we only submit
438 * the request after the signaler completed, that indicates the
439 * system is overloaded and using semaphores at this time only
440 * increases the amount of work we are doing. If so, we disable
441 * further use of semaphores until we are idle again, whence we
442 * optimistically try again.
443 */
444 if (request->sched.semaphores &&
445 i915_sw_fence_signaled(&request->semaphore))
446 request->hw_context->saturated |= request->sched.semaphores;
447
428 /* We may be recursing from the signal callback of another i915 fence */ 448 /* We may be recursing from the signal callback of another i915 fence */
429 spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); 449 spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING);
430 450
@@ -813,6 +833,24 @@ i915_request_await_start(struct i915_request *rq, struct i915_request *signal)
813 I915_FENCE_GFP); 833 I915_FENCE_GFP);
814} 834}
815 835
836static intel_engine_mask_t
837already_busywaiting(struct i915_request *rq)
838{
839 /*
840 * Polling a semaphore causes bus traffic, delaying other users of
841 * both the GPU and CPU. We want to limit the impact on others,
842 * while taking advantage of early submission to reduce GPU
843 * latency. Therefore we restrict ourselves to not using more
844 * than one semaphore from each source, and not using a semaphore
845 * if we have detected the engine is saturated (i.e. would not be
846 * submitted early and cause bus traffic reading an already passed
847 * semaphore).
848 *
849 * See the are-we-too-late? check in __i915_request_submit().
850 */
851 return rq->sched.semaphores | rq->hw_context->saturated;
852}
853
816static int 854static int
817emit_semaphore_wait(struct i915_request *to, 855emit_semaphore_wait(struct i915_request *to,
818 struct i915_request *from, 856 struct i915_request *from,
@@ -826,7 +864,7 @@ emit_semaphore_wait(struct i915_request *to,
826 GEM_BUG_ON(INTEL_GEN(to->i915) < 8); 864 GEM_BUG_ON(INTEL_GEN(to->i915) < 8);
827 865
828 /* Just emit the first semaphore we see as request space is limited. */ 866 /* Just emit the first semaphore we see as request space is limited. */
829 if (to->sched.semaphores & from->engine->mask) 867 if (already_busywaiting(to) & from->engine->mask)
830 return i915_sw_fence_await_dma_fence(&to->submit, 868 return i915_sw_fence_await_dma_fence(&to->submit,
831 &from->fence, 0, 869 &from->fence, 0,
832 I915_FENCE_GFP); 870 I915_FENCE_GFP);
diff --git a/drivers/gpu/drm/i915/intel_context.c b/drivers/gpu/drm/i915/intel_context.c
index 8931e0fee873..924cc556223a 100644
--- a/drivers/gpu/drm/i915/intel_context.c
+++ b/drivers/gpu/drm/i915/intel_context.c
@@ -230,6 +230,7 @@ intel_context_init(struct intel_context *ce,
230 ce->gem_context = ctx; 230 ce->gem_context = ctx;
231 ce->engine = engine; 231 ce->engine = engine;
232 ce->ops = engine->cops; 232 ce->ops = engine->cops;
233 ce->saturated = 0;
233 234
234 INIT_LIST_HEAD(&ce->signal_link); 235 INIT_LIST_HEAD(&ce->signal_link);
235 INIT_LIST_HEAD(&ce->signals); 236 INIT_LIST_HEAD(&ce->signals);
diff --git a/drivers/gpu/drm/i915/intel_context_types.h b/drivers/gpu/drm/i915/intel_context_types.h
index 68b4ca1611e0..339c7437fe82 100644
--- a/drivers/gpu/drm/i915/intel_context_types.h
+++ b/drivers/gpu/drm/i915/intel_context_types.h
@@ -14,6 +14,7 @@
14#include <linux/types.h> 14#include <linux/types.h>
15 15
16#include "i915_active_types.h" 16#include "i915_active_types.h"
17#include "intel_engine_types.h"
17 18
18struct i915_gem_context; 19struct i915_gem_context;
19struct i915_vma; 20struct i915_vma;
@@ -58,6 +59,8 @@ struct intel_context {
58 atomic_t pin_count; 59 atomic_t pin_count;
59 struct mutex pin_mutex; /* guards pinning and associated on-gpuing */ 60 struct mutex pin_mutex; /* guards pinning and associated on-gpuing */
60 61
62 intel_engine_mask_t saturated; /* submitting semaphores too late? */
63
61 /** 64 /**
62 * active_tracker: Active tracker for the external rq activity 65 * active_tracker: Active tracker for the external rq activity
63 * on this intel_context object. 66 * on this intel_context object.