fftw: simplify the recipe and make use of specific targets (#12889)
* fftw: grouped precisions in a single variant * fftw: simd options are now based on target features and not on variants * fftw: simplified computing the selected precisions
This commit is contained in:
		 Massimiliano Culpo
					Massimiliano Culpo
				
			
				
					committed by
					
						 Adam J. Stewart
						Adam J. Stewart
					
				
			
			
				
	
			
			
			 Adam J. Stewart
						Adam J. Stewart
					
				
			
						parent
						
							46e319ecd4
						
					
				
				
					commit
					2cd800306d
				
			| @@ -3,12 +3,12 @@ | ||||
| # | ||||
| # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||
|  | ||||
| from spack import * | ||||
| from spack.spec import ConflictsInSpecError | ||||
| import os | ||||
| import os.path | ||||
|  | ||||
| import llnl.util.lang | ||||
| # os is used for rename, etc in patch() | ||||
| import os | ||||
|  | ||||
| from spack import * | ||||
|  | ||||
|  | ||||
| class Fftw(AutotoolsPackage): | ||||
| @@ -35,84 +35,32 @@ class Fftw(AutotoolsPackage): | ||||
|     patch('pgi-3.3.6-pl2.patch', when="@3.3.6-pl2%pgi", level=0) | ||||
|  | ||||
|     variant( | ||||
|         'float', default=True, | ||||
|         description='Produces a single precision version of the library') | ||||
|     variant( | ||||
|         'double', default=True, | ||||
|         description='Produces a double precision version of the library') | ||||
|     variant( | ||||
|         'long_double', default=True, | ||||
|         description='Produces a long double precision version of the library') | ||||
|     variant( | ||||
|         'quad', default=False, | ||||
|         description='Produces a quad precision version of the library ' | ||||
|                     '(works only with GCC and libquadmath)') | ||||
|         'precision', values=any_combination_of( | ||||
|             'float', 'double', 'long_double', 'quad' | ||||
|         ).prohibit_empty_set().with_default('float,double'), | ||||
|         description='Build the selected floating-point precision libraries' | ||||
|     ) | ||||
|     variant('openmp', default=False, description="Enable OpenMP support.") | ||||
|     variant('mpi', default=True, description='Activate MPI support') | ||||
|     variant( | ||||
|         'pfft_patches', default=False, | ||||
|         description='Add extra transpose functions for PFFT compatibility') | ||||
|  | ||||
|     variant( | ||||
|         'simd', | ||||
|         default='generic-simd128,generic-simd256', | ||||
|         values=( | ||||
|             'sse', 'sse2', 'avx', 'avx2', 'avx512',  # Intel | ||||
|             'avx-128-fma', 'kcvi',  # Intel | ||||
|             'altivec', 'vsx',  # IBM | ||||
|             'neon',  # ARM | ||||
|             'generic-simd128', 'generic-simd256'  # Generic | ||||
|         ), | ||||
|         description='Optimizations that are enabled in this build', | ||||
|         multi=True | ||||
|     ) | ||||
|     variant('fma', default=False, description='Activate support for fma') | ||||
|  | ||||
|     depends_on('mpi', when='+mpi') | ||||
|     depends_on('automake', type='build', when='+pfft_patches') | ||||
|     depends_on('autoconf', type='build', when='+pfft_patches') | ||||
|     depends_on('libtool', type='build', when='+pfft_patches') | ||||
|  | ||||
|     # https://github.com/FFTW/fftw3/commit/902d0982522cdf6f0acd60f01f59203824e8e6f3 | ||||
|     conflicts('%gcc@8:8.9999', when="@3.3.7") | ||||
|     conflicts('precision=long_double', when='@2.1.5', | ||||
|               msg='Long double precision is not supported in FFTW 2') | ||||
|     conflicts('precision=quad', when='@2.1.5', | ||||
|               msg='Quad precision is not supported in FFTW 2') | ||||
|  | ||||
|     provides('fftw-api@2', when='@2.1.5') | ||||
|     provides('fftw-api@3', when='@3:') | ||||
|  | ||||
|     def flag_handler(self, name, flags): | ||||
|         arch = "" | ||||
|         spec = self.spec | ||||
|         target_simds = { | ||||
|             ('x86_64',): ('sse', 'sse2', 'avx', 'avx2', 'avx512', | ||||
|                           'avx-128-fma', 'kcvi'), | ||||
|             ('ppc', 'ppc64le', 'power7'): ('altivec', 'vsx'), | ||||
|             ('arm',): ('neon',) | ||||
|         } | ||||
|  | ||||
|         if spec.satisfies("platform=cray"): | ||||
|             # FIXME; It is assumed that cray is x86_64. | ||||
|             # If you support arm on cray, you need to fix it. | ||||
|             arch  = "x86_64" | ||||
|  | ||||
|         for targets, simds in target_simds.items(): | ||||
|             if ( | ||||
|                 (arch not in targets) | ||||
|                 and str(spec.target.family) not in targets | ||||
|             ): | ||||
|                 if any(spec.satisfies('simd={0}'.format(x)) for x in simds): | ||||
|                     raise ConflictsInSpecError( | ||||
|                         spec, | ||||
|                         [( | ||||
|                             spec, | ||||
|                             spec.architecture.target, | ||||
|                             spec.variants['simd'], | ||||
|                             'simd={0} are valid only on {1}'.format( | ||||
|                                 ','.join(target_simds[targets]), | ||||
|                                 ','.join(targets) | ||||
|                             ) | ||||
|                         )] | ||||
|                     ) | ||||
|         return (flags, None, None) | ||||
|  | ||||
|     @property | ||||
|     def libs(self): | ||||
|  | ||||
| @@ -157,6 +105,11 @@ def autoreconf(self, spec, prefix): | ||||
|             autoreconf = which('autoreconf') | ||||
|             autoreconf('-ifv') | ||||
|  | ||||
|     @property | ||||
|     def selected_precisions(self): | ||||
|         """Precisions that have been selected in this build""" | ||||
|         return self.spec.variants['precision'].value | ||||
|  | ||||
|     def configure(self, spec, prefix): | ||||
|         # Base options | ||||
|         options = [ | ||||
| @@ -184,68 +137,60 @@ def configure(self, spec, prefix): | ||||
|         if '+mpi' in spec: | ||||
|             options.append('--enable-mpi') | ||||
|  | ||||
|         # SIMD support | ||||
|         float_options, double_options = [], [] | ||||
|         if spec.satisfies('@3:', strict=True): | ||||
|             for opts in (float_options, double_options): | ||||
|                 opts += self.enable_or_disable('simd') | ||||
|                 opts += self.enable_or_disable('fma') | ||||
|         # Specific SIMD support. Note there's SSE support too for float, but | ||||
|         # given that it can be activated only for float and that most machines | ||||
|         # are new enough to have SSE2 it has been skipped not to complicate the | ||||
|         # recipe further. | ||||
|         simd_features = ['sse2', 'avx', 'avx2', 'avx512', 'avx-128-fma', | ||||
|                          'kcvi', 'altivec', 'vsx', 'neon'] | ||||
|         simd_options = [] | ||||
|         for feature in simd_features: | ||||
|             msg = '--enable-{0}' if feature in spec.target else '--disable-{0}' | ||||
|             simd_options.append(msg.format(feature)) | ||||
|  | ||||
|         # If no features are found, enable the generic ones | ||||
|         if not any(f in spec.target for f in simd_features): | ||||
|             simd_options += [ | ||||
|                 '--enable-generic-simd128', | ||||
|                 '--enable-generic-simd256' | ||||
|             ] | ||||
|  | ||||
|         simd_options += [ | ||||
|             '--enable-fma' if 'fma' in spec.target else '--disable-fma' | ||||
|         ] | ||||
|  | ||||
|         # Double is the default precision, for all the others we need | ||||
|         # to enable the corresponding option. | ||||
|         enable_precision = { | ||||
|             'float': ['--enable-float'], | ||||
|             'double': None, | ||||
|             'long_double': ['--enable-long-double'], | ||||
|             'quad': ['--enable-quad-precision'] | ||||
|         } | ||||
|  | ||||
|         # Different precisions must be configured and compiled one at a time | ||||
|         configure = Executable('../configure') | ||||
|         for precision in self.selected_precisions: | ||||
|             opts = (enable_precision[precision] or []) + options[:] | ||||
|  | ||||
|         # Build double/float/long double/quad variants | ||||
|         if '+double' in spec: | ||||
|             with working_dir('double', create=True): | ||||
|                 configure(*(options + double_options)) | ||||
|         if '+float' in spec: | ||||
|             with working_dir('float', create=True): | ||||
|                 configure('--enable-float', *(options + float_options)) | ||||
|         if spec.satisfies('@3:+long_double'): | ||||
|             with working_dir('long-double', create=True): | ||||
|                 configure('--enable-long-double', *options) | ||||
|         if spec.satisfies('@3:+quad'): | ||||
|             with working_dir('quad', create=True): | ||||
|                 configure('--enable-quad-precision', *options) | ||||
|             # SIMD optimizations are available only for float and double | ||||
|             # starting from FFTW 3 | ||||
|             if precision in ('float', 'double') and spec.satisfies('@3:'): | ||||
|                 opts += simd_options | ||||
|  | ||||
|             with working_dir(precision, create=True): | ||||
|                 configure(*opts) | ||||
|  | ||||
|     def for_each_precision_make(self, *targets): | ||||
|         for precision in self.selected_precisions: | ||||
|             with working_dir(precision): | ||||
|                 make(*targets) | ||||
|  | ||||
|     def build(self, spec, prefix): | ||||
|         if '+double' in spec: | ||||
|             with working_dir('double'): | ||||
|                 make() | ||||
|         if '+float' in spec: | ||||
|             with working_dir('float'): | ||||
|                 make() | ||||
|         if spec.satisfies('@3:+long_double'): | ||||
|             with working_dir('long-double'): | ||||
|                 make() | ||||
|         if spec.satisfies('@3:+quad'): | ||||
|             with working_dir('quad'): | ||||
|                 make() | ||||
|         self.for_each_precision_make() | ||||
|  | ||||
|     def check(self): | ||||
|         spec = self.spec | ||||
|         if '+double' in spec: | ||||
|             with working_dir('double'): | ||||
|                 make("check") | ||||
|         if '+float' in spec: | ||||
|             with working_dir('float'): | ||||
|                 make("check") | ||||
|         if spec.satisfies('@3:+long_double'): | ||||
|             with working_dir('long-double'): | ||||
|                 make("check") | ||||
|         if spec.satisfies('@3:+quad'): | ||||
|             with working_dir('quad'): | ||||
|                 make("check") | ||||
|         self.for_each_precision_make('check') | ||||
|  | ||||
|     def install(self, spec, prefix): | ||||
|         if '+double' in spec: | ||||
|             with working_dir('double'): | ||||
|                 make("install") | ||||
|         if '+float' in spec: | ||||
|             with working_dir('float'): | ||||
|                 make("install") | ||||
|         if spec.satisfies('@3:+long_double'): | ||||
|             with working_dir('long-double'): | ||||
|                 make("install") | ||||
|         if spec.satisfies('@3:+quad'): | ||||
|             with working_dir('quad'): | ||||
|                 make("install") | ||||
|         self.for_each_precision_make('install') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user