[Mesa-dev] [PATCH] radv: using tls to store llvm related info and speed up compiles (v8)
Dieter Nützel
Dieter at nuetzel-hh.de
Thu Jul 5 03:22:14 UTC 2018
Tested-by: Dieter Nützel <Dieter at nuetzel-hh.de>
on RX580
with F1 2017
and 'smoketest':
cpupower frequency-set -g ondemand
/home/dieter> smoketest
5172 presents in 5.00043 seconds (FPS: 1034.31)
5426 presents in 5.00098 seconds (FPS: 1084.99)
5304 presents in 5.00002 seconds (FPS: 1060.8)
5338 presents in 5.00085 seconds (FPS: 1067.42)
5304 presents in 5.00034 seconds (FPS: 1060.73)
5357 presents in 5.00073 seconds (FPS: 1071.24)
frames:35390, elapsedms:33388
cpupower frequency-set -g performance
/home/dieter> smoketest
5907 presents in 5.00033 seconds (FPS: 1181.32)
6093 presents in 5.00007 seconds (FPS: 1218.58)
6070 presents in 5.00094 seconds (FPS: 1213.77)
6096 presents in 5.00006 seconds (FPS: 1219.19)
6107 presents in 5.00063 seconds (FPS: 1221.25)
frames:33423, elapsedms:27686
Dieter
Am 05.07.2018 02:03, schrieb Dave Airlie:
> From: Dave Airlie <airlied at redhat.com>
>
> This uses the common compiler passes abstraction to help radv
> avoid fixed cost compiler overheads. This uses a linked list per
> thread stored in thread local storage, with an entry in the list
> for each target machine.
>
> This should remove all the fixed overheads setup costs of creating
> the pass manager each time.
>
> This takes a demo app time to compile the radv meta shaders on nocache
> and exit from 1.7s to 1s. It also has been reported to take the startup
> time of uncached shaders on RoTR from 12m24s to 11m35s (Alex)
>
> v2: fix llvm6 build, inline emit function, handle multiple targets
> in one thread
> v3: rebase and port onto new structure
> v4: rename some vars (Bas)
> v5: drag all code into radv for now, we can refactor it out later
> for radeonsi if we make it shareable
> v6: use a bit more C++ in the wrapper
> v7: logic bugs fixed so it actually runs again.
> v8: rebase on top of radeonsi changes.
> ---
> src/amd/vulkan/Makefile.sources | 2 +
> src/amd/vulkan/meson.build | 2 +
> src/amd/vulkan/radv_debug.h | 1 +
> src/amd/vulkan/radv_device.c | 1 +
> src/amd/vulkan/radv_llvm_helper.cpp | 148 ++++++++++++++++++++++++++++
> src/amd/vulkan/radv_nir_to_llvm.c | 27 +----
> src/amd/vulkan/radv_shader.c | 10 +-
> src/amd/vulkan/radv_shader_helper.h | 44 +++++++++
> 8 files changed, 207 insertions(+), 28 deletions(-)
> create mode 100644 src/amd/vulkan/radv_llvm_helper.cpp
> create mode 100644 src/amd/vulkan/radv_shader_helper.h
>
> diff --git a/src/amd/vulkan/Makefile.sources
> b/src/amd/vulkan/Makefile.sources
> index 70d56e88cb3..152fdd7cb71 100644
> --- a/src/amd/vulkan/Makefile.sources
> +++ b/src/amd/vulkan/Makefile.sources
> @@ -54,6 +54,7 @@ VULKAN_FILES := \
> radv_meta_resolve_cs.c \
> radv_meta_resolve_fs.c \
> radv_nir_to_llvm.c \
> + radv_llvm_helper.cpp \
> radv_pass.c \
> radv_pipeline.c \
> radv_pipeline_cache.c \
> @@ -62,6 +63,7 @@ VULKAN_FILES := \
> radv_shader.c \
> radv_shader_info.c \
> radv_shader.h \
> + radv_shader_helper.h \
> radv_query.c \
> radv_util.c \
> radv_util.h \
> diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build
> index 22857926fa1..9f2842182e7 100644
> --- a/src/amd/vulkan/meson.build
> +++ b/src/amd/vulkan/meson.build
> @@ -67,6 +67,7 @@ libradv_files = files(
> 'radv_descriptor_set.h',
> 'radv_formats.c',
> 'radv_image.c',
> + 'radv_llvm_helper.cpp',
> 'radv_meta.c',
> 'radv_meta.h',
> 'radv_meta_blit.c',
> @@ -88,6 +89,7 @@ libradv_files = files(
> 'radv_radeon_winsys.h',
> 'radv_shader.c',
> 'radv_shader.h',
> + 'radv_shader_helper.h',
> 'radv_shader_info.c',
> 'radv_query.c',
> 'radv_util.c',
> diff --git a/src/amd/vulkan/radv_debug.h b/src/amd/vulkan/radv_debug.h
> index f1b0dc26a63..9fe4c3b7404 100644
> --- a/src/amd/vulkan/radv_debug.h
> +++ b/src/amd/vulkan/radv_debug.h
> @@ -49,6 +49,7 @@ enum {
> RADV_DEBUG_ERRORS = 0x80000,
> RADV_DEBUG_STARTUP = 0x100000,
> RADV_DEBUG_CHECKIR = 0x200000,
> + RADV_DEBUG_NOTHREADLLVM = 0x400000,
> };
>
> enum {
> diff --git a/src/amd/vulkan/radv_device.c
> b/src/amd/vulkan/radv_device.c
> index ad3465f594e..73c48cef1f0 100644
> --- a/src/amd/vulkan/radv_device.c
> +++ b/src/amd/vulkan/radv_device.c
> @@ -436,6 +436,7 @@ static const struct debug_control
> radv_debug_options[] = {
> {"errors", RADV_DEBUG_ERRORS},
> {"startup", RADV_DEBUG_STARTUP},
> {"checkir", RADV_DEBUG_CHECKIR},
> + {"nothreadllvm", RADV_DEBUG_NOTHREADLLVM},
> {NULL, 0}
> };
>
> diff --git a/src/amd/vulkan/radv_llvm_helper.cpp
> b/src/amd/vulkan/radv_llvm_helper.cpp
> new file mode 100644
> index 00000000000..dad881f6b1a
> --- /dev/null
> +++ b/src/amd/vulkan/radv_llvm_helper.cpp
> @@ -0,0 +1,148 @@
> +/*
> + * Copyright © 2018 Red Hat.
> + *
> + * Permission is hereby granted, free of charge, to any person
> obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> the
> + * Software is furnished to do so, subject to the following
> conditions:
> + *
> + * The above copyright notice and this permission notice (including
> the next
> + * paragraph) shall be included in all copies or substantial portions
> of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
> OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + */
> +#include "ac_llvm_util.h"
> +#include "ac_llvm_build.h"
> +#include "radv_shader_helper.h"
> +#include <llvm-c/Core.h>
> +#include <llvm-c/Support.h>
> +#include <llvm/Target/TargetMachine.h>
> +#include <llvm/Analysis/TargetLibraryInfo.h>
> +#include <llvm/IR/LegacyPassManager.h>
> +#if HAVE_LLVM >= 0x0700
> +#include <llvm-c/Transforms/Utils.h>
> +#endif
> +#if HAVE_LLVM < 0x0700
> +#include "llvm/Support/raw_ostream.h"
> +#endif
> +
> +class radv_llvm_per_thread_info {
> +public:
> + radv_llvm_per_thread_info(enum radeon_family arg_family,
> + enum ac_target_machine_options arg_tm_options)
> + : family(arg_family), tm_options(arg_tm_options) {}
> +
> + ~radv_llvm_per_thread_info()
> + {
> + ac_destroy_llvm_passes(passes);
> + ac_destroy_llvm_compiler(&llvm_info);
> + }
> +
> + bool init(void)
> + {
> + if (!ac_init_llvm_compiler(&llvm_info,
> + true,
> + family,
> + tm_options))
> + return false;
> +
> + passes = ac_create_llvm_passes(llvm_info.tm);
> + if (!passes)
> + return false;
> +
> + return true;
> + }
> +
> + bool compile_to_memory_buffer(LLVMModuleRef module,
> + struct ac_shader_binary *binary)
> + {
> + return ac_compile_module_to_binary(passes, module, binary);
> + }
> +
> + bool is_same(enum radeon_family arg_family,
> + enum ac_target_machine_options arg_tm_options) {
> + if (arg_family == family &&
> + arg_tm_options == tm_options)
> + return true;
> + return false;
> + }
> + struct ac_llvm_compiler llvm_info;
> +private:
> + enum radeon_family family;
> + enum ac_target_machine_options tm_options;
> + struct ac_compiler_passes *passes;
> +};
> +
> +/* we have to store a linked list per thread due to the possiblity of
> multiple gpus being required */
> +static thread_local std::list<radv_llvm_per_thread_info>
> radv_llvm_per_thread_list;
> +
> +bool radv_compile_to_binary(struct ac_llvm_compiler *info,
> + LLVMModuleRef module,
> + struct ac_shader_binary *binary)
> +{
> + radv_llvm_per_thread_info *thread_info = nullptr;
> +
> + for (auto &I : radv_llvm_per_thread_list) {
> + if (I.llvm_info.tm == info->tm) {
> + thread_info = &I;
> + break;
> + }
> + }
> +
> + if (!thread_info) {
> + struct ac_compiler_passes *passes = ac_create_llvm_passes(info->tm);
> + bool ret = ac_compile_module_to_binary(passes, module, binary);
> + ac_destroy_llvm_passes(passes);
> + return ret;
> + }
> +
> + return thread_info->compile_to_memory_buffer(module, binary);
> +}
> +
> +bool radv_init_llvm_compiler(struct ac_llvm_compiler *info,
> + bool okay_to_leak_target_library_info,
> + bool thread_compiler,
> + enum radeon_family family,
> + enum ac_target_machine_options tm_options)
> +{
> + if (thread_compiler) {
> + for (auto &I : radv_llvm_per_thread_list) {
> + if (I.is_same(family, tm_options)) {
> + *info = I.llvm_info;
> + return true;
> + }
> + }
> +
> + radv_llvm_per_thread_list.emplace_back(family, tm_options);
> + radv_llvm_per_thread_info &tinfo = radv_llvm_per_thread_list.back();
> +
> + if (!tinfo.init())
> + return false;
> +
> + *info = tinfo.llvm_info;
> + return true;
> + }
> +
> + if (!ac_init_llvm_compiler(info,
> + okay_to_leak_target_library_info,
> + family,
> + tm_options))
> + return false;
> + return true;
> +}
> +
> +void radv_destroy_llvm_compiler(struct ac_llvm_compiler *info,
> + bool thread_compiler)
> +{
> + if (!thread_compiler)
> + ac_destroy_llvm_compiler(info);
> +}
> diff --git a/src/amd/vulkan/radv_nir_to_llvm.c
> b/src/amd/vulkan/radv_nir_to_llvm.c
> index 15c10493022..6bebab6e6ba 100644
> --- a/src/amd/vulkan/radv_nir_to_llvm.c
> +++ b/src/amd/vulkan/radv_nir_to_llvm.c
> @@ -27,6 +27,7 @@
>
> #include "radv_private.h"
> #include "radv_shader.h"
> +#include "radv_shader_helper.h"
> #include "nir/nir.h"
>
> #include <llvm-c/Core.h>
> @@ -3328,12 +3329,7 @@ static unsigned ac_llvm_compile(LLVMModuleRef M,
> struct ac_llvm_compiler *ac_llvm)
> {
> unsigned retval = 0;
> - char *err;
> LLVMContextRef llvm_ctx;
> - LLVMMemoryBufferRef out_buffer;
> - unsigned buffer_size;
> - const char *buffer_data;
> - LLVMBool mem_err;
>
> /* Setup Diagnostic Handler*/
> llvm_ctx = LLVMGetModuleContext(M);
> @@ -3342,27 +3338,8 @@ static unsigned ac_llvm_compile(LLVMModuleRef M,
> &retval);
>
> /* Compile IR*/
> - mem_err = LLVMTargetMachineEmitToMemoryBuffer(ac_llvm->tm, M,
> LLVMObjectFile,
> - &err, &out_buffer);
> -
> - /* Process Errors/Warnings */
> - if (mem_err) {
> - fprintf(stderr, "%s: %s", __FUNCTION__, err);
> - free(err);
> + if (!radv_compile_to_binary(ac_llvm, M, binary))
> retval = 1;
> - goto out;
> - }
> -
> - /* Extract Shader Code*/
> - buffer_size = LLVMGetBufferSize(out_buffer);
> - buffer_data = LLVMGetBufferStart(out_buffer);
> -
> - ac_elf_read(buffer_data, buffer_size, binary);
> -
> - /* Clean up */
> - LLVMDisposeMemoryBuffer(out_buffer);
> -
> -out:
> return retval;
> }
>
> diff --git a/src/amd/vulkan/radv_shader.c
> b/src/amd/vulkan/radv_shader.c
> index 5cca761d89e..13990059985 100644
> --- a/src/amd/vulkan/radv_shader.c
> +++ b/src/amd/vulkan/radv_shader.c
> @@ -30,6 +30,7 @@
> #include "radv_debug.h"
> #include "radv_private.h"
> #include "radv_shader.h"
> +#include "radv_shader_helper.h"
> #include "nir/nir.h"
> #include "nir/nir_builder.h"
> #include "spirv/nir_spirv.h"
> @@ -542,7 +543,7 @@ shader_variant_create(struct radv_device *device,
> struct radv_shader_variant *variant;
> struct ac_shader_binary binary;
> struct ac_llvm_compiler ac_llvm;
> -
> + bool thread_compiler;
> variant = calloc(1, sizeof(struct radv_shader_variant));
> if (!variant)
> return NULL;
> @@ -564,8 +565,11 @@ shader_variant_create(struct radv_device *device,
> if (options->check_ir)
> tm_options |= AC_TM_CHECK_IR;
>
> + thread_compiler = !(device->instance->debug_flags &
> RADV_DEBUG_NOTHREADLLVM);
> radv_init_llvm_once();
> - ac_init_llvm_compiler(&ac_llvm, false, chip_family, tm_options);
> + radv_init_llvm_compiler(&ac_llvm, false,
> + thread_compiler,
> + chip_family, tm_options);
> if (gs_copy_shader) {
> assert(shader_count == 1);
> radv_compile_gs_copy_shader(&ac_llvm, *shaders, &binary,
> @@ -577,7 +581,7 @@ shader_variant_create(struct radv_device *device,
> options);
> }
>
> - ac_destroy_llvm_compiler(&ac_llvm);
> + radv_destroy_llvm_compiler(&ac_llvm, thread_compiler);
>
> radv_fill_shader_variant(device, variant, &binary, stage);
>
> diff --git a/src/amd/vulkan/radv_shader_helper.h
> b/src/amd/vulkan/radv_shader_helper.h
> new file mode 100644
> index 00000000000..3c81f5be54a
> --- /dev/null
> +++ b/src/amd/vulkan/radv_shader_helper.h
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright © 2018 Red Hat.
> + *
> + * Permission is hereby granted, free of charge, to any person
> obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> the
> + * Software is furnished to do so, subject to the following
> conditions:
> + *
> + * The above copyright notice and this permission notice (including
> the next
> + * paragraph) shall be included in all copies or substantial portions
> of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
> OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + */
> +#ifndef RADV_SHADER_HELPER_H
> +#define RADV_SHADER_HELPER_H
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +bool radv_init_llvm_compiler(struct ac_llvm_compiler *info,
> + bool okay_to_leak_target_library_info,
> + bool thread_compiler,
> + enum radeon_family family,
> + enum ac_target_machine_options tm_options);
> +void radv_destroy_llvm_compiler(struct ac_llvm_compiler *info,
> + bool thread_compiler);
> +
> +bool radv_compile_to_binary(struct ac_llvm_compiler *info,
> + LLVMModuleRef module,
> + struct ac_shader_binary *binary);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +#endif
More information about the mesa-dev
mailing list