[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