Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Chris Wilson <chris@chris-wilson.co.uk>,
	Tvrtko Ursulin <tursulin@ursulin.net>,
	igt-dev@lists.freedesktop.org
Cc: Intel-gfx@lists.freedesktop.org
Subject: Re: [igt-dev] [Intel-gfx] [PATCH i-g-t 4/5] tests/perf_pmu: Add tests for engine queued/runnable/running stats
Date: Fri, 23 Mar 2018 10:08:05 +0000	[thread overview]
Message-ID: <87510b5a-221f-28f2-df6d-86bdac580f52@linux.intel.com> (raw)
In-Reply-To: <152149308453.3594.8973938010545694941@mail.alporthouse.com>


On 19/03/2018 20:58, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2018-03-19 18:22:04)
>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>
>> Simple tests to check reported queue depths are correct.
>>
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> ---
>>   tests/perf_pmu.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 224 insertions(+)
>>
>> diff --git a/tests/perf_pmu.c b/tests/perf_pmu.c
>> index 469b9becdbac..206c18960b7b 100644
>> --- a/tests/perf_pmu.c
>> +++ b/tests/perf_pmu.c
>> @@ -966,6 +966,196 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e)
>>          assert_within_epsilon(val[1], perf_slept[1], tolerance);
>>   }
>>   
>> +static double calc_queued(uint64_t d_val, uint64_t d_ns)
>> +{
>> +       return (double)d_val * 1e9 / I915_SAMPLE_QUEUED_DIVISOR / d_ns;
>> +}
>> +
>> +static void
>> +queued(int gem_fd, const struct intel_execution_engine2 *e)
>> +{
>> +       const unsigned long engine = e2ring(gem_fd, e);
>> +       const unsigned int max_rq = 10;
>> +       double queued[max_rq + 1];
>> +       uint32_t bo[max_rq + 1];
>> +       unsigned int n, i;
>> +       uint64_t val[2];
>> +       uint64_t ts[2];
>> +       int fd;
> 
> igt_require_sw_sync();
> 
> I guess we should do igt_require_cork(CORK_SYNC_FD) or something like
> that.
> 
>> +
>> +       memset(queued, 0, sizeof(queued));
>> +       memset(bo, 0, sizeof(bo));
>> +
>> +       fd = open_pmu(I915_PMU_ENGINE_QUEUED(e->class, e->instance));
>> +
>> +       for (n = 0; n <= max_rq; n++) {
>> +               int fence = -1;
>> +               struct igt_cork cork = { .fd = fence, .type = CORK_SYNC_FD };
> 
> IGT_CORK_FENCE(cork); if you prefer

Missed it.

> 
>> +
>> +               gem_quiescent_gpu(gem_fd);
>> +
>> +               if (n)
>> +                       fence = igt_cork_plug(&cork, -1);
>> +
>> +               for (i = 0; i < n; i++) {
>> +                       struct drm_i915_gem_exec_object2 obj = { };
>> +                       struct drm_i915_gem_execbuffer2 eb = { };
>> +
>> +                       if (!bo[i]) {
>> +                               const uint32_t bbe = MI_BATCH_BUFFER_END;
>> +
>> +                               bo[i] = gem_create(gem_fd, 4096);
>> +                               gem_write(gem_fd, bo[i], 4092, &bbe,
>> +                                         sizeof(bbe));
>> +                       }
>> +
>> +                       obj.handle = bo[i];
> 
> Looks like you can use just the one handle multiple times?

Hm yeah.

> 
>> +
>> +                       eb.buffer_count = 1;
>> +                       eb.buffers_ptr = to_user_pointer(&obj);
>> +
>> +                       eb.flags = engine | I915_EXEC_FENCE_IN;
>> +                       eb.rsvd2 = fence;
> 
> You do however also want to check with one context per execbuf.

Ok.

> 
> if (flags & CONTEXTS)
> 	eb.rsvd1 = gem_context_create(fd);
>> +
>> +                       gem_execbuf(gem_fd, &eb);
> 
> if (flags & CONTEXTS)
> 	gem_context_destroy(fd, eb.rsvd1);
> 	eb.rsvd1 = gem_context_create();
> 
>> +               }
>> +
>> +               val[0] = __pmu_read_single(fd, &ts[0]);
>> +               usleep(batch_duration_ns / 1000);
>> +               val[1] = __pmu_read_single(fd, &ts[1]);
>> +
>> +               queued[n] = calc_queued(val[1] - val[0], ts[1] - ts[0]);
>> +               igt_info("n=%u queued=%.2f\n", n, queued[n]);
>> +
>> +               if (fence >= 0)
>> +                       igt_cork_unplug(&cork);
> 
> Maybe we should just make this a no-op when used on an unplugged cork.

Don't know really, there's an assert in there and I didn't feel like 
evaluating all callers.

> 
>> +
>> +               for (i = 0; i < n; i++)
>> +                       gem_sync(gem_fd, bo[i]);
>> +       }
>> +
>> +       close(fd);
>> +
>> +       for (i = 0; i < max_rq; i++) {
>> +               if (bo[i])
>> +                       gem_close(gem_fd, bo[i]);
>> +       }
>> +
>> +       for (i = 0; i <= max_rq; i++)
>> +               assert_within_epsilon(queued[i], i, tolerance);
>> +}
>> +
>> +static void
>> +runnable(int gem_fd, const struct intel_execution_engine2 *e)
>> +{
>> +       const unsigned long engine = e2ring(gem_fd, e);
>> +       const unsigned int max_rq = 10;
>> +       igt_spin_t *spin[max_rq + 1];
>> +       double runnable[max_rq + 1];
>> +       uint32_t ctx[max_rq];
>> +       unsigned int n, i;
>> +       uint64_t val[2];
>> +       uint64_t ts[2];
>> +       int fd;
>> +
>> +       memset(runnable, 0, sizeof(runnable));
>> +       memset(ctx, 0, sizeof(ctx));
>> +
>> +       fd = open_pmu(I915_PMU_ENGINE_RUNNABLE(e->class, e->instance));
>> +
>> +       for (n = 0; n <= max_rq; n++) {
>> +               gem_quiescent_gpu(gem_fd);
>> +
>> +               for (i = 0; i < n; i++) {
>> +                       if (!ctx[i])
>> +                               ctx[i] = gem_context_create(gem_fd);
>> +
>> +                       if (i == 0)
>> +                               spin[i] = __spin_poll(gem_fd, ctx[i], engine);
>> +                       else
>> +                               spin[i] = __igt_spin_batch_new(gem_fd, ctx[i],
>> +                                                              engine, 0);
>> +               }
>> +
>> +               if (n)
>> +                       __spin_wait(gem_fd, spin[0]);
>> +
>> +               val[0] = __pmu_read_single(fd, &ts[0]);
>> +               usleep(batch_duration_ns / 1000);
>> +               val[1] = __pmu_read_single(fd, &ts[1]);
>> +
>> +               runnable[n] = calc_queued(val[1] - val[0], ts[1] - ts[0]);
>> +               igt_info("n=%u runnable=%.2f\n", n, runnable[n]);
>> +
>> +               for (i = 0; i < n; i++) {
>> +                       end_spin(gem_fd, spin[i], FLAG_SYNC);
>> +                       igt_spin_batch_free(gem_fd, spin[i]);
>> +               }
>> +       }
>> +
>> +       for (i = 0; i < max_rq; i++) {
>> +               if (ctx[i])
>> +                       gem_context_destroy(gem_fd, ctx[i]);
> 
> I would just create the contexts unconditionally.

Can do.

> 
>> +       }
>> +
>> +       close(fd);
>> +
>> +       assert_within_epsilon(runnable[0], 0, tolerance);
>> +       igt_assert(runnable[max_rq] > 0.0);
>> +       assert_within_epsilon(runnable[max_rq] - runnable[max_rq - 1], 1,
>> +                             tolerance);
>> +}
>> +
>> +static void
>> +running(int gem_fd, const struct intel_execution_engine2 *e)
>> +{
>> +       const unsigned long engine = e2ring(gem_fd, e);
>> +       const unsigned int max_rq = 10;
>> +       igt_spin_t *spin[max_rq + 1];
>> +       double running[max_rq + 1];
>> +       unsigned int n, i;
>> +       uint64_t val[2];
>> +       uint64_t ts[2];
>> +       int fd;
>> +
>> +       memset(running, 0, sizeof(running));
>> +       memset(spin, 0, sizeof(spin));
>> +
>> +       fd = open_pmu(I915_PMU_ENGINE_RUNNING(e->class, e->instance));
>> +
>> +       for (n = 0; n <= max_rq; n++) {
>> +               gem_quiescent_gpu(gem_fd);
>> +
>> +               for (i = 0; i < n; i++) {
>> +                       if (i == 0)
>> +                               spin[i] = __spin_poll(gem_fd, 0, engine);
>> +                       else
>> +                               spin[i] = __igt_spin_batch_new(gem_fd, 0,
>> +                                                              engine, 0);
>> +               }
>> +
>> +               if (n)
>> +                       __spin_wait(gem_fd, spin[0]);
> 
> So create N requests on the same context so that running == N due to
> lite-restore every time. I have some caveats that this relies on the
> precise implementation, e.g. I don't think it will work for guc (using
> execlists emulation with no lite-restore) for N > 2 or 8, or if we get
> creative with execlists.

Yep, I think it doesn't work with GuC. Well, the assert would need to be 
different as minimum.

For N > 2 and execlists I think it works since it only needs port 0.

Runnable subtest on the other hand tries to be flexible towards 
different possible Ns already. I guess for running I could downgrade the 
asserts to just check running[N + 1] >= running[N] and running[1] > 0.

> 
>> +
>> +               val[0] = __pmu_read_single(fd, &ts[0]);
>> +               usleep(batch_duration_ns / 1000);
>> +               val[1] = __pmu_read_single(fd, &ts[1]);
>> +
>> +               running[n] = calc_queued(val[1] - val[0], ts[1] - ts[0]);
>> +               igt_info("n=%u running=%.2f\n", n, running[n]);
>> +
>> +               for (i = 0; i < n; i++) {
>> +                       end_spin(gem_fd, spin[i], FLAG_SYNC);
>> +                       igt_spin_batch_free(gem_fd, spin[i]);
>> +               }
>> +       }
>> +
>> +       close(fd);
>> +
>> +       for (i = 0; i <= max_rq; i++)
>> +               assert_within_epsilon(running[i], i, tolerance);
>> +}
> 
> Ok, the tests look like they should be covering the counters.
> 
> Do we need to do an all-engines pass to check concurrent usage?

Depends how grey is your approach between white box and black box testing.

But what is definitely needed is some tests involving hangs, resets and 
preemption, since I am pretty sure a bug sneaked in somewhere in those 
areas.

Regards,

Tvrtko
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

  reply	other threads:[~2018-03-23 10:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-19 18:22 [Intel-gfx] [PATCH i-g-t 0/5] Queued/runnable/running engine stats Tvrtko Ursulin
2018-03-19 18:22 ` [igt-dev] [PATCH i-g-t 1/5] include: i915 uAPI headers Tvrtko Ursulin
2018-03-19 18:22 ` [igt-dev] [PATCH i-g-t 2/5] intel-gpu-overlay: Add engine queue stats Tvrtko Ursulin
2018-03-19 18:22 ` [Intel-gfx] [PATCH i-g-t 3/5] intel-gpu-overlay: Show 1s, 30s and 15m GPU load Tvrtko Ursulin
2018-03-19 18:22 ` [Intel-gfx] [PATCH i-g-t 4/5] tests/perf_pmu: Add tests for engine queued/runnable/running stats Tvrtko Ursulin
2018-03-19 20:58   ` [igt-dev] " Chris Wilson
2018-03-23 10:08     ` Tvrtko Ursulin [this message]
2018-03-19 18:22 ` [igt-dev] [PATCH i-g-t 5/5] tests/i915_query: Engine queues tests Tvrtko Ursulin
2018-03-22 21:22   ` Lionel Landwerlin
2018-03-23 10:18     ` Tvrtko Ursulin
2018-03-23 10:47       ` [Intel-gfx] " Lionel Landwerlin
2018-03-23 10:53       ` Chris Wilson
2018-03-19 21:54 ` [igt-dev] ✗ Fi.CI.BAT: failure for Queued/runnable/running engine stats Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87510b5a-221f-28f2-df6d-86bdac580f52@linux.intel.com \
    --to=tvrtko.ursulin@linux.intel.com \
    --cc=Intel-gfx@lists.freedesktop.org \
    --cc=chris@chris-wilson.co.uk \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=tursulin@ursulin.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox