def run_template(): fn, contains, avoids = combo_svml_usecase(dtype, mode, vlen, flags['fastmath'], flags['name']) # look for specific patters in the asm for a given target with override_env_config('NUMBA_CPU_NAME', vlen2cpu[vlen]), \ override_env_config('NUMBA_CPU_FEATURES', vlen2cpu_features[vlen]): # recompile for overridden CPU try: jitted_fn = njit(sig, fastmath=flags['fastmath'], error_model=flags['error_model'],)(fn) except: raise Exception("raised while compiling "+fn.__doc__) asm = jitted_fn.inspect_asm(sig) missed = [pattern for pattern in contains if not pattern in asm] found = [pattern for pattern in avoids if pattern in asm] ok = not missed and not found detail = '\n'.join( [line for line in asm.split('\n') if cls.asm_filter.search(line) and not '"' in line]) msg = ( f"While expecting {missed} and not {found},\n" f"it contains:\n{detail}\n" f"when compiling {fn.__doc__}" ) return ok, msg
def check(self, pyfunc, *args, **kwargs): jitstd, jitfast = self.compile(pyfunc, *args) std_pattern = kwargs.pop('std_pattern', None) fast_pattern = kwargs.pop('fast_pattern', None) cpu_name = kwargs.pop('cpu_name', 'skylake-avx512') # python result py_expected = pyfunc(*self.copy_args(*args)) # jit result jitstd_result = jitstd.entry_point(*self.copy_args(*args)) # fastmath result jitfast_result = jitfast.entry_point(*self.copy_args(*args)) # assert numerical equality np.testing.assert_almost_equal(jitstd_result, py_expected, **kwargs) np.testing.assert_almost_equal(jitfast_result, py_expected, **kwargs) # look for specific patters in the asm for a given target with override_env_config('NUMBA_CPU_NAME', cpu_name), \ override_env_config('NUMBA_CPU_FEATURES', ''): # recompile for overridden CPU jitstd, jitfast = self.compile(pyfunc, *args) if std_pattern: self.check_svml_presence(jitstd, std_pattern) if fast_pattern: self.check_svml_presence(jitfast, fast_pattern)
def create_config_effect(self, cfg): """ Returns a config "original" from a location with no config file and then the impact of applying the supplied cfg dictionary as a config file at a location in the returned "current". """ # store original cwd original_cwd = os.getcwd() # create mock launch location launch_dir = self.mock_cfg_location() # switch cwd to the mock launch location, get and store settings os.chdir(launch_dir) # use override to ensure that the config is zero'd out with respect # to any existing settings with override_env_config('_', '_'): original = self.get_settings() # inject new config into a file in the mock launch location self.inject_mock_cfg(launch_dir, cfg) try: # override something but don't change the value, this is to refresh # the config and make sure the injected config file is read with override_env_config('_', '_'): current = self.get_settings() finally: # switch back to original dir with no new config os.chdir(original_cwd) return original, current
def check(self, pyfunc, *args, **kwargs): jitstd, jitfast = self.compile(pyfunc, *args) std_pattern = kwargs.pop('std_pattern', None) fast_pattern = kwargs.pop('fast_pattern', None) cpu_name = kwargs.pop('cpu_name', 'skylake-avx512') # force LLVM to use AVX512 registers for vectorization # https://reviews.llvm.org/D67259 cpu_features = kwargs.pop('cpu_features', '-prefer-256-bit') # python result py_expected = pyfunc(*self.copy_args(*args)) # jit result jitstd_result = jitstd.entry_point(*self.copy_args(*args)) # fastmath result jitfast_result = jitfast.entry_point(*self.copy_args(*args)) # assert numerical equality np.testing.assert_almost_equal(jitstd_result, py_expected, **kwargs) np.testing.assert_almost_equal(jitfast_result, py_expected, **kwargs) # look for specific patters in the asm for a given target with override_env_config('NUMBA_CPU_NAME', cpu_name), \ override_env_config('NUMBA_CPU_FEATURES', cpu_features): # recompile for overridden CPU jitstd, jitfast = self.compile(pyfunc, *args) if std_pattern: self.check_svml_presence(jitstd, std_pattern) if fast_pattern: self.check_svml_presence(jitfast, fast_pattern)
def test_template(self): fn, contains, avoids = combo_svml_usecase(*args) # look for specific patters in the asm for a given target with override_env_config("NUMBA_CPU_NAME", vlen2cpu[vlen]), override_env_config( "NUMBA_CPU_FEATURES", ""): # recompile for overridden CPU try: jit = compile_isolated(fn, (numba.int64, ), flags=flags) except: raise Exception("raised while compiling " + fn.__doc__) asm = jit.library.get_asm_str() missed = [pattern for pattern in contains if not pattern in asm] found = [pattern for pattern in avoids if pattern in asm] self.assertTrue( not missed and not found, "While expecting %s and no %s,\nit contains:\n%s\nwhen compiling %s" % ( str(missed), str(found), "\n".join([ line for line in asm.split("\n") if cls.asm_filter.search(line) and not '"' in line ]), fn.__doc__, ), )
def gen_ir(self, func, args_tuple, fastmath=False): with override_env_config("NUMBA_CPU_NAME", "skylake-avx512"), override_env_config( "NUMBA_CPU_FEATURES", ""): _flags = Flags() _flags.set('fastmath', FastMathOptions(fastmath)) jitted = compile_isolated(func, args_tuple, flags=_flags) return jitted.library.get_llvm_str()
def gen_ir(self, func, args_tuple, **flags): with override_env_config("NUMBA_CPU_NAME", "skylake-avx512"), override_env_config( "NUMBA_CPU_FEATURES", ""): jobj = njit(**flags)(func) jobj.compile(args_tuple) ol = jobj.overloads[jobj.signatures[0]] return ol.library.get_llvm_str()
def test_user_set_cpu_features(self): self.check_pycache(0) mod = self.import_module() mod.self_test() cache_size = len(self.cache_contents()) mtimes = self.get_cache_mtimes() # Change CPU feature my_cpu_features = '-sse;-avx' system_features = codegen.get_host_cpu_features() self.assertNotEqual(system_features, my_cpu_features) with override_env_config('NUMBA_CPU_FEATURES', my_cpu_features): self.run_in_separate_process() self.check_later_mtimes(mtimes) self.assertGreater(len(self.cache_contents()), cache_size) # Check cache index cache = mod.add_usecase._cache cache_file = cache._cache_file cache_index = cache_file._load_index() self.assertEqual(len(cache_index), 2) [key_a, key_b] = cache_index.keys() if key_a[1][2] == system_features: key_host, key_generic = key_a, key_b else: key_host, key_generic = key_b, key_a self.assertEqual(key_host[1][1], ll.get_host_cpu_name()) self.assertEqual(key_host[1][2], system_features) self.assertEqual(key_generic[1][1], ll.get_host_cpu_name()) self.assertEqual(key_generic[1][2], my_cpu_features)
def test_user_set_cpu_name(self): self.check_pycache(0) mod = self.import_module() mod.self_test() cache_size = len(self.cache_contents()) mtimes = self.get_cache_mtimes() # Change CPU name to generic with override_env_config('NUMBA_CPU_NAME', 'generic'): self.run_in_separate_process() self.check_later_mtimes(mtimes) self.assertGreater(len(self.cache_contents()), cache_size) # Check cache index cache = mod.add_usecase._cache cache_file = cache._cache_file cache_index = cache_file._load_index() self.assertEqual(len(cache_index), 2) [key_a, key_b] = cache_index.keys() if key_a[1][1] == ll.get_host_cpu_name(): key_host, key_generic = key_a, key_b else: key_host, key_generic = key_b, key_a self.assertEqual(key_host[1][1], ll.get_host_cpu_name()) self.assertEqual(key_host[1][2], codegen.get_host_cpu_features()) self.assertEqual(key_generic[1][1], 'generic') self.assertEqual(key_generic[1][2], '')
def test_no_cuda_boundscheck(self): with self.assertRaises(NotImplementedError): @cuda.jit(boundscheck=True) def func(): pass # Make sure we aren't raising "not supported" error if we aren't # requesting bounds checking anyway. Related pull request: #5257 @cuda.jit(boundscheck=False) def func3(): pass with override_env_config('NUMBA_BOUNDSCHECK', '1'): @cuda.jit def func2(x, a): a[1] = x[1] a = np.ones((1, )) x = np.zeros((1, )) # Out of bounds but doesn't raise (it does raise in the simulator, # so skip there) if not config.ENABLE_CUDASIM: func2[1, 1](x, a)
def test_boundscheck_disabled(self): with override_env_config('NUMBA_BOUNDSCHECK', '0'): a = np.array([1]) # Doesn't raise self.default(a) self.off(a) self.on(a)
def test_boundscheck_enabled(self): with override_env_config('NUMBA_BOUNDSCHECK', '1'): a = np.array([1]) with self.assertRaises(IndexError): self.default(a) self.off(a) self.on(a)
def test_array_debug_opt_stats(self): """ Test that NUMBA_DEBUG_ARRAY_OPT_STATS produces valid output """ # deliberately trigger a compilation loop to increment the # Parfor class state, this is to ensure the test works based # on indices computed based on this state and not hard coded # indices. cres = compile_isolated(supported_parfor, (types.int64, ), flags=force_parallel_flags) with override_env_config("NUMBA_DEBUG_ARRAY_OPT_STATS", "1"): with captured_stdout() as out: cres = compile_isolated(supported_parfor, (types.int64, ), flags=force_parallel_flags) # grab the various parts out the output output = out.getvalue().split("\n") parallel_loop_output = [ x for x in output if "is produced from pattern" in x ] fuse_output = [x for x in output if "is fused into" in x] after_fusion_output = [ x for x in output if "After fusion, function" in x ] # Parfor's have a shared state index, grab the current value # as it will be used as an offset for all loop messages parfor_state = int( re.compile(r"#([0-9]+)").search( parallel_loop_output[0]).group(1)) bounds = range(parfor_state, parfor_state + len(parallel_loop_output)) # Check the Parallel for-loop <index> is produced from <pattern> # works first pattern = ("('ones function', 'NumPy mapping')", ("prange", "user", "")) fmt = "Parallel for-loop #{} is produced from pattern '{}' at" for i, trials, lpattern in zip(bounds, parallel_loop_output, pattern): to_match = fmt.format(i, lpattern) self.assertIn(to_match, trials) # Check the fusion statements are correct pattern = (parfor_state + 1, parfor_state + 0) fmt = "Parallel for-loop #{} is fused into for-loop #{}." for trials in fuse_output: to_match = fmt.format(*pattern) self.assertIn(to_match, trials) # Check the post fusion statements are correct pattern = (supported_parfor.__name__, 1, set([parfor_state])) fmt = "After fusion, function {} has {} parallel for-loop(s) #{}." for trials in after_fusion_output: to_match = fmt.format(*pattern) self.assertIn(to_match, trials)
def test_boundscheck_unset(self): with override_env_config('NUMBA_BOUNDSCHECK', ''): a = np.array([1]) # Doesn't raise self.default(a) self.off(a) with self.assertRaises(IndexError): self.on(a)
def test_debug(self): out = self.compile_simple_nopython() self.assertFalse(out) with override_env_config('NUMBA_DEBUG', '1'): out = self.compile_simple_nopython() # Note that all variables dependent on NUMBA_DEBUG are # updated too. self.check_debug_output(out, ['ir', 'typeinfer', 'llvm', 'func_opt_llvm', 'optimized_llvm', 'assembly']) out = self.compile_simple_nopython() self.assertFalse(out)
def test_get_numba_envvar(self): # Make up an env-var that is not already defined. # This makes a string with the following regex pattern "NUMBA_0+" env = "0" while f"NUMBA_{env}" in os.environ: env += "0" default = "the default" # Check that we are getting the default got = envvars.get_numba_envvar(env, default=default) self.assertIs(got, default) # Check that we are reading the env-var correctly with override_env_config(f"NUMBA_{env}", "my value"): got = envvars.get_numba_envvar(env, default=default) self.assertEqual(got, "my value")
def test_no_cuda_boundscheck(self): with self.assertRaises(NotImplementedError): @cuda.jit(boundscheck=True) def func(): pass with override_env_config('NUMBA_BOUNDSCHECK', '1'): @cuda.jit def func2(x, a): a[1] = x[1] a = np.ones((1,)) x = np.zeros((1,)) # Out of bounds but doesn't raise (it does raise in the simulator, # so skip there) if not config.ENABLE_CUDASIM: func2[1, 1](x, a)
def test_debug(self): out = self.compile_simple_nopython() self.assertFalse(out) with override_env_config("NUMBA_DEBUG", "1"): out = self.compile_simple_nopython() # Note that all variables dependent on NUMBA_DEBUG are # updated too. self.check_debug_output( out, [ "ir", "typeinfer", "llvm", "func_opt_llvm", "optimized_llvm", "assembly", ], ) out = self.compile_simple_nopython() self.assertFalse(out)