def tear_down(self, old_dir, exp_dir): isdirectory_good = U.check_provided_directory(exp_dir) if isdirectory_good: try: U.change_cwd(old_dir) except Exception as e: L.get_logger().log(str(e), level='error')
def main(argv): # create the getopt table + read and validate the options given to the script tools_json_dir_path = parse_input(argv) # read the content of the DATS.json files present in the boutiques's cached # directory present in ~ tool_descriptor_list = Utility.read_boutiques_cached_dir(tools_json_dir_path) # digest the content of the DATS.json files into a summary of variables of interest tools_summary_dict = {} i = 0 for tool in tool_descriptor_list: tools_summary_dict[i] = parse_json_information(tool) i += 1 # create the summary statistics of the variables of interest organized per # domain of application csv_content = [ [ 'Domain of Application', 'Number Of Tools', 'Containers', 'Execution Capacity' ] ] for field in ['Neuroinformatics', 'Bioinformatics', 'MRI', 'EEG', 'Connectome', 'BIDS-App']: summary_list = get_stats_per_domain(tools_summary_dict, field) csv_content.append(summary_list) # write the summary statistics into a CSV file Utility.write_csv_file('tools_summary_statistics_per_domain', csv_content)
def check_paths(self, conf): error_message = "Error in configuration-file:\n\n" exception_occured = False for build_dir in conf.directories: if not (util.check_provided_directory(build_dir)): error_message += "Build-directory " + build_dir + " does not exist.\n\n" exception_occured = True for item in conf.builds[build_dir][_ITEMS]: for inst_ana in conf.items[build_dir][item][ "instrument_analysis"]: if not (util.check_provided_directory(inst_ana)): error_message += "Instrument-analysis directory " + inst_ana + " does not exist.\n" exception_occured = True if not (util.check_provided_directory( conf.items[build_dir][item]["builders"])): error_message += "Builders-directory " + conf.items[ build_dir][item]["builders"] + " does not exist.\n" exception_occured = True for arg in conf.items[build_dir][item]["args"]: if not (util.check_provided_directory(arg)): error_message += "args" + arg + "does not exist.\n" exception_occured = True if not (util.check_provided_directory( conf.items[build_dir][item]["runner"])): error_message += "runner" + conf.items[build_dir][ item]["runner"] + "does not exist.\n" exception_occured = True if exception_occured: raise PiraConfigurationErrorException(error_message)
def create_tempfiles(self): for directory in directories_to_create: U.make_dirs(tempdir + directory) for filepath in functor_files: tempfile = open(tempdir + filepath,'a') tempfile.close()
def main(argv): # create the getopt table + read and validate the options given to the script conp_dataset_dir = parse_input(argv) # read the content of the DATS.json files present in the conp-dataset directory dataset_descriptor_list = Utility.read_conp_dataset_dir(conp_dataset_dir) # digest the content of the DATS.json files into a summary of variables of interest datasets_summary_dict = {} i = 0 for dataset in dataset_descriptor_list: datasets_summary_dict[i] = parse_dats_information(dataset) i += 1 # create the summary statistics of the variables of interest organized per data providers csv_content = [[ 'Data Provider', 'Number Of Datasets', 'Number Of Datasets Requiring Authentication', 'Total Number Of Files', 'Total Size (GB)', 'Keywords Describing The Data' ]] for data_provider in ['braincode', 'frdr', 'loris', 'osf', 'zenodo']: summary_list = get_stats_for_data_provider(datasets_summary_dict, data_provider) csv_content.append(summary_list) # write the summary statistics into a CSV file Utility.write_csv_file('dataset_summary_statistics_per_data_providers', csv_content)
def parse_from_json(self, json_tree) -> None: # Top-level key elements // theoretically not required try: directories = U.json_to_canonic(json_tree[_DIRS]) except Exception as e: L.get_logger().log( 'SimplifiedConfigurationLoader::parse_from_json: ' + str(e)) directories = {} for tld_build in json_tree[_BUILDS]: # These are the elements, i.e., %astar and alike directory_for_item = U.json_to_canonic(tld_build) if self.is_escaped(directory_for_item): directory_for_item = directories[directory_for_item[1:]] item_tree = U.json_to_canonic( json_tree[_BUILDS][tld_build][_ITEMS]) for item_key in item_tree: L.get_logger().log( 'SimplifiedConfigurationLoader::parse_from_json: ' + str(item_key)) pira_item = self.create_item_from_json(item_key, item_tree) self._config.add_item(directory_for_item, pira_item) self._config._empty = False
def prep_db_for_build_item_in_flavor(self, config, build, item, flavor): """Generates all the necessary build work to write to the db. :config: PIRA configuration :build: the build :item: current item :flavor: current flavor :returns: unique ID for current item """ build_tuple = (u.generate_random_string(), build, '', flavor, build) self.insert_data_builds(build_tuple) # XXX My implementation returns the full path, including the file extension. # In case something in the database goes wild, this could be it. func_manager = fm.FunctorManager() analyse_functor = func_manager.get_analyzer_file(build, item, flavor) build_functor = func_manager.get_builder_file(build, item, flavor) run_functor = func_manager.get_runner_file(build, item, flavor) # TODO implement the get_submitter_file(build, item, flavor) method! benchmark_name = config.get_benchmark_name(item) submitter_functor = config.get_runner_func(build, item) + '/slurm_submitter_' + benchmark_name + flavor exp_dir = config.get_analyser_exp_dir(build, item) db_item_id = u.generate_random_string() db_item_data = (db_item_id, benchmark_name, analyse_functor, build_functor, '', run_functor, submitter_functor, exp_dir, build) self.insert_data_items(db_item_data) return db_item_id
def _set_up(self, build, item, flavor, it_nr, is_instr_run) -> None: L.get_logger().log('ScorepSystemHelper::_set_up: is_instr_run: ' + str(is_instr_run), level='debug') if not is_instr_run: return exp_dir = self.config.get_analyzer_exp_dir(build, item) L.get_logger().log( 'ScorepSystemHelper::_set_up: Retrieved analyzer experiment directory: ' + exp_dir, level='debug') effective_dir = U.get_cube_file_path(exp_dir, flavor, it_nr) if not U.check_provided_directory(effective_dir): L.get_logger().log( 'ScorepSystemHelper::_set_up: Experiment directory does not exist. \nCreating path: ' + effective_dir, level='debug') U.create_directory(effective_dir) db_exp_dir = U.build_cube_file_path_for_db(exp_dir, flavor, it_nr) self.data['cube_dir'] = db_exp_dir self.set_exp_dir(exp_dir, flavor, it_nr) self.set_memory_size('500M') self.set_overwrite_exp_dir() self.set_profiling_basename(flavor, build, item)
def get_parameter(self, item_tree, item_key): run_opts = {} run_opts['mapper'] = U.json_to_canonic( item_tree[item_key]['argmap']['mapper']) params = {} param_tree = item_tree[item_key]['argmap'] file_mapper = False if 'pira-file' in param_tree: run_opts['pira-file'] = [] run_opts['pira-file'] = U.json_to_canonic( param_tree['pira-file']['names']) param_tree = param_tree['pira-file'] file_mapper = True for param in param_tree: parameter = U.json_to_canonic(param) if param == 'mapper': continue if file_mapper and param == 'names': continue try: params[parameter] except: params[parameter] = [] params[parameter] = U.json_to_canonic(param_tree[param]) run_opts['argmap'] = params return run_opts
def set_up(self) -> None: L.get_logger().log('Builder::set_up for ' + self.directory) directory_good = U.check_provided_directory(self.directory) if directory_good: self.old_cwd = U.get_cwd() U.change_cwd(self.directory) else: self.error = True raise Exception('Builder::set_up: Could not change to directory')
def set_filter_file(self, file_name: str) -> None: L.get_logger().log( 'ScorepMeasurementSystem::set_filter_file: File for runtime filtering = ' + file_name) if not U.is_valid_file_name(file_name): raise MeasurementSystemException('Score-P filter file not valid.') self.cur_filter_file = file_name U.set_env('SCOREP_FILTERING_FILE', self.cur_filter_file)
def set_exp_dir(self, exp_dir: str, flavor: str, iterationNumber: int) -> None: effective_dir = U.get_cube_file_path(exp_dir, flavor, iterationNumber) if not U.is_valid_file_name(effective_dir): raise MeasurementSystemException( 'Score-p experiment directory invalid.') self.cur_exp_directory = effective_dir U.set_env('SCOREP_EXPERIMENT_DIRECTORY', self.cur_exp_directory) return
def test_concat_a_b_with_sep(self): a = 'a' b = 'b' sep = '_' r = u.concat_a_b_with_sep(a, b, sep) self.assertEqual(r, 'a_b') a = 'aaaa' b = '' r = u.concat_a_b_with_sep(a, b, sep) self.assertEqual(r, 'aaaa_')
def execute_with_config(runner: Runner, analyzer: A, pira_iters: int, target_config: TargetConfiguration) -> None: try: log.get_logger().log('run_setup phase.', level='debug') instrument = False pira_iterations = pira_iters # Build without any instrumentation vanilla_builder = B(target_config, instrument) tracker = tt.TimeTracker() tracker.m_track('Vanilla Build', vanilla_builder, 'build') # Run without instrumentation for baseline log.get_logger().log('Running baseline measurements', level='info') vanilla_rr = runner.do_baseline_run(target_config) log.get_logger().log( 'Pira::execute_with_config: RunResult: ' + str(vanilla_rr) + ' | avg: ' + str(vanilla_rr.get_average()), level='debug') instr_file = '' for x in range(0, pira_iterations): log.get_logger().log('Running instrumentation iteration ' + str(x), level='info') # Only run the pgoe to get the functions name iteration_tracker = tt.TimeTracker() # Analysis Phase instr_file = analyzer.analyze(target_config, x) log.get_logger().log('[WHITELIST] $' + str(x) + '$ ' + str(util.lines_in_file(instr_file)), level='perf') util.shell('stat ' + instr_file) # After baseline measurement is complete, do the instrumented build/run # This is only necessary in every iteration when run in compile-time mode. if x is 0 or target_config.is_compile_time_filtering(): instrument = True instr_builder = B(target_config, instrument, instr_file) tracker.m_track('Instrument Build', instr_builder, 'build') #Run Phase log.get_logger().log('Running profiling measurements', level='info') instr_rr = runner.do_profile_run(target_config, x) # Compute overhead of instrumentation ovh_percentage = instr_rr.compute_overhead(vanilla_rr) log.get_logger().log('[RUNTIME] $' + str(x) + '$ ' + str(instr_rr.get_average()), level='perf') log.get_logger().log('[OVERHEAD] $' + str(x) + '$ ' + str(ovh_percentage), level='perf') iteration_tracker.stop() user_time, system_time = iteration_tracker.get_time() log.get_logger().log('[ITERTIME] $' + str(x) + '$ ' + str(user_time) + ', ' + str(system_time), level='perf') except Exception as e: log.get_logger().log( 'Pira::execute_with_config: Problem during preparation of run.\nMessage:\n' + str(e), level='error') raise RuntimeError(str(e))
def test_concat_a_b_with_sep_empty(self): a = 'a' b = '' sep = '' r = u.concat_a_b_with_sep(a, b, sep) self.assertEqual(r, 'a') b = 'a' a = '' r = u.concat_a_b_with_sep(a, b, sep) self.assertEqual(r, 'a')
def send_mail(html='', attachments=None): smtp_server_host = 'smtp.qq.com' smtp_server_ssl_port = 465 my_email = '*****@*****.**' # 发件人邮箱账号 my_password = '******' # 发件人邮箱密码或授权码 to_email = ['*****@*****.**', '*****@*****.**', '*****@*****.**'] # 构造一个MIMEMultipart对象代表邮件本身 msg = MIMEMultipart() # Header对中文进行转码 msg['From'] = format_addr('App-Store-Review-Guidelines 差异监控 <%s>' % my_email).encode() msg['To'] = ','.join(to_email) msg['Subject'] = Header('App-Store-Review-Guidelines 差异监控', 'utf-8').encode() # 添加邮件正文 msg.attach(MIMEText(html, 'html', 'utf-8')) # 添加附件就是加上一个MIMEBase if isinstance(attachments, list): for attachment in attachments: if os.path.isfile(attachment): # file_extension = os.path.splitext(attachment)[1] mime_type = mimetypes.guess_type(attachment)[0] major_type = mime_type.split('/')[0] sub_type = mime_type.split('/')[1] with open(attachment, 'rb') as f: # 设置附件的MIME和文件名,这里是png类型: mime = MIMEBase(major_type, sub_type, filename=attachment) # 加上必要的头信息: mime.add_header('Content-Disposition', 'attachment', filename=attachment) mime.add_header('Content-ID', '<0>') mime.add_header('X-Attachment-Id', '0') # 把附件的内容读进来: mime.set_payload(f.read()) # 用Base64编码: encoders.encode_base64(mime) # 添加到MIMEMultipart: msg.attach(mime) Utility.log('成功添加附件:', attachment) try: server = smtplib.SMTP_SSL(smtp_server_host, smtp_server_ssl_port) server.set_debuglevel(1) # 开启调试信息 server.login(my_email, my_password) # 括号中对应的是发件人邮箱账号、授权码 server.sendmail(my_email, to_email, msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件 server.quit() # 关闭连接 except smtplib.SMTPException as e: return "Error: %s" % e return True
def prepare_scorep_filter_file(self, filter_file: str) -> None: ''' Prepares the file that Score-P uses to include or exclude. NOTE: The filter_file is a positive list! We want to include these functions! ''' file_dir = U.get_base_dir(filter_file) file_content = U.read_file(filter_file) scorep_filter_file_content = self.append_scorep_footer( self.prepend_scorep_header(file_content)) scorep_filter_file_name = file_dir + '/scorep_filter_file.txt' U.write_file(scorep_filter_file_name, scorep_filter_file_content) return scorep_filter_file_name
def build_flavors(self, kwargs) -> None: L.get_logger().log( 'Builder::build_flavors: Building for ' + self.target_config.get_target() + ' in ' + self.target_config.get_flavor(), level='debug') build = self.target_config.get_build() benchmark = self.target_config.get_target() flavor = self.target_config.get_flavor() f_man = F.FunctorManager() # Returns the currently loaded FM clean_functor = f_man.get_or_load_functor(build, benchmark, flavor, 'clean') kwargs = {} if self.build_instr: L.get_logger().log('Builder::build_flavors: Instrumentation', level='debug') try: self.check_build_prerequisites() L.get_logger().log('Builder::build_flavors: Prerequisite check successfull.') except Exception as e: raise BuilderException('Precheck failed.\n' + str(e)) if not self.target_config.is_compile_time_filtering(): L.get_logger().log('Builder::build_flavors: Runtime filtering enabled.') self.target_config.set_instr_file(self.instrumentation_file) build_functor = f_man.get_or_load_functor(build, benchmark, flavor, 'build') kwargs = self.construct_pira_instr_kwargs() ScorepSystemHelper.prepare_MPI_filtering(self.instrumentation_file) else: L.get_logger().log('Builder::build_flavors: No instrumentation', level='debug') build_functor = f_man.get_or_load_functor(build, benchmark, flavor, 'basebuild') kwargs = self.construct_pira_kwargs() if build_functor.get_method()['active']: L.get_logger().log('Builder::build_flavors: Running the passive functor.', level='debug') build_functor.active(benchmark, **kwargs) else: try: L.get_logger().log('Builder::build_flavors: Running the passive functor.', level='debug') ''' The build command uses CC and CXX to pass flags that are needed by PIRA for the given toolchain. ''' build_command = build_functor.passive(benchmark, **kwargs) clean_command = clean_functor.passive(benchmark, **kwargs) L.get_logger().log( 'Builder::build_flavors: Clean in ' + benchmark + '\n Using ' + clean_command, level='debug') U.shell(clean_command) L.get_logger().log('Builder::build_flavors: Building: ' + build_command, level='debug') U.shell(build_command) except Exception as e: L.get_logger().log('Builder::build_flavors: ' + str(e), level='error')
def check_and_prepare(self, experiment_dir: str, target_config: TargetConfiguration, instr_config: InstrumentConfig) -> str: cur_ep_dir = self.get_extrap_dir_name( target_config, instr_config.get_instrumentation_iteration()) if not u.is_valid_file_name(cur_ep_dir): log.get_logger().log( 'ExtrapProfileSink::check_and_prepare: Generated directory name no good. Abort\n' + cur_ep_dir, level='error') else: if u.check_provided_directory(cur_ep_dir): new_dir_name = cur_ep_dir + '_' + u.generate_random_string() log.get_logger().log( 'ExtrapProfileSink::check_and_prepare: Moving old experiment directory to: ' + new_dir_name, level='info') u.rename(cur_ep_dir, new_dir_name) u.create_directory(cur_ep_dir) cubex_name = experiment_dir + '/' + target_config.get_flavor( ) + '-' + target_config.get_target() + '.cubex' log.get_logger().log(cubex_name) if not u.is_file(cubex_name): log.get_logger().log( 'ExtrapProfileSink::check_and_prepare: Returned experiment cube name is no file: ' + cubex_name) else: return cubex_name raise ProfileSinkException( 'ExtrapProfileSink: Could not create target directory or Cube dir bad.' )
def get_place(self, build): place = build for k in self._directories.keys(): if place == k: if not U.is_absolute_path(k): place = self._abs_base_path + '/' + str(k) return place
def create_item_from_json(self, item_key: str, item_tree): pira_item = PiraItem(item_key) analyzer_dir = item_tree[item_key]['analyzer'] if analyzer_dir is '': analyzer_dir = U.get_base_dir( __file__) + '/../extern/install/pgis/bin' L.get_logger().log('Analyzer: using analyzer default: ' + analyzer_dir, level='debug') cubes_dir = item_tree[item_key]['cubes'] flavors = item_tree[item_key]['flavors'] functors_base_path = item_tree[item_key]['functors'] mode = item_tree[item_key]['mode'] run_opts = self.get_parameter(item_tree, item_key) run_options = ArgumentMapperFactory.get_mapper(run_opts) pira_item.set_analyzer_dir(analyzer_dir) pira_item.set_cubes_dir(cubes_dir) pira_item.set_flavors(flavors) pira_item.set_functors_base_path(functors_base_path) pira_item.set_mode(mode) pira_item.set_run_options(run_options) return pira_item
def test_shell_invoc(self): command = 'echo "Hello World!"' expected_out = 'Hello World!\n' out, t = u.shell(command, time_invoc=False) self.assertEqual(out, expected_out) self.assertEqual(t, -1.0) # XXX This is already a little fishy!
def get_or_load_functor(self, build: str, item: str, flavor: str, func: str): ''' We use the wholename, i.e. fully qualified path to the functor, as the key in our functor cache. ''' if func is 'basebuild': path, name, wnm = self.get_builder(build, item, flavor, True) elif func is 'build': path, name, wnm = self.get_builder(build, item, flavor) elif func is 'clean': path, name, wnm = self.get_cleaner(build, item, flavor) elif func is 'analyze': path, name, wnm = self.get_analyzer(build, item, flavor) elif func is 'run': path, name, wnm = self.get_runner(build, item, flavor) else: raise Exception( 'No such option available to load functor for. Value = ' + func) try: _ = self.functor_cache[name] except KeyError: self.functor_cache[name] = U.load_functor(path, name) L.get_logger().log('FunctorManager::get_or_load: The retrieved ' + func + ' functor: ' + str(self.functor_cache[name]), level='debug') return self.functor_cache[name]
def check_paths(self, config): error_message = "Error in configuration-file:\n\n" exception_occured = False for dir in config.get_directories(): if not (util.check_provided_directory(dir)): error_message += "Directory " + dir + " does not exist.\n" exception_occured = True for item in config.get_items(dir): if not (util.check_provided_directory( item.get_analyzer_dir())): error_message += "Analyzer-Directory " + item.get_analyzer_dir( ) + " does not exist\n" exception_occured = True if not (util.check_provided_directory( item.get_analyzer_dir())): error_message += "Cubes-Directory " + item.get_cubes_dir( ) + " does not exist\n" exception_occured = True if not (util.check_provided_directory( item.get_functor_base_path())): error_message += "Functors-Base-Directory " + item.get_functor_base_path( ) + " does not exist\n" exception_occured = True for flavor in item.get_flavors(): if not (util.is_file(item.get_functor_base_path() + "/analyse_" + item._name + "_" + flavor + ".py")): error_message += "analyse-functor of flavor " + flavor + " does not exist.\n" exception_occured = True if not (util.is_file(item.get_functor_base_path() + "/clean_" + item._name + "_" + flavor + ".py")): error_message += "clean-functor of flavor " + flavor + " does not exist.\n" exception_occured = True if not (util.is_file(item.get_functor_base_path() + "/no_instr_" + item._name + "_" + flavor + ".py")): error_message += "no_instr-functor of flavor " + flavor + " does not exist.\n" exception_occured = True if not (util.is_file(item.get_functor_base_path() + "/runner_" + item._name + "_" + flavor + ".py")): error_message += "runner-functor of flavor " + flavor + " does not exist.\n" exception_occured = True if not (util.is_file(item.get_functor_base_path() + "/" + item._name + "_" + flavor + ".py")): error_message += "plain-functor of flavor " + flavor + " does not exist.\n" exception_occured = True if exception_occured: raise PiraConfigurationErrorException(error_message)
def run(self, target_config: TargetConfiguration, instrument_config: InstrumentConfig, compile_time_filtering: bool) -> float: """ Implements the actual invocation """ functor_manager = fm.FunctorManager() run_functor = functor_manager.get_or_load_functor( target_config.get_build(), target_config.get_target(), target_config.get_flavor(), 'run') default_provider = defaults.BackendDefaults() kwargs = default_provider.get_default_kwargs() kwargs['util'] = util kwargs['LD_PRELOAD'] = default_provider.get_MPI_wrap_LD_PRELOAD() runtime = .0 if run_functor.get_method()['active']: run_functor.active(target_config.get_target(), **kwargs) log.get_logger().log( 'For the active functor we can barely measure runtime', level='warn') runtime = 1.0 try: util.change_cwd(target_config.get_place()) invoke_arguments = target_config.get_args_for_invocation() kwargs['args'] = invoke_arguments if invoke_arguments is not None: log.get_logger().log('LocalBaseRunner::run: (args) ' + str(invoke_arguments)) command = run_functor.passive(target_config.get_target(), **kwargs) _, runtime = util.shell(command, time_invoc=True) log.get_logger().log( 'LocalBaseRunner::run::passive_invocation -> Returned runtime: ' + str(runtime), level='debug') except Exception as e: log.get_logger().log('LocalBaseRunner::run Exception\n' + str(e), level='error') raise RuntimeError('LocalBaseRunner::run caught exception. ' + str(e)) # TODO: Insert the data into the database return runtime
def test_shell_dry_run(self): command = 'echo "Hello world!"' expected_out = '[debug] Utility::shell: DRY RUN SHELL CALL: ' + command out, t = u.shell(command, dry=True) lm = log.get_logger().get_last_msg() self.assertEqual(lm, expected_out) self.assertEqual(t, 1.0) self.assertEqual(out, '')
def get_builder(self, build: str, item: str, flavor: str, base: bool = False) -> typing.Tuple[str, str, str]: p = self.config.get_builder_path(build, item) n = self.get_builder_name(build, item, flavor) if base: n = U.concat_a_b_with_sep('no_instr', n, '_') wnm = self.get_builder_file(build, item, flavor) return p, n, wnm
def check_build_prerequisites(cls) -> None: scorep_init_file_name = 'scorep.init.c' L.get_logger().log( 'ScorepMeasurementSystem::check_build_prerequisites: global home dir: ' + U.get_home_dir()) pira_scorep_resource = U.get_home_dir() + '/resources/scorep.init.c' if not U.is_file(scorep_init_file_name): U.copy_file(pira_scorep_resource, U.get_cwd() + '/' + scorep_init_file_name) # In case something goes wrong with copying if U.is_file(scorep_init_file_name): U.shell('gcc -c ' + scorep_init_file_name) else: raise MeasurementSystemException( 'ScorepMeasurementSystem::check_build_prerequisites: Missing ' + scorep_init_file_name)
def load_conf(self, config_file: str) -> PiraConfiguration: if not U.is_file(config_file): raise RuntimeError( 'SimplifiedConfigurationLoader::load_conf: Invalid config file location "' + config_file + '" [no such file].') config_abs = U.get_absolute_path(config_file) config_abs_path = config_abs[:config_abs.rfind('/')] self._config.set_absolute_base_path(config_abs_path) try: file_content = U.read_file(config_file) json_tree = json.loads(file_content) self.parse_from_json(json_tree) except Exception as e: L.get_logger().log( 'SimplifiedConfigurationLoader::load_conf: Caught exception "' + str(e)) return PiraConfigurationAdapter(self._config)
def output_config(self, benchmark, output_dir): L.get_logger().log('ExtrapProfileSink::output_config:\ndir: ' + self._base_dir + '\nprefix: ' + self._prefix + '\npostfix: ' + self._postfix + '\nreps: ' + str(self._total_reps) + '\nNiter: ' + str(self._iteration + 1)) s = '' for p in self._params: s += p + ', ' L.get_logger().log('params: ' + s) json_str = json.dumps({ 'dir': self._base_dir, 'prefix': self._prefix, 'postfix': self._postfix, 'reps': int(self._total_reps), 'iter': int(self._iteration + 1), 'params': self._params }) out_file_final = output_dir + '/pgis_cfg_' + benchmark + '.json' U.write_file(out_file_final, json_str) return out_file_final