/* * return next tree item that matches key */ opal_tree_item_t *opal_tree_find_with(opal_tree_item_t *item, void *key) { opal_tree_item_t *curr_item = item, *result = NULL; if (!opal_tree_is_empty(item->opal_tree_container)) { /* check my descendant for a match */ result = find_in_descendants(opal_tree_get_first_child(item), key); if (!result) { /* check my siblings for match */ if (NULL != (curr_item = opal_tree_get_next_sibling(curr_item))) { result = find_in_descendants(curr_item, key); } } /* check my ancestors (uncles) for match */ curr_item = item; while (!result && curr_item && curr_item->opal_tree_num_ancestors > 0){ curr_item = opal_tree_get_next_sibling(item->opal_tree_parent); while (NULL == curr_item && item->opal_tree_parent->opal_tree_num_ancestors > 0) { item = item->opal_tree_parent; curr_item = opal_tree_get_next_sibling(item->opal_tree_parent); } if (curr_item) { /* search ancestors descendants for match */ result = find_in_descendants(curr_item, key); } } } return(result); }
static void pretty_print_subtree(opal_tree_t *tree, opal_tree_item_t *parent, int level) { opal_tree_item_t *child = NULL; if( NULL == parent ) { return; } /* * Display Self */ pretty_print_subtree_element(tree, parent, level); /* * Depth-first display children * Basecase; If no children - return */ level++; for(child = opal_tree_get_first_child(parent); child != NULL; child = opal_tree_get_next_sibling(child) ) { pretty_print_subtree(tree, child, level); } return; }
/* * count all the descendants from our level and below */ static int count_descendants(opal_tree_item_t* item) { int current_count = 0; /* loop over all siblings for descendants to count */ while (item) { current_count += count_descendants(opal_tree_get_first_child(item)); current_count++; /* count ourselves */ item = opal_tree_get_next_sibling(item); } return(current_count); }
/* * add item to opal buffer that represents all items of a sub-tree from the * item passed in on down. We exit out of converting tree items once we've * done the last child of the tree_item and we are at depth 1. */ static int add_tree_item2buf(opal_tree_item_t *tree_item, opal_buffer_t *buf, opal_tree_item_serialize_fn_t fn, int depth ) { opal_tree_item_t *first_child; int rc; do { /* add start delim to buffer */ if (OPAL_SUCCESS != (rc = opal_dss.pack(buf, &start_lvl, 1, OPAL_STRING))){ return(rc); } /* add item to opal buffer from class creator */ fn(tree_item, buf); if ((first_child = opal_tree_get_first_child(tree_item))) { /* add items for our children */ if (OPAL_SUCCESS != (rc = add_tree_item2buf(first_child, buf, fn, depth+1))){ return(rc); } if (OPAL_SUCCESS != (rc = opal_dss.pack(buf, &end_lvl, 1, OPAL_STRING))){ return(rc); } } else { /* end item entry */ if (OPAL_SUCCESS != (rc = opal_dss.pack(buf, &end_lvl, 1, OPAL_STRING))){ return(rc); } } /* advance to next sibling, if none we'll drop out of * loop and return to our parent */ tree_item = opal_tree_get_next_sibling(tree_item); } while (tree_item && 1 < depth); return(OPAL_SUCCESS); }
/* * search myself, descendants and siblings for item matching key */ static opal_tree_item_t *find_in_descendants(opal_tree_item_t* item, void *key) { opal_tree_item_t *result = NULL, *first_child; while (!result && item) { /* check for item match */ result = (item->opal_tree_container->comp(item, key) == 0) ? item : NULL; if (!result && (first_child = opal_tree_get_first_child(item))) { /* search descendants for match */ result = find_in_descendants(first_child, key); } if (!result) { /* didn't find match at our node or descending so check sibling */ item = opal_tree_get_next_sibling(item); } } return(result); }
static bool item_in_tree(opal_tree_item_t *item, opal_tree_item_t *search_item) { bool result = false; opal_tree_item_t *first_child; while (!result && item) { /* check for item match */ result = (item == search_item) ? true : false; if (!result && (first_child = opal_tree_get_first_child(item))) { /* search descendants for match */ result = item_in_tree(first_child, search_item); } if (!result) { /* didn't find match at our node or descending so check sibling */ item = opal_tree_get_next_sibling(item); } } return(result); }
static int rmaps_lama_prune_max_tree(opal_tree_t *max_tree, opal_tree_item_t *parent_item) { int ret; opal_tree_item_t *child_item = NULL, *next_item; int i; bool found; rmaps_lama_level_type_t *key_max; char *tmp_str = NULL; /* * Basecase */ if( NULL == parent_item ) { return ORTE_SUCCESS; } /* * Recursively decend tree - Depth first * Basecase: No children, loop skipped */ child_item = opal_tree_get_first_child(parent_item); while( child_item != NULL ) { /* Do this before the recursive call, since it might remove this * child so we need to preserve a pointer to the next sibling. */ next_item = opal_tree_get_next_sibling(child_item); if( ORTE_SUCCESS != (ret = rmaps_lama_prune_max_tree(max_tree, child_item)) ) { return ret; } child_item = next_item; } key_max = (rmaps_lama_level_type_t*)max_tree->get_key(parent_item); /* * Check keys against the user supplied layout */ found = false; for(i = 0; i < lama_mapping_num_layouts; ++i ) { if( 0 == max_tree->comp(parent_item, &lama_mapping_layout[i]) ) { found = true; break; } } if( !found ) { if( 15 <= opal_output_get_verbosity(orte_rmaps_base_framework.framework_output) ) { tmp_str = lama_type_enum_to_str(*key_max); opal_output_verbose(5, orte_rmaps_base_framework.framework_output, "mca:rmaps:lama: ----- Before pruning %s", tmp_str); free(tmp_str); rmaps_lama_max_tree_pretty_print_tree(max_tree); } opal_tree_remove_item(max_tree, parent_item); return ORTE_SUCCESS; } return ORTE_SUCCESS; }
static int rmaps_lama_merge_trees(opal_tree_t *src_tree, opal_tree_t *max_tree, opal_tree_item_t *src_parent, opal_tree_item_t *max_parent) { int ret, exit_status = ORTE_SUCCESS; rmaps_lama_level_type_t *key_src, *key_max; opal_tree_item_t *child_item = NULL, *max_grandparent = NULL; opal_tree_item_t *max_child_item = NULL; int num_max, num_src; int i; char *key_src_str = NULL; char *key_max_str = NULL; #if 1 char *str = NULL; #endif /* * Basecase */ if( NULL == src_parent ) { return ORTE_SUCCESS; } key_src = (rmaps_lama_level_type_t*)src_tree->get_key(src_parent); key_max = (rmaps_lama_level_type_t*)max_tree->get_key(max_parent); key_src_str = lama_type_enum_to_str(*key_src); key_max_str = lama_type_enum_to_str(*key_max); if( 15 <= opal_output_get_verbosity(orte_rmaps_base_framework.framework_output) ) { opal_output_verbose(5, orte_rmaps_base_framework.framework_output, "mca:rmaps:lama: CHECK: Merge Trees: Keys Src (%2d - %s) vs Max (%2d - %s)", *key_src, key_src_str, *key_max, key_max_str); } /* * Make sure keys at this level match. * * JJH: Give up if they do not match. * JJH: We should pick a victim and prune from the tree * JJH: preferably from the 'native' tree. */ if( 0 != max_tree->comp(max_parent, src_tree->get_key(src_parent)) ) { /* * If the source conflicts due to cache, iterate to children to find a match. * JJH: Double check this for different heterogenous systems */ if( LAMA_LEVEL_CACHE_L3 == *key_src || LAMA_LEVEL_CACHE_L2 == *key_src || LAMA_LEVEL_CACHE_L1 == *key_src || LAMA_LEVEL_NUMA == *key_src ) { opal_output_verbose(10, orte_rmaps_base_framework.framework_output, "mca:rmaps:lama: Warning: Merge Trees: " "Src with Conflicting Memory Hierarchy [Src (%2d - %s) vs Max (%2d - %s)]", *key_src, key_src_str, *key_max, key_max_str); /* * If we are pruning a cache level, then check to make sure it is * not important to the process layout. */ if( !rmaps_lama_ok_to_prune_level(*key_src) ) { orte_show_help("help-orte-rmaps-lama.txt", "orte-rmaps-lama:merge-conflict-bad-prune-src", true, key_src_str, (NULL == rmaps_lama_cmd_map ? "[Not Provided]" : rmaps_lama_cmd_map), (NULL == rmaps_lama_cmd_bind ? "[Not Provided]" : rmaps_lama_cmd_bind), (NULL == rmaps_lama_cmd_mppr ? "[Not Provided]" : rmaps_lama_cmd_mppr), (NULL == rmaps_lama_cmd_ordering ? "[Not Provided]" : rmaps_lama_cmd_ordering)); exit_status = ORTE_ERROR; goto cleanup; } /* * If the number of children at this pruned level was larger than * the max tree arity at this level, then duplicate the max_tree * element the approprate number of times */ max_grandparent = opal_tree_get_parent(max_parent); num_max = opal_tree_num_children(max_grandparent); num_src = opal_tree_num_children(src_parent); for(i = 0; i < (num_src - num_max); ++i ) { #if 1 str = rmaps_lama_max_tree_pretty_print_subtree_element_get(max_tree, max_parent, 0); opal_output_verbose(5, orte_rmaps_base_framework.framework_output, "mca:rmaps:lama: Merge: Appending child %s - post prune", str); free(str); #endif /* Duplicate max child subtree */ opal_tree_copy_subtree(max_tree, max_parent, max_tree, max_grandparent); } /* * Iterate to children, until we find a match */ for(child_item = opal_tree_get_first_child(src_parent); child_item != NULL; child_item = opal_tree_get_next_sibling(child_item) ) { if( ORTE_SUCCESS != (ret = rmaps_lama_merge_trees(src_tree, max_tree, child_item, max_parent)) ) { exit_status = ret; goto cleanup; } } exit_status = ORTE_SUCCESS; goto cleanup; } /* * If the max tree conflicts due to cache, then we need to prune the * max tree until it matches. * JJH: If we are pruning a level of the hierarchy then make sure we * JJH: don't need it for the process layout. */ else if( LAMA_LEVEL_CACHE_L3 == *key_max || LAMA_LEVEL_CACHE_L2 == *key_max || LAMA_LEVEL_CACHE_L1 == *key_max || LAMA_LEVEL_NUMA == *key_max ) { opal_output_verbose(10, orte_rmaps_base_framework.framework_output, "mca:rmaps:lama: Warning: Merge Trees: " "Max with Conflicting Memory Hierarchy [Src (%2d - %s) vs Max (%2d - %s)]", *key_src, key_src_str, *key_max, key_max_str); /* * If we are pruning a cache level, then check to make sure it is * not important to the process layout. */ if( !rmaps_lama_ok_to_prune_level(*key_max) ) { orte_show_help("help-orte-rmaps-lama.txt", "orte-rmaps-lama:merge-conflict-bad-prune-src", true, key_max_str, (NULL == rmaps_lama_cmd_map ? "[Not Provided]" : rmaps_lama_cmd_map), (NULL == rmaps_lama_cmd_bind ? "[Not Provided]" : rmaps_lama_cmd_bind), (NULL == rmaps_lama_cmd_mppr ? "[Not Provided]" : rmaps_lama_cmd_mppr), (NULL == rmaps_lama_cmd_ordering ? "[Not Provided]" : rmaps_lama_cmd_ordering)); exit_status = ORTE_ERROR; goto cleanup; } max_child_item = opal_tree_get_first_child(max_parent); /* Prune parent */ opal_tree_remove_item(max_tree, max_parent); /* Try again with child */ exit_status = rmaps_lama_merge_trees(src_tree, max_tree, src_parent, max_child_item); goto cleanup; } /* * If we cannot resolve it, give up. */ opal_output(0, "mca:rmaps:lama: Error: Merge Trees: " "Different Keys Src (%2d - %s) vs Max (%2d - %s) - Do not know how to resolve - give up!", *key_src, key_src_str, *key_max, key_max_str); exit_status = ORTE_ERROR; goto cleanup; } num_max = opal_tree_num_children(max_parent); num_src = opal_tree_num_children(src_parent); /* * If the 'native' tree has more children than the 'max' tree. * Add the missing children to the 'max' tree. */ if( num_max < num_src ) { i = 0; for(child_item = opal_tree_get_first_child(src_parent); child_item != NULL; child_item = opal_tree_get_next_sibling(child_item)) { if(i >= num_max ) { #if 1 str = rmaps_lama_max_tree_pretty_print_subtree_element_get(src_tree, child_item, 0); opal_output_verbose(5, orte_rmaps_base_framework.framework_output, "mca:rmaps:lama: Merge: Appending child %s", str); free(str); #endif /* Add child's subtree to max */ opal_tree_copy_subtree(src_tree, child_item, max_tree, max_parent); } ++i; } } /* * Recursively search all children of 'native' tree. * * Note: Only need to add the children to the 'left-most' branch of the * 'max' tree since that is the only branch that is searched during mapping. * But do the whole thing for good measure. */ for( child_item = opal_tree_get_first_child(src_parent), max_child_item = opal_tree_get_first_child(max_parent); child_item != NULL; child_item = opal_tree_get_next_sibling(child_item), max_child_item = opal_tree_get_next_sibling(max_child_item) ) { if( ORTE_SUCCESS != (ret = rmaps_lama_merge_trees(src_tree, max_tree, child_item, max_child_item)) ) { exit_status = ret; goto cleanup; } } cleanup: if( NULL != key_src_str ) { free(key_src_str); key_src_str = NULL; } if( NULL != key_max_str ) { free(key_max_str); key_max_str = NULL; } return exit_status; }