From 5957b0c162290e444d9e57dbed07047c421e7148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 7 Oct 2020 07:41:41 -0400 Subject: [PATCH] glthread: pin driver threads to the same L3 as the main thread regularly This improves performance on my Ryzen 3900X, which has 4 L3 caches and 6 threads per L3. The best improvement is 33% if the kernel CPU scheduler doesn't move the main thread too often. v2: pin only once in 128 batch flushes Acked-by: Jose Fonseca Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/mesa/main/dd.h | 2 ++ src/mesa/main/glthread.c | 20 ++++++++++++++++++++ src/mesa/main/glthread.h | 3 +++ src/mesa/state_tracker/st_context.c | 13 +++++++++++++ 4 files changed, 38 insertions(+) diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 417f2592301..eb3c14e64a9 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -1326,6 +1326,8 @@ struct dd_function_table { void (*SetMaxShaderCompilerThreads)(struct gl_context *ctx, unsigned count); bool (*GetShaderProgramCompletionStatus)(struct gl_context *ctx, struct gl_shader_program *shprog); + + void (*PinDriverToL3Cache)(struct gl_context *ctx, unsigned L3_cache); }; diff --git a/src/mesa/main/glthread.c b/src/mesa/main/glthread.c index b0779435af0..eb8eb30cabc 100644 --- a/src/mesa/main/glthread.c +++ b/src/mesa/main/glthread.c @@ -38,6 +38,7 @@ #include "main/hash.h" #include "util/u_atomic.h" #include "util/u_thread.h" +#include "util/u_cpu_detect.h" static void @@ -195,6 +196,25 @@ _mesa_glthread_flush_batch(struct gl_context *ctx) if (!next->used) return; + /* Pin threads regularly to the same Zen CCX that the main thread is + * running on. The main thread can move between CCXs. + */ + if (util_cpu_caps.nr_cpus != util_cpu_caps.cores_per_L3 && + /* driver support */ + ctx->Driver.PinDriverToL3Cache && + ++glthread->pin_thread_counter % 128 == 0) { + int cpu = util_get_current_cpu(); + + if (cpu >= 0) { + unsigned L3_cache = util_cpu_caps.cpu_to_L3[cpu]; + + util_set_thread_affinity(glthread->queue.threads[0], + util_cpu_caps.L3_affinity_mask[L3_cache], + NULL, UTIL_MAX_CPUS); + ctx->Driver.PinDriverToL3Cache(ctx, L3_cache); + } + } + /* Debug: execute the batch immediately from this thread. * * Note that glthread_unmarshal_batch() changes the dispatch table so we'll diff --git a/src/mesa/main/glthread.h b/src/mesa/main/glthread.h index 76cb41192a8..8a98a151b3a 100644 --- a/src/mesa/main/glthread.h +++ b/src/mesa/main/glthread.h @@ -134,6 +134,9 @@ struct glthread_state /** Whether GLThread is inside a display list generation. */ bool inside_dlist; + /** For L3 cache pinning. */ + unsigned pin_thread_counter; + /** The ring of batches in memory. */ struct glthread_batch batches[MARSHAL_MAX_BATCHES]; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 668a7aa7be2..1605e4682e8 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -908,6 +908,16 @@ st_get_driver_uuid(struct gl_context *ctx, char *uuid) } +static void +st_pin_driver_to_l3_cache(struct gl_context *ctx, unsigned L3_cache) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + pipe->set_context_param(pipe, PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE, + L3_cache); +} + + static void st_init_driver_functions(struct pipe_screen *screen, struct dd_function_table *functions) @@ -999,6 +1009,9 @@ st_create_context(gl_api api, struct pipe_context *pipe, memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(pipe->screen, &funcs); + if (pipe->set_context_param) + funcs.PinDriverToL3Cache = st_pin_driver_to_l3_cache; + ctx = calloc(1, sizeof(struct gl_context)); if (!ctx) return NULL;