Skip to content

Commit

Permalink
Merge pull request #430 from therault/ttg/termdet-dynamic-PTG
Browse files Browse the repository at this point in the history
Ttg/termdet dynamic PTG
  • Loading branch information
bosilca authored Oct 12, 2022
2 parents 1f0d392 + 4cea117 commit 4ba2aa0
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 197 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ option(PARSEC_WANT_HOME_CONFIG_FILES
"Should the runtime check for the parameter configuration file in the user home (\$HOME/.parsec/mca-params.conf)" ON)

### PaRSEC PP options
set(PARSEC_PTGFLAGS "--noline" CACHE STRING "Additional parsec-ptgpp precompiling flags (separate flags with ';')" )
mark_as_advanced(PARSEC_PTGFLAGS)
set(PARSEC_PTGPP_FLAGS "--noline" CACHE STRING "Additional parsec-ptgpp precompiling flags (separate flags with ';')" )
mark_as_advanced(PARSEC_PTGPP_FLAGS)

option(PARSEC_WITH_DEVEL_HEADERS "Install additional headers in include/parsec allowing external compilation." ON)

Expand Down
2 changes: 1 addition & 1 deletion cmake_modules/PaRSECConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,6 @@ endif(NOT TARGET PaRSEC::parsec)

# Populate the variables

set(PARSEC_PTGFLAGS "$ENV{PTGFLAGS}" CACHE STRING "Flags to pass to the parsec-ptgpp executable")
set(PARSEC_PTGPP_FLAGS "$ENV{PTGPPFLAGS}" CACHE STRING "Flags to pass to the parsec-ptgpp executable")
set(PARSEC_PTGPP_EXECUTABLE ${PARSEC_BINARY_DIRS}/parsec-ptgpp CACHE STRING "Point to the parsec-ptgpp executable")
set(PARSEC_LIBRARIES PaRSEC::parsec CACHE STRING "List of libraries suitable for use in target_link_libraries") # for compatibility with older (non-target based) clients
11 changes: 9 additions & 2 deletions cmake_modules/ParsecCompilePTG.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ function(target_ptg_source_ex)
set(target "${PARSEC_PTGPP_TARGET}")

set(_ptgpp_flags "")
if(DEFINED PARSEC_PTGPP_PTGPP_FLAGS)
if(DEFINED PARSEC_PTGPP_FLAGS) #Those are the global flags set at the top level CMakeLists.txt
list(APPEND _ptgpp_flags ${PARSEC_PTGPP_FLAGS})
endif()

if(DEFINED PARSEC_PTGPP_PTGPP_FLAGS) #Those are optional flags passed to this function
list(APPEND _ptgpp_flags ${PARSEC_PTGPP_PTGPP_FLAGS})
endif()

Expand Down Expand Up @@ -53,7 +57,7 @@ function(target_ptg_source_ex)
endif()

get_property(compile_options SOURCE ${PARSEC_PTGPP_SOURCE} PROPERTY PTGPP_COMPILE_OPTIONS)
list(APPEND _ptgpp_flags "${compile_options}")
list(APPEND _ptgpp_flags "${compile_options}") #In case the user has set compile options specific to this source

if(PARSEC_PTGPP_DEBUG)
list(APPEND _ptgpp_flags "--debug")
Expand All @@ -64,6 +68,9 @@ function(target_ptg_source_ex)
if(PARSEC_PTGPP_FORCE_PROFILE)
list(APPEND _ptgpp_flags "--force-profile")
endif()
if(PARSEC_PTGPP_DYNAMIC_TERMDET)
list(APPEND -ptgpp_flags "--dynmic-termdet")
endif()

if(DEFINED PARSEC_PTGPP_DEP_MANAGEMENT)
list(APPEND _ptgpp_flags "--dep-management;${PARSEC_PTGPP_DEP_MANAGEMENT}")
Expand Down
2 changes: 1 addition & 1 deletion parsec/interfaces/ptg/ptg-compiler/jdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1662,7 +1662,7 @@ const char*jdf_property_get_string( const jdf_def_list_t* properties,
jdf_expr_t* expr = jdf_find_property(properties, prop_name, &property);

if( NULL != expr ) {
if( JDF_OP_IS_VAR(expr->op) )
if( JDF_OP_IS_VAR(expr->op) || JDF_OP_IS_STRING(expr->op) )
return expr->jdf_var;
printf("Warning: property %s defined at line %d only support ON/OFF\n",
prop_name, JDF_OBJECT_LINENO(property));
Expand Down
11 changes: 11 additions & 0 deletions parsec/interfaces/ptg/ptg-compiler/jdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ int jdf_sanity_checks( jdf_warning_mask_t mask );
#define DEP_MANAGEMENT_INDEX_ARRAY_STRING "index-array"
#define DEP_MANAGEMENT_INDEX_ARRAY 2

#define TERMDET_DEFAULT 0
#define TERMDET_DYNAMIC 1

#define DISABLE_DEP_WARNING_PROPERTY_NAME "warning"

typedef struct jdf_compiler_global_args {
Expand All @@ -104,6 +107,7 @@ typedef struct jdf_compiler_global_args {
int dep_management;
int noline; /**< Don't dump the jdf line number in the generate .c file */
struct jdf_name_list *ignore_properties; /**< Properties to ignore */
int termdet; /**< What termination detection to use (one of TERMDET_*) */
} jdf_compiler_global_args_t;
extern jdf_compiler_global_args_t JDF_COMPILER_GLOBAL_ARGS;

Expand Down Expand Up @@ -207,6 +211,13 @@ typedef unsigned int jdf_flags_t;

#define JDF_PROP_NO_AUTOMATIC_TASKPOOL_INSTANCE "no_taskpool_instance"

#define JDF_PROP_TERMDET_NAME "termdet"
#define JDF_HAS_USER_TRIGGERED_TERMDET ((jdf_flags_t)(1 << 5))
#define JDF_HAS_DYNAMIC_TERMDET ((jdf_flags_t)(1 << 6))
#define JDF_PROP_TERMDET_LOCAL "local"
#define JDF_PROP_TERMDET_DYNAMIC "dynamic"
#define JDF_PROP_TERMDET_USER_TRIGGERED "user-triggered"

typedef struct jdf_function_entry {
struct jdf_object_t super;
struct jdf_function_entry *next;
Expand Down
135 changes: 93 additions & 42 deletions parsec/interfaces/ptg/ptg-compiler/jdf2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ static void var_to_c_code(jdf_expr_t* expr)
expr->jdf_c_code.function_context = NULL;
}

static int jdf_uses_dynamic_termdet( const jdf_t *jdf )
{
const char *pname = jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_NAME, NULL);
if(NULL == pname) return 0;
return strcmp(pname, JDF_PROP_TERMDET_DYNAMIC) == 0;
}

/**
* Generate a semi-persistent string (kept in a circular buffer that will be reused after
Expand Down Expand Up @@ -3166,16 +3172,20 @@ static void jdf_generate_startup_tasks(const jdf_t *jdf, const jdf_function_entr
coutput("%s restore_context = 0;\n"
"%s (void)restore_context;\n"
"%s if( nb_tasks > this_task->locals.reserved[0].value ) {\n"
"%s if( (size_t)this_task->locals.reserved[0].value < parsec_task_startup_iter ) this_task->locals.reserved[0].value <<= 1;\n"
"%s __parsec_schedule_vp(es, (parsec_task_t**)pready_ring, 0);\n"
"%s if( (size_t)this_task->locals.reserved[0].value < parsec_task_startup_iter ) this_task->locals.reserved[0].value <<= 1;\n",
indent(nesting), indent(nesting), indent(nesting), indent(nesting));
if(jdf_uses_dynamic_termdet(jdf)) {
coutput("%s __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, nb_tasks);\n",
indent(nesting));
}
coutput("%s __parsec_schedule_vp(es, (parsec_task_t**)pready_ring, 0);\n"
"%s total_nb_tasks += nb_tasks;\n"
"%s nb_tasks = 0;\n"
"%s if( total_nb_tasks > parsec_task_startup_chunk ) { /* stop here and request to be rescheduled */\n"
"%s return PARSEC_HOOK_RETURN_AGAIN;\n"
"%s }\n"
"%s }\n",
indent(nesting), indent(nesting), indent(nesting), indent(nesting),
indent(nesting), indent(nesting), indent(nesting), indent(nesting),
indent(nesting), indent(nesting), indent(nesting));

/* We close all variables, in reverse order to manage the local indices */
Expand All @@ -3202,8 +3212,11 @@ static void jdf_generate_startup_tasks(const jdf_t *jdf, const jdf_function_entr
string_arena_free(sa_properties);

coutput(" (void)vpid;\n"
" if( 0 != nb_tasks ) {\n"
" __parsec_schedule_vp(es, (parsec_task_t**)pready_ring, 0);\n"
" if( 0 != nb_tasks ) {\n");
if(jdf_uses_dynamic_termdet(jdf)) {
coutput(" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, nb_tasks);\n");
}
coutput(" __parsec_schedule_vp(es, (parsec_task_t**)pready_ring, 0);\n"
" nb_tasks = 0;\n"
" }\n"
" return PARSEC_HOOK_RETURN_DONE;\n"
Expand Down Expand Up @@ -3796,16 +3809,29 @@ static void jdf_generate_internal_init(const jdf_t *jdf, const jdf_function_entr
jdf_expr_t *expr;
jdf_def_list_t* property;
if( NULL != (expr = jdf_find_property(jdf->global_properties, JDF_PROP_UD_NB_LOCAL_TASKS_FN_NAME, &property) ) ) {
coutput(" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, %s(__parsec_tp));\n",
expr->jdf_c_code.fname);
if(JDF_C_CODE == expr->op) {
assert(NULL != expr->jdf_c_code.fname);
coutput(" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, %s(__parsec_tp));\n",
expr->jdf_c_code.fname);
} else if(JDF_VAR == expr->op || JDF_STRING == expr->op) {
assert(NULL != expr->jdf_var);
coutput(" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, %s(__parsec_tp));\n",
expr->jdf_var);
} else {
jdf_fatal(JDF_OBJECT_LINENO(expr),
"During code generation: the expression that defines the property '%s' is neither a function, a string nor a variable name (op code: %d).\n"
"Unable to generate user-defined task counting operation in the internal_init of %s\n",
JDF_PROP_UD_NB_LOCAL_TASKS_FN_NAME, expr->op,
f->fname);
}
} else {
assert((f->user_defines & JDF_HAS_USER_TRIGGERED_TERMDET) ||
(NULL != jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_DYNAMIC, NULL)));
(f->user_defines & JDF_HAS_DYNAMIC_TERMDET));
/* The startup tasks are going to count the real number of tasks as they discover them.
* For now, we lock the idleness by creating a runtime pending action, and
* we use sync_point to find when all the startup tasks are done. */
coutput(" __parsec_tp->sync_point = PARSEC_%s_NB_TASK_CLASSES\n;"
" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, 1);\n",
coutput(" __parsec_tp->sync_point = PARSEC_%s_NB_TASK_CLASSES;\n"
" //__parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, 1);\n",
jdf_basename);
}
} else {
Expand Down Expand Up @@ -4236,19 +4262,10 @@ static void jdf_generate_one_function( const jdf_t *jdf, jdf_function_entry_t *f
}
}
string_arena_add_string(sa, " .find_deps = %s,\n", jdf_property_get_function(f->properties, JDF_PROP_UD_FIND_DEPS_FN_NAME, NULL));

if( use_mask ) {
if( NULL == jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_DYNAMIC, NULL)) {
string_arena_add_string(sa, " .update_deps = parsec_update_deps_with_mask,\n");
} else {
string_arena_add_string(sa, " .update_deps = parsec_update_deps_with_mask_count_task,\n");
}
string_arena_add_string(sa, " .update_deps = parsec_update_deps_with_mask,\n");
} else {
if( NULL == jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_DYNAMIC, NULL)) {
string_arena_add_string(sa, " .update_deps = parsec_update_deps_with_counter,\n");
} else {
string_arena_add_string(sa, " .update_deps = parsec_update_deps_with_counter_count_task,\n");
}
string_arena_add_string(sa, " .update_deps = parsec_update_deps_with_counter,\n");
}

if( !(f->flags & JDF_FUNCTION_FLAG_NO_SUCCESSORS) ) {
Expand Down Expand Up @@ -4582,18 +4599,6 @@ static void jdf_generate_constructor( const jdf_t* jdf )
sa1 = string_arena_new(64);
sa2 = string_arena_new(64);

if( NULL != jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_DYNAMIC, NULL)) {
coutput("static parsec_hook_return_t tp_ready_when_synced(struct parsec_execution_stream_s *es, parsec_task_t *task) {\n"
" (void)es;\n"
" __parsec_%s_internal_taskpool_t *__parsec_tp = (__parsec_%s_internal_taskpool_t *)task->taskpool;\n"
" int remaining = parsec_atomic_fetch_dec_int32(&__parsec_tp->sync_point) - 1;\n"
" if( 0 == remaining ) {\n"
" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks(&__parsec_tp->super.super, __parsec_tp->initial_number_tasks-1);\n"
" }\n"
" return PARSEC_HOOK_RETURN_DONE;\n"
"}\n\n", jdf_basename, jdf_basename);
}

coutput("void __parsec_%s_internal_constructor(__parsec_%s_internal_taskpool_t* __parsec_tp)\n{\n"
" parsec_task_class_t* tc;\n"
" uint32_t i, j;\n\n",
Expand Down Expand Up @@ -4660,10 +4665,6 @@ static void jdf_generate_constructor( const jdf_t* jdf )
coutput(" ((__parsec_chore_t*)&tc->incarnations[0])->hook = (parsec_hook_t *)%s;\n",
jdf_property_get_function(f->properties, JDF_PROP_UD_STARTUP_TASKS_FN_NAME, NULL));
}
if( NULL != jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_DYNAMIC, NULL) ) {
coutput(" assert(NULL == tc->complete_execution);\n"
" tc->complete_execution = (parsec_hook_t*)tp_ready_when_synced;\n");
}
}

{
Expand Down Expand Up @@ -4779,7 +4780,7 @@ static void jdf_generate_new_function( const jdf_t* jdf )
" (void)parsec_taskpool_reserve_id((parsec_taskpool_t*)__parsec_tp);\n",
jdf_basename);

if( NULL != jdf_property_get_string(jdf->global_properties, JDF_PROP_TERMDET_DYNAMIC, NULL) ) {
if( jdf_uses_dynamic_termdet(jdf) ) {
coutput(" __parsec_tp->initial_number_tasks = 0;\n");
}

Expand Down Expand Up @@ -7221,11 +7222,21 @@ static void jdf_generate_code_release_deps(const jdf_t *jdf, const jdf_function_
"#endif\n"
"\n");
coutput(" if(action_mask & PARSEC_ACTION_RELEASE_LOCAL_DEPS) {\n"
" data_repo_entry_addto_usage_limit(%s_repo, arg.output_entry->ht_item.key, arg.output_usage);\n"
" __parsec_schedule_vp(es, arg.ready_lists, 0);\n"
" }\n",
" data_repo_entry_addto_usage_limit(%s_repo, arg.output_entry->ht_item.key, arg.output_usage);\n",
f->fname);

if(jdf_uses_dynamic_termdet(jdf)) {
coutput(" {\n"
" /* Using Dynamic Termination Detection, the DSL is reponsible of counting the number of tasks scheduled before scheduling them */\n"
" int __nb_tasks = 0;\n"
" for(__vp_id = 0; __vp_id < es->virtual_process->parsec_context->nb_vp; __vp_id++) {\n"
" if( NULL == arg.ready_lists[__vp_id] ) continue;\n"
" _LIST_ITEM_ITERATOR(arg.ready_lists[__vp_id], &arg.ready_lists[__vp_id]->super, __item, __nb_tasks++);"
" }\n"
" __parsec_tp->super.super.tdm.module->taskpool_addto_nb_tasks((parsec_taskpool_t*)__parsec_tp, __nb_tasks);\n"
" }\n");
}
coutput(" __parsec_schedule_vp(es, arg.ready_lists, 0);\n"
" }\n");
} else {
coutput(" /* No successors, don't call iterate_successors and don't release any local deps */\n");
}
Expand Down Expand Up @@ -8358,6 +8369,46 @@ int jdf_optimize( jdf_t* jdf )
return 0;
}

/** Force the PTG to use a dynamic termination detection **/
int jdf_force_termdet_dynamic(jdf_t* jdf)
{
jdf_def_list_t* property;
jdf_expr_t *termdet_expr;
int rc = 0;

termdet_expr = jdf_find_property(jdf->global_properties, JDF_PROP_TERMDET_NAME, &property);
if( NULL != termdet_expr && strcmp(termdet_expr->jdf_var, JDF_PROP_TERMDET_USER_TRIGGERED) == 0 ) {
return rc; // We don't override a user-trigger termination detection selection
}
if( NULL != termdet_expr && strcmp(termdet_expr->jdf_var, JDF_PROP_TERMDET_DYNAMIC) == 0 ) {
return rc; // The PTG developer already asked for dynamic termination detection
}
if(NULL != termdet_expr) {
if(strcmp(termdet_expr->jdf_var, JDF_PROP_TERMDET_LOCAL) != 0) {
jdf_warn(termdet_expr->super.lineno, "'%s' is not a recognized value for option '%s' -- option overwritten to '%s' because --termdet-dynamic is requested\n",
termdet_expr->jdf_var, JDF_PROP_TERMDET_NAME, JDF_PROP_TERMDET_DYNAMIC);
}
free(termdet_expr->jdf_var);
termdet_expr->jdf_var = strdup(JDF_PROP_TERMDET_DYNAMIC);
return rc;
}

termdet_expr = (jdf_expr_t *)calloc(sizeof(jdf_expr_t), 1);
termdet_expr->op = JDF_STRING;
termdet_expr->local_variables = NULL;
termdet_expr->scope = -1;
termdet_expr->alias = NULL;
termdet_expr->jdf_var = strdup(JDF_PROP_TERMDET_DYNAMIC);

property = (jdf_def_list_t*)calloc(sizeof(jdf_def_list_t), 1);
property->expr = termdet_expr;
property->name = strdup(JDF_PROP_TERMDET_NAME);
property->next = jdf->global_properties;
jdf->global_properties = property;

return rc;
}

/** Main Function */

#if defined(PARSEC_HAVE_INDENT) && !(defined(__WINDOWS__) || defined(__MING64__) || defined(__CYGWIN__))
Expand Down
2 changes: 2 additions & 0 deletions parsec/interfaces/ptg/ptg-compiler/jdf2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

int jdf_optimize( jdf_t* jdf );

int jdf_force_termdet_dynamic(jdf_t* jdf);

int jdf2c(const char *output_c, const char *output_h, const char *_basename, jdf_t *jdf);

#endif /* _jdf2c_h */
26 changes: 23 additions & 3 deletions parsec/interfaces/ptg/ptg-compiler/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static jdf_compiler_global_args_t DEFAULTS = {
.wmask = JDF_ALL_WARNINGS,
.compile = 1, /* by default the file must be compiled */
.dep_management = DEP_MANAGEMENT_DYNAMIC_HASH_TABLE,
.termdet = TERMDET_DEFAULT,
#if defined(PARSEC_HAVE_INDENT) && !defined(PARSEC_HAVE_AWK)
.noline = 1, /*< By default, don't print the #line per default if can't fix the line numbers with awk */
#else
Expand Down Expand Up @@ -67,6 +68,12 @@ static void usage(void)
" are '"DEP_MANAGEMENT_INDEX_ARRAY_STRING"' or '"DEP_MANAGEMENT_DYNAMIC_HASH_TABLE_STRING"'\n"
" (default '%s')\n"
"\n"
" --dynamic-termdet|-D Use dynamic termination detection, even for PTGs that can use\n"
" local (i.e. pre-counted number of tasks) termination detection\n"
" NB. PTGs that are defined to use user-trigger termination\n"
" detection continue to rely on user-trigger termination detection.\n"
" (default: use local termination detection)\n"
"\n"
" --noline Do not dump the JDF line number in the .c output file\n"
" --line Force dumping the JDF line number in the .c output file\n"
" Default: %s\n"
Expand Down Expand Up @@ -187,6 +194,7 @@ static void parse_args(int argc, char *argv[])
{ "dep-management",required_argument, NULL, 'M' },
{ "force-profile", no_argument, NULL, 2 },
{ "ignore-properties", required_argument, NULL, 'I' },
{ "dynamic-termdet", no_argument, NULL, 'D' },
{ NULL, 0, NULL, 0 }
};

Expand All @@ -196,12 +204,15 @@ static void parse_args(int argc, char *argv[])

print_jdf_line = !DEFAULTS.noline;

while( (ch = getopt_long(argc, argv, "di:C:H:o:f:hEsIO:M:I:", longopts, NULL)) != -1) {
while( (ch = getopt_long(argc, argv, "dDi:C:H:o:f:hEsIO:M:I:", longopts, NULL)) != -1) {
switch(ch) {
case 'd':
yydebug = 1;
jdfdebug = 1;
break;
case 'D':
JDF_COMPILER_GLOBAL_ARGS.termdet = TERMDET_DYNAMIC;
break;
case 'i':
if( NULL != JDF_COMPILER_GLOBAL_ARGS.input )
free(JDF_COMPILER_GLOBAL_ARGS.input);
Expand Down Expand Up @@ -265,8 +276,10 @@ static void parse_args(int argc, char *argv[])
usage();
exit(0);
default:
/* save the option for later */
parsec_argv_append(&token_count, &extra_argv, optarg);
if(NULL != optarg) {
/* save the option for later, if there was one */
parsec_argv_append(&token_count, &extra_argv, optarg);
}
}
}

Expand Down Expand Up @@ -408,6 +421,13 @@ int main(int argc, char *argv[])
return 1;
}

if( JDF_COMPILER_GLOBAL_ARGS.termdet == TERMDET_DYNAMIC ) {
rc = jdf_force_termdet_dynamic(&current_jdf);
if(rc != 0) {
return 1;
}
}

/* Lets try to optimize the jdf */
jdf_optimize( &current_jdf );

Expand Down
Loading

0 comments on commit 4ba2aa0

Please sign in to comment.