예제 #1
0
/*
 * 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);
}
예제 #2
0
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;

}
예제 #3
0
/*
 * 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);
}
예제 #4
0
/*
 * 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);
}    
예제 #5
0
/*
 * 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);
}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #8
0
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;
}