def benchmark_plot(fn=None, cases=None, columns=None, column_titles=None, archs=None, title=None, bars='sync_vs_async', bar_width=0.4, bar_distance=0, left_margin=0, size=(12, 8)): import matplotlib.pyplot as plt import yaml if fn is None: fn = os.path.join(_ti_core.get_repo_dir(), 'benchmarks', 'output', 'benchmark.yml') with open(fn, 'r') as f: data = yaml.load(f, Loader=yaml.SafeLoader) if bars != 'sync_vs_async': # need baseline baseline_dir = os.path.join(_ti_core.get_repo_dir(), 'benchmarks', 'baseline') baseline_file = f'{baseline_dir}/benchmark.yml' with open(baseline_file, 'r') as f: baseline_data = yaml.load(f, Loader=yaml.SafeLoader) if cases is None: cases = list(data.keys()) assert len(cases) >= 1 if len(cases) == 1: cases = [cases[0], cases[0]] ti.warning( 'Function benchmark_plot does not support plotting with only one case for now. Duplicating the item to move on.' ) if columns is None: columns = list(data[cases[0]].keys()) if column_titles is None: column_titles = columns normalize_to_lowest = lambda x: True figure, subfigures = plt.subplots(len(cases), len(columns)) if title is None: title = 'Taichi Performance Benchmarks (Higher means more)' figure.suptitle(title, fontweight="bold") for col_id in range(len(columns)): subfigures[0][col_id].set_title(column_titles[col_id]) for case_id in range(len(cases)): case = cases[case_id] subfigures[case_id][0].annotate( case, xy=(0, 0.5), xytext=(-subfigures[case_id][0].yaxis.labelpad - 5, 0), xycoords=subfigures[case_id][0].yaxis.label, textcoords='offset points', size='large', ha='right', va='center') for col_id in range(len(columns)): col = columns[col_id] if archs is None: current_archs = data[case][col].keys() else: current_archs = [ x for x in archs if x in data[case][col].keys() ] if bars == 'sync_vs_async': y_left = [ data[case][col][arch]['sync'] for arch in current_archs ] label_left = 'sync' y_right = [ data[case][col][arch]['async'] for arch in current_archs ]
def init(arch=None, default_fp=None, default_ip=None, _test_mode=False, enable_fallback=True, **kwargs): """Initializes the Taichi runtime. This should always be the entry point of your Taichi program. Most importantly, it sets the backend used throughout the program. Args: arch: Backend to use. This is usually :const:`~taichi.lang.cpu` or :const:`~taichi.lang.gpu`. default_fp (Optional[type]): Default floating-point type. default_ip (Optional[type]): Default integral type. **kwargs: Taichi provides highly customizable compilation through ``kwargs``, which allows for fine grained control of Taichi compiler behavior. Below we list some of the most frequently used ones. For a complete list, please check out https://github.com/taichi-dev/taichi/blob/master/taichi/program/compile_config.h. * ``cpu_max_num_threads`` (int): Sets the number of threads used by the CPU thread pool. * ``debug`` (bool): Enables the debug mode, under which Taichi does a few more things like boundary checks. * ``print_ir`` (bool): Prints the CHI IR of the Taichi kernels. * ``packed`` (bool): Enables the packed memory layout. See https://docs.taichi.graphics/lang/articles/advanced/layout. """ # Check version for users every 7 days. os.makedirs(_ti_core.get_repo_dir(), exist_ok=True) timestamp_path = os.path.join(_ti_core.get_repo_dir(), 'timestamp') cur_date = datetime.date.today() if os.path.exists(timestamp_path): last_time = '' with open(timestamp_path, 'r') as f: last_time = f.readlines()[0].rstrip() if cur_date.strftime('%Y-%m-%d') > last_time: if check_version(): with open(timestamp_path, 'w') as f: f.write((cur_date + datetime.timedelta(days=14)).strftime('%Y-%m-%d')) f.truncate() else: if check_version(): with open(timestamp_path, 'w') as f: f.write((cur_date + datetime.timedelta(days=14)).strftime('%Y-%m-%d')) # Make a deepcopy in case these args reference to items from ti.cfg, which are # actually references. If no copy is made and the args are indeed references, # ti.reset() could override the args to their default values. default_fp = _deepcopy(default_fp) default_ip = _deepcopy(default_ip) kwargs = _deepcopy(kwargs) ti.reset() spec_cfg = _SpecialConfig() env_comp = _EnvironmentConfigurator(kwargs, ti.cfg) env_spec = _EnvironmentConfigurator(kwargs, spec_cfg) # configure default_fp/ip: # TODO: move these stuff to _SpecialConfig too: env_default_fp = os.environ.get("TI_DEFAULT_FP") if env_default_fp: if default_fp is not None: _ti_core.warn( f'ti.init argument "default_fp" overridden by environment variable TI_DEFAULT_FP={env_default_fp}' ) if env_default_fp == '32': default_fp = ti.f32 elif env_default_fp == '64': default_fp = ti.f64 elif env_default_fp is not None: raise ValueError( f'Invalid TI_DEFAULT_FP={env_default_fp}, should be 32 or 64') env_default_ip = os.environ.get("TI_DEFAULT_IP") if env_default_ip: if default_ip is not None: _ti_core.warn( f'ti.init argument "default_ip" overridden by environment variable TI_DEFAULT_IP={env_default_ip}' ) if env_default_ip == '32': default_ip = ti.i32 elif env_default_ip == '64': default_ip = ti.i64 elif env_default_ip is not None: raise ValueError( f'Invalid TI_DEFAULT_IP={env_default_ip}, should be 32 or 64') if default_fp is not None: impl.get_runtime().set_default_fp(default_fp) if default_ip is not None: impl.get_runtime().set_default_ip(default_ip) # submodule configurations (spec_cfg): env_spec.add('print_preprocessed') env_spec.add('log_level', str) env_spec.add('gdb_trigger') env_spec.add('excepthook') env_spec.add('experimental_real_function') # compiler configurations (ti.cfg): for key in dir(ti.cfg): if key in ['arch', 'default_fp', 'default_ip']: continue _cast = type(getattr(ti.cfg, key)) if _cast is bool: _cast = None env_comp.add(key, _cast) unexpected_keys = kwargs.keys() if 'use_unified_memory' in unexpected_keys: _ti_core.warn( f'"use_unified_memory" is a deprecated option, as taichi no longer have the option of using unified memory.' ) del kwargs['use_unified_memory'] if len(unexpected_keys): raise KeyError( f'Unrecognized keyword argument(s) for ti.init: {", ".join(unexpected_keys)}' ) # dispatch configurations that are not in ti.cfg: if not _test_mode: ti.set_gdb_trigger(spec_cfg.gdb_trigger) impl.get_runtime().print_preprocessed = spec_cfg.print_preprocessed impl.get_runtime().experimental_real_function = \ spec_cfg.experimental_real_function ti.set_logging_level(spec_cfg.log_level.lower()) if spec_cfg.excepthook: # TODO(#1405): add a way to restore old excepthook ti.enable_excepthook() # select arch (backend): env_arch = os.environ.get('TI_ARCH') if env_arch is not None: ti.info(f'Following TI_ARCH setting up for arch={env_arch}') arch = _ti_core.arch_from_name(env_arch) ti.cfg.arch = adaptive_arch_select(arch, enable_fallback) if ti.cfg.arch == cc: _ti_core.set_tmp_dir(locale_encode(prepare_sandbox())) print(f'[Taichi] Starting on arch={_ti_core.arch_name(ti.cfg.arch)}') # Torch based ndarray on opengl backend allocates memory on host instead of opengl backend. # So it won't work. if ti.cfg.arch == opengl and ti.cfg.ndarray_use_torch: ti.warn( f'Opengl backend doesn\'t support torch based ndarray. Setting ndarray_use_torch to False.' ) ti.cfg.ndarray_use_torch = False if _test_mode: return spec_cfg get_default_kernel_profiler().set_kernel_profiler_mode( ti.cfg.kernel_profiler) # create a new program: impl.get_runtime().create_program() ti.trace('Materializing runtime...') impl.get_runtime().prog.materialize_runtime() impl._root_fb = FieldsBuilder() return None