diff options
author | Sayed Adel <seiko@imavr.com> | 2020-06-13 18:15:41 +0200 |
---|---|---|
committer | Sayed Adel <seiko@imavr.com> | 2020-06-15 22:49:27 +0200 |
commit | 4c97add06371bf80f3bc02e0cfb0ee83737b909c (patch) | |
tree | ff6de3901d33d82d11b474b081e5d817850884b2 /numpy/distutils/command/build_clib.py | |
parent | 8ccd582937a182391f49f412908fecf1770787d7 (diff) | |
download | numpy-4c97add06371bf80f3bc02e0cfb0ee83737b909c.tar.gz |
ENH: [3/7] enable multi-platform SIMD compiler optimizations
- Put `CCompilerOpt` in action through add two command line
arguments that passed directly to `CCompilerOpt`'s
parameters which explained as follows:
* `--cpu-baseline` minimal set of required optimizations,
default is 'min' which provides the minimum CPU features
that can safely run on a wide range of users platforms.
* `--cpu-dispatch` dispatched set of additional optimizations,
default is 'max-xop-fma4' which enables all CPU features,
except for AMD legacy features.
the new arguments can be reached from `build`, `build_clib`,
`build_ext`, if `build_clib` or `build_ext` are not specified
by the user the arguments of `build` will be used, which also
hold the default values.
- Activate the new compiler dispatcher that comes with `CCompilerOpt`,
through adding a hock inside `build_clib` and `build_ext`
that works as a filter taking any C source files ends with
`.dispatch.c` and pass it directly to `CCompilerOpt` and
then take returned objects and linked to the final C lib.
- Add a third command-line argument `--disable-optimization` which
explicitly disable the whole new infrastructure, also
It adds a new compiler definition called `NPY_DISABLE_OPTIMIZATION`.
when `--disable-optimization` is enabled the dispatch-able sources
that end with `.dispatch.c` will be treated as a normal
C sources, also due to this disabling any C headers that
generated by `CCompilerOpt` must guard it with `NPY_DISABLE_OPTIMIZATION`,
otherwise, it will definitely break the build.
- New auto-generated C header located at `core/include/numpy/_cpu_dispatch.h`,
the new header contains all definitions and headers of CPU features that
enabled according to specified configuration in `--cpu-baseline`
and `--cpu-dispatch`.
Diffstat (limited to 'numpy/distutils/command/build_clib.py')
-rw-r--r-- | numpy/distutils/command/build_clib.py | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/numpy/distutils/command/build_clib.py b/numpy/distutils/command/build_clib.py index f6a84e351..87345adbc 100644 --- a/numpy/distutils/command/build_clib.py +++ b/numpy/distutils/command/build_clib.py @@ -13,6 +13,7 @@ from numpy.distutils.misc_util import ( filter_sources, get_lib_source_files, get_numpy_include_dirs, has_cxx_sources, has_f_sources, is_sequence ) +from numpy.distutils.ccompiler_opt import new_ccompiler_opt # Fix Python distutils bug sf #1718574: _l = old_build_clib.user_options @@ -34,9 +35,16 @@ class build_clib(old_build_clib): "number of parallel jobs"), ('warn-error', None, "turn all warnings into errors (-Werror)"), + ('cpu-baseline=', None, + "specify a list of enabled baseline CPU optimizations"), + ('cpu-dispatch=', None, + "specify a list of dispatched CPU optimizations"), + ('disable-optimization', None, + "disable CPU optimized code(dispatch,simd,fast...)"), ] - boolean_options = old_build_clib.boolean_options + ['inplace', 'warn-error'] + boolean_options = old_build_clib.boolean_options + \ + ['inplace', 'warn-error', 'disable-optimization'] def initialize_options(self): old_build_clib.initialize_options(self) @@ -44,6 +52,10 @@ class build_clib(old_build_clib): self.inplace = 0 self.parallel = None self.warn_error = None + self.cpu_baseline = None + self.cpu_dispatch = None + self.disable_optimization = None + def finalize_options(self): if self.parallel: @@ -55,6 +67,9 @@ class build_clib(old_build_clib): self.set_undefined_options('build', ('parallel', 'parallel'), ('warn_error', 'warn_error'), + ('cpu_baseline', 'cpu_baseline'), + ('cpu_dispatch', 'cpu_dispatch'), + ('disable_optimization', 'disable_optimization') ) def have_f_sources(self): @@ -102,6 +117,25 @@ class build_clib(old_build_clib): self.compiler.show_customization() + if not self.disable_optimization: + opt_cache_path = os.path.abspath( + os.path.join(self.build_temp, 'ccompiler_opt_cache_clib.py' + )) + self.compiler_opt = new_ccompiler_opt( + compiler=self.compiler, cpu_baseline=self.cpu_baseline, + cpu_dispatch=self.cpu_dispatch, cache_path=opt_cache_path + ) + if not self.compiler_opt.is_cached(): + log.info("Detected changes on compiler optimizations, force rebuilding") + self.force = True + + import atexit + def report(): + log.info("\n########### CLIB COMPILER OPTIMIZATION ###########") + log.info(self.compiler_opt.report(full=True)) + + atexit.register(report) + if self.have_f_sources(): from numpy.distutils.fcompiler import new_fcompiler self._f_compiler = new_fcompiler(compiler=self.fcompiler, @@ -211,6 +245,8 @@ class build_clib(old_build_clib): 'extra_f90_compile_args') or [] macros = build_info.get('macros') + if macros is None: + macros = [] include_dirs = build_info.get('include_dirs') if include_dirs is None: include_dirs = [] @@ -223,6 +259,31 @@ class build_clib(old_build_clib): if requiref90: self.mkpath(module_build_dir) + dispatch_objects = [] + if not self.disable_optimization: + dispatch_sources = [ + c_sources.pop(c_sources.index(src)) + for src in c_sources[:] if src.endswith(".dispatch.c") + ] + if dispatch_sources: + if not self.inplace: + build_src = self.get_finalized_command("build_src").build_src + else: + build_src = None + dispatch_objects = self.compiler_opt.try_dispatch( + dispatch_sources, + output_dir=self.build_temp, + src_dir=build_src, + macros=macros, + include_dirs=include_dirs, + debug=self.debug, + extra_postargs=extra_postargs + ) + extra_args_baseopt = extra_postargs + self.compiler_opt.cpu_baseline_flags() + else: + extra_args_baseopt = extra_postargs + macros.append(("NPY_DISABLE_OPTIMIZATION", 1)) + if compiler.compiler_type == 'msvc': # this hack works around the msvc compiler attributes # problem, msvc uses its own convention :( @@ -237,7 +298,8 @@ class build_clib(old_build_clib): macros=macros, include_dirs=include_dirs, debug=self.debug, - extra_postargs=extra_postargs) + extra_postargs=extra_args_baseopt) + objects.extend(dispatch_objects) if cxx_sources: log.info("compiling C++ sources") |