tests/perf_pmu: Verify engine busyness accuracy
RFC 1/1 tests/perf_pmu: Verify engine busyness accuracy
From: Tvrtko Ursulin <[email protected]>
A subtest to verify that the engine busyness is reported with expected accuracy on platforms where the feature is available.
We test three patterns: 2%, 50% and 98% load per engine.
v2:
* Use spin batch instead of nop calibration.
* Various tweaks.
v3:
* Change loops to be time based.
* Use __igt_spin_batch_new inside timing sensitive loops.
* Fixed PWM sleep handling.
--- tests/perf_pmu.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+)
tests/perf_pmu.c +145 -0
@@ -35,6 +35,7 @@#include <dirent.h> #include <time.h> #include <poll.h> +#include <sched.h> #include "igt.h" #include "igt_core.h"
@@ -1169,6 +1170,140 @@ test_rc6(int gem_fd)assert_within_epsilon (busy - prev,0.0 , tolerance); } +static uint64_t __pmu_read_single (int fd,uint64_t *ts) +{ +uint64_t data[2 ]; + +igt_assert_eq (read (fd, data,sizeof (data)),sizeof (data)); + + *ts = data[1 ]; + +return data[0 ]; +} + +static double __error (double val,double ref) +{ +return (100.0 * val / ref) -100.0 ; +} + +static void debug_error (const char *str,double val,double ref) +{ +igt_debug ("%s=%.2f%% (%.2f/%.2f)\n" , str,__error (val, ref), val, ref); +} + +static void log_error (const char *str,double val,double ref) +{ +debug_error (str, val, ref); +igt_info ("%s=%.2f%%\n" , str,__error (val, ref)); +} + +#define div_round_up (a, b) (((a) + (b) - 1) / (b)) + +static void +accuracy (int gem_fd,const struct intel_execution_engine2 *e, +unsigned long target_busy_pct) +{ +const unsigned int test_us =1e6 ; +const unsigned int pwm_calibration_us =500e3 ; +unsigned long busy_us =2500 ; +unsigned long idle_us =100 * (busy_us - target_busy_pct * + busy_us /100 ) / target_busy_pct; +double busy_r; +uint64_t val[2 ]; +uint64_t ts[2 ]; +int fd; + +/* Sampling platforms cannot reach the high accuracy criteria. */ +igt_require (intel_gen (intel_get_drm_devid (gem_fd)) >=8 ); + +while (idle_us <2500 ) { + busy_us *=2 ; + idle_us *=2 ; + } + +assert_within_epsilon ((double )busy_us / (busy_us + idle_us), + (double )target_busy_pct /100.0 , tolerance); + +/* Emit PWM pattern on the engine from a child. */ + igt_fork(child, 1) { +struct sched_param rt = { .sched_priority =99 }; +struct timespec test_start = { }; +unsigned long overhead_ns =0 ; +unsigned long loops =0 ; + +/* We need the best sleep accuracy we can get. */ +igt_require (sched_setscheduler (0 , +SCHED_FIFO |SCHED_RESET_ON_FORK , + &rt) ==0 ); + +/* Measure setup overhead. */ +igt_nsec_elapsed (&test_start); +do { +struct timespec start = { }; +igt_spin_t *spin; +unsigned int ns; + +igt_nsec_elapsed (&start); + spin =__igt_spin_batch_new (gem_fd,0 , +e2ring (gem_fd, e),0 ); +igt_spin_batch_end (spin); + ns =igt_nsec_elapsed (&start); +gem_sync (gem_fd, spin->handle); +igt_spin_batch_free (gem_fd, spin); + overhead_ns += ns; + loops++; +usleep (1000 ); + }while (igt_nsec_elapsed (&test_start) < + pwm_calibration_us *1000 ); + + overhead_ns =div_round_up (overhead_ns, loops); +igt_debug ("spin setup overhead = %luus\n" , overhead_ns /1000 ); +igt_assert (overhead_ns < busy_us *1000 ); + +/* Emit PWM busy signal. */ + busy_us -= overhead_ns /1000 ; +memset (&test_start,0 ,sizeof (test_start)); +igt_nsec_elapsed (&test_start); +do { +struct timespec start = { }; +igt_spin_t *spin; +unsigned int ns, sleep; + + spin =__igt_spin_batch_new (gem_fd,0 , +e2ring (gem_fd, e),0 ); + ns =measured_usleep (busy_us); +igt_spin_batch_end (spin); +debug_error ("busy sleep error" , ns, busy_us *1000 ); +gem_sync (gem_fd, spin->handle); +igt_nsec_elapsed (&start); +igt_spin_batch_free (gem_fd, spin); + ns =igt_nsec_elapsed (&start); +igt_assert_lt (ns, idle_us *1000 ); + sleep = idle_us *1000 - ns; + ns =measured_usleep (sleep /1000 ); +debug_error ("idle sleep error" , ns, sleep); + }while (igt_nsec_elapsed (&test_start) < test_us *2 *1000 ); + } + +/* Let the child run. */ +usleep (pwm_calibration_us *2 ); + +/* Collect engine busyness for a subset of child runtime. */ + fd =open_pmu (I915_PMU_ENGINE_BUSY (e->class, e->instance)); + val[0 ] =__pmu_read_single (fd, &ts[0 ]); +usleep (test_us /2 ); + val[1 ] =__pmu_read_single (fd, &ts[1 ]); +close (fd); + +igt_waitchildren (); + + busy_r = (double )(val[1 ] - val[0 ]) / (ts[1 ] - ts[0 ]); + +log_error ("error" , busy_r, target_busy_pct /100.0 ); + +assert_within_epsilon (busy_r, (double )target_busy_pct /100.0 ,0.15 ); +} + igt_main { const unsigned int num_other_metrics =
@@ -1197,6 +1332,8 @@ igt_maininvalid_init ();for_each_engine_class_instance (fd, e) { +const unsigned int pct[] = {2 ,50 ,98 }; +/** * Test that a single engine metric can be initialized. */
@@ -1277,6 +1414,14 @@ igt_main*/ igt_subtest_f("busy-double-start-%s", e->name)busy_double_start (fd, e); + +/** +* Check engine busyness accuracy is as expected. +*/ +for (i =0 ; i <ARRAY_SIZE (pct); i++) { + igt_subtest_f("busy-accuracy-%u-%s", pct[i], e->name) +accuracy (fd, e, pct[i]); + } }/**
Signature · 6 lines
2.14.1 _______________________________________________ igt-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/igt-dev
Quoting Tvrtko Ursulin (2018-01-30 18:11:04)
tests/perf_pmu.c test_rc6(int gem_fd) · line 1186
Quoted 3 lines
tests/perf_pmu.c +3
-0+static double __error (double val,double ref) +{ +return (100.0 * val / ref) -100.0 ;
ref == 0? sign?
-Chris
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
Patchwork
CI[igt-dev] ✓ Fi.CI.BAT: success for tests/perf_pmu: Verify engine busyness accuracy
In reply to Tvrtko Ursulin== Series Details ==
== Series Details ==
Series: tests/perf_pmu: Verify engine busyness accuracy
URL : https://patchwork.freedesktop.org/series/37359/
State : success
== Summary ==
IGT patchset tested on top of latest successful build3f820260ce660cdff7fb803237c57554a29498c0 tests/kms_atomic_transition: Don't abuse the HSKEW flag to force a modeset
with latest DRM-Tip kernel build CI_DRM_37030edf4cc4e7c1 drm-tip: 2018y-01m-30d-18h-33m-48s UTC integration manifest
Testlist changes:
+igt@perf_pmu@busy-accuracy-2-bcs0
+igt@perf_pmu@busy-accuracy-2-rcs0
+igt@perf_pmu@busy-accuracy-2-vcs0
+igt@perf_pmu@busy-accuracy-2-vcs1
+igt@perf_pmu@busy-accuracy-2-vecs0
+igt@perf_pmu@busy-accuracy-50-bcs0
+igt@perf_pmu@busy-accuracy-50-rcs0
+igt@perf_pmu@busy-accuracy-50-vcs0
+igt@perf_pmu@busy-accuracy-50-vcs1
+igt@perf_pmu@busy-accuracy-50-vecs0
+igt@perf_pmu@busy-accuracy-98-bcs0
+igt@perf_pmu@busy-accuracy-98-rcs0
+igt@perf_pmu@busy-accuracy-98-vcs0
+igt@perf_pmu@busy-accuracy-98-vcs1
+igt@perf_pmu@busy-accuracy-98-vecs0
fi-bdw-5557u total:288 pass:267 dwarn:0 dfail:0 fail:0 skip:21 time:430s fi-bdw-gvtdvm total:288 pass:264 dwarn:0 dfail:0 fail:0 skip:24 time:430s fi-blb-e6850 total:288 pass:223 dwarn:1 dfail:0 fail:0 skip:64 time:373s fi-bsw-n3050 total:288 pass:242 dwarn:0 dfail:0 fail:0 skip:46 time:494s fi-bwr-2160 total:288 pass:183 dwarn:0 dfail:0 fail:0 skip:105 time:284s fi-bxt-dsi total:288 pass:258 dwarn:0 dfail:0 fail:0 skip:30 time:490s fi-bxt-j4205 total:288 pass:259 dwarn:0 dfail:0 fail:0 skip:29 time:490s fi-byt-j1900 total:288 pass:253 dwarn:0 dfail:0 fail:0 skip:35 time:472s fi-byt-n2820 total:288 pass:249 dwarn:0 dfail:0 fail:0 skip:39 time:457s fi-cfl-s2 total:288 pass:262 dwarn:0 dfail:0 fail:0 skip:26 time:580s fi-elk-e7500 total:224 pass:168 dwarn:10 dfail:0 fail:0 skip:45 fi-gdg-551 total:288 pass:179 dwarn:0 dfail:0 fail:1 skip:108 time:279s fi-glk-1 total:288 pass:260 dwarn:0 dfail:0 fail:0 skip:28 time:514s fi-hsw-4770 total:288 pass:261 dwarn:0 dfail:0 fail:0 skip:27 time:392s fi-hsw-4770r total:288 pass:261 dwarn:0 dfail:0 fail:0 skip:27 time:403s fi-ilk-650 total:288 pass:228 dwarn:0 dfail:0 fail:0 skip:60 time:414s fi-ivb-3520m total:288 pass:259 dwarn:0 dfail:0 fail:0 skip:29 time:450s fi-ivb-3770 total:288 pass:255 dwarn:0 dfail:0 fail:0 skip:33 time:423s fi-kbl-7500u total:288 pass:263 dwarn:1 dfail:0 fail:0 skip:24 time:457s fi-kbl-7560u total:288 pass:269 dwarn:0 dfail:0 fail:0 skip:19 time:502s fi-kbl-7567u total:288 pass:268 dwarn:0 dfail:0 fail:0 skip:20 time:455s fi-kbl-r total:288 pass:261 dwarn:0 dfail:0 fail:0 skip:27 time:505s fi-skl-6260u total:288 pass:268 dwarn:0 dfail:0 fail:0 skip:20 time:430s fi-skl-6600u total:288 pass:261 dwarn:0 dfail:0 fail:0 skip:27 time:511s fi-skl-6700hq total:288 pass:262 dwarn:0 dfail:0 fail:0 skip:26 time:534s fi-skl-6700k2 total:288 pass:264 dwarn:0 dfail:0 fail:0 skip:24 time:489s fi-skl-6770hq total:288 pass:268 dwarn:0 dfail:0 fail:0 skip:20 time:474s fi-skl-guc total:288 pass:260 dwarn:0 dfail:0 fail:0 skip:28 time:418s fi-skl-gvtdvm total:288 pass:265 dwarn:0 dfail:0 fail:0 skip:23 time:433s fi-snb-2520m total:288 pass:248 dwarn:0 dfail:0 fail:0 skip:40 time:523s fi-snb-2600 total:288 pass:248 dwarn:0 dfail:0 fail:0 skip:40 time:404s
Blacklisted hosts:
fi-glk-dsi total:15 pass:13 dwarn:0 dfail:0 fail:1 skip:0
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_838/issues.html
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
Quoting Tvrtko Ursulin (2018-01-30 18:11:04)
Quoted 52 lines
From: Tvrtko Ursulin <[email protected]>
A subtest to verify that the engine busyness is reported with expected accuracy on platforms where the feature is available.
We test three patterns: 2%, 50% and 98% load per engine.
v2:
* Use spin batch instead of nop calibration.
* Various tweaks.v3:
* Change loops to be time based.
* Use__igt_spin_batch_newinside timing sensitive loops.
* Fixed PWM sleep handling.Signed-off-by Tvrtko Ursulin <[email protected]>--- tests/perf_pmu.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+)tests/perf_pmu.c +16
-0@@ -35,6 +35,7 @@#include <dirent.h> #include <time.h> #include <poll.h> +#include <sched.h> #include "igt.h" #include "igt_core.h" @@ -1169,6 +1170,140 @@ test_rc6(int gem_fd)assert_within_epsilon (busy - prev,0.0 , tolerance); } +static uint64_t __pmu_read_single (int fd,uint64_t *ts) +{ +uint64_t data[2 ]; + +igt_assert_eq (read (fd, data,sizeof (data)),sizeof (data)); + + *ts = data[1 ]; + +return data[0 ]; +} + +static double __error (double val,double ref) +{ +return (100.0 * val / ref) -100.0 ; +}
tests/perf_pmu.c test_rc6(int gem_fd) · line 1197
Quoted 10 lines
tests/perf_pmu.c +10
-0+ +static void debug_error (const char *str,double val,double ref) +{ +igt_debug ("%s=%.2f%% (%.2f/%.2f)\n" , str,__error (val, ref), val, ref); +} + +static void log_error (const char *str,double val,double ref) +{ +debug_error (str, val, ref); +igt_info ("%s=%.2f%%\n" , str,__error (val, ref));
Not convinced you want both log levels, is the raw value in () too confusing to show by default?
Quoted 30 lines
tests/perf_pmu.c +30
-0+} + +#define div_round_up (a, b) (((a) + (b) - 1) / (b)) + +static void +accuracy (int gem_fd,const struct intel_execution_engine2 *e, +unsigned long target_busy_pct) +{ +const unsigned int test_us =1e6 ; +const unsigned int pwm_calibration_us =500e3 ; +unsigned long busy_us =2500 ; +unsigned long idle_us =100 * (busy_us - target_busy_pct * + busy_us /100 ) / target_busy_pct; +double busy_r; +uint64_t val[2 ]; +uint64_t ts[2 ]; +int fd; + +/* Sampling platforms cannot reach the high accuracy criteria. */ +igt_require (intel_gen (intel_get_drm_devid (gem_fd)) >=8 ); + +while (idle_us <2500 ) { + busy_us *=2 ; + idle_us *=2 ; + } + +assert_within_epsilon ((double )busy_us / (busy_us + idle_us), + (double )target_busy_pct /100.0 , tolerance); + +/* Emit PWM pattern on the engine from a child. */
tests/perf_pmu.c test_rc6(int gem_fd) · line 1237
Quoted 10 lines
tests/perf_pmu.c +10
-0+ igt_fork(child, 1) { +struct sched_param rt = { .sched_priority =99 }; +struct timespec test_start = { }; +unsigned long overhead_ns =0 ; +unsigned long loops =0 ; + +/* We need the best sleep accuracy we can get. */ +igt_require (sched_setscheduler (0 , +SCHED_FIFO |SCHED_RESET_ON_FORK , + &rt) ==0 );
(RESET_ON_FORK may be overkill here ;)
Quoted 8 lines
tests/perf_pmu.c +8
-0+ +/* Measure setup overhead. */ +igt_nsec_elapsed (&test_start); + do { + struct timespec start = { }; + igt_spin_t *spin; + unsigned int ns; +
tests/perf_pmu.c test_rc6(int gem_fd) · line 1255
Quoted 10 lines
tests/perf_pmu.c +10
-0+igt_nsec_elapsed (&start); + spin =__igt_spin_batch_new (gem_fd,0 , +e2ring (gem_fd, e),0 ); +igt_spin_batch_end (spin); + ns =igt_nsec_elapsed (&start); +gem_sync (gem_fd, spin->handle); +igt_spin_batch_free (gem_fd, spin); + overhead_ns += ns; + loops++; +usleep (1000 );
Hmm, first request is for whitespace! If we require consistent setup overhead, I think you will want to keep the single spinner around and re-execbuf it. (Restoring the first dword back to MI_NOOP/MI_ARB before use.) That way we won't keep creating new bo with the irregularities that may cause.
Quoted 19 lines
tests/perf_pmu.c +19
-0+ }while (igt_nsec_elapsed (&test_start) < + pwm_calibration_us *1000 ); + + overhead_ns =div_round_up (overhead_ns, loops); +igt_debug ("spin setup overhead = %luus\n" , overhead_ns /1000 ); +igt_assert (overhead_ns < busy_us *1000 ); + +/* Emit PWM busy signal. */ + busy_us -= overhead_ns /1000 ; +memset (&test_start,0 ,sizeof (test_start)); +igt_nsec_elapsed (&test_start); + do { + struct timespec start = { }; + igt_spin_t *spin; + unsigned int ns, sleep; + + spin = __igt_spin_batch_new(gem_fd, 0, + e2ring(gem_fd, e), 0); + ns = measured_usleep(busy_us);
tests/perf_pmu.c test_rc6(int gem_fd) · line 1284
Quoted 10 lines
tests/perf_pmu.c +10
-0+igt_spin_batch_end (spin); +debug_error ("busy sleep error" , ns, busy_us *1000 ); +gem_sync (gem_fd, spin->handle); +igt_nsec_elapsed (&start); +igt_spin_batch_free (gem_fd, spin); + ns =igt_nsec_elapsed (&start); +igt_assert_lt (ns, idle_us *1000 ); + sleep = idle_us *1000 - ns; + ns =measured_usleep (sleep /1000 ); +debug_error ("idle sleep error" , ns, sleep);
We definitely would benefit from whitespace here! There's at least two different phases in each loop, and measurement on top.
tests/perf_pmu.c test_rc6(int gem_fd) · line 1296
Quoted 12 lines
tests/perf_pmu.c +12
-0+ }while (igt_nsec_elapsed (&test_start) < test_us *2 *1000 ); + } + +/* Let the child run. */ +usleep (pwm_calibration_us *2 ); + +/* Collect engine busyness for a subset of child runtime. */ + fd =open_pmu (I915_PMU_ENGINE_BUSY (e->class, e->instance)); + val[0 ] =__pmu_read_single (fd, &ts[0 ]); +usleep (test_us /2 ); + val[1 ] =__pmu_read_single (fd, &ts[1 ]); +close (fd);
Includes its own timestamp, that should eradicate one whole class of problem!
Quoted 24 lines
tests/perf_pmu.c +12
-0+ +igt_waitchildren (); + + busy_r = (double )(val[1 ] - val[0 ]) / (ts[1 ] - ts[0 ]); + +log_error ("error" , busy_r, target_busy_pct /100.0 ); + +assert_within_epsilon (busy_r, (double )target_busy_pct /100.0 ,0.15 ); +} + igt_main { const unsigned int num_other_metrics =@@ -1197,6 +1332,8 @@ igt_maininvalid_init ();for_each_engine_class_instance (fd, e) { +const unsigned int pct[] = {2 ,50 ,98 }; +/** * Test that a single engine metric can be initialized. */ @@ -1277,6 +1414,14 @@ igt_main*/
tests/perf_pmu.c igt_main · line 1424
Quoted 10 lines
tests/perf_pmu.c +8
-0igt_subtest_f("busy-double-start-%s", e->name)busy_double_start (fd, e); + +/** +* Check engine busyness accuracy is as expected. +*/ +for (i =0 ; i <ARRAY_SIZE (pct); i++) { + igt_subtest_f("busy-accuracy-%u-%s", pct[i], e->name) +accuracy (fd, e, pct[i]); + }
We cover accuracy of one engine, let's do them all concurrently as well! That should stress our accuracy claims when running flat out? The spin batch should come close to being the finest pwm userspace can use, so should be a reasonable estimate of the worst-case loading across all engines we can expect. (Although we might run into problems trying to use more RT threads than cores.)
-Chris
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
Patchwork
CI[igt-dev] ✓ Fi.CI.IGT: success for tests/perf_pmu: Verify engine busyness accuracy
In reply to Tvrtko Ursulin== Series Details ==
== Series Details ==
Series: tests/perf_pmu: Verify engine busyness accuracy
URL : https://patchwork.freedesktop.org/series/37359/
State : success
== Summary ==
Test kms_flip:
Subgroup wf_vblank-ts-check-interruptible:
fail -> PASS (shard-snb) fdo#100368 +1
Test kms_cursor_legacy:
Subgroup 2x-long-flip-vs-cursor-legacy:
fail -> PASS (shard-hsw)
Test perf:
Subgroup enable-disable:
pass -> FAIL (shard-apl) fdo#103715
Subgroup oa-exponents:
pass -> FAIL (shard-apl) fdo#102254
Test kms_sysfs_edid_timing:
pass -> WARN (shard-apl) fdo#100047
Test kms_setmode:
Subgroup basic:
fail -> PASS (shard-hsw) fdo#99912
Test perf_pmu:
Subgroup frequency:
fail -> PASS (shard-apl) fdo#104829fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#103715 https://bugs.freedesktop.org/show_bug.cgi?id=103715
fdo#102254 https://bugs.freedesktop.org/show_bug.cgi?id=102254
fdo#100047 https://bugs.freedesktop.org/show_bug.cgi?id=100047
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
fdo#104829 https://bugs.freedesktop.org/show_bug.cgi?id=104829
shard-apl total:2853 pass:1757 dwarn:1 dfail:0 fail:27 skip:1067 time:12622s shard-hsw total:2853 pass:1737 dwarn:1 dfail:0 fail:9 skip:1105 time:11801s shard-snb total:2853 pass:1330 dwarn:1 dfail:0 fail:10 skip:1512 time:6593s
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_838/shards.html
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev