1
1

* Add LLM (the rte resource allocator) framework

* Add hostfile component for the LLM (reads hostfiles, returns array of
  node identifiers

NOTES: 
  - This will require the full autogen / configure / make.
  - You now need flex to build Open MPI from Subversion.  The versions
    available on most Linux boxen and OS X is more than new enough.  You
    do *not* need flex to build from a nightly or release tarball.

This commit was SVN r1890.
Этот коммит содержится в:
Brian Barrett 2004-08-05 14:01:45 +00:00
родитель 2399ac3cf8
Коммит dadb047103
35 изменённых файлов: 1541 добавлений и 2 удалений

Просмотреть файл

@ -55,7 +55,7 @@ fi
# The list of MCA types (it's fixed)
AC_MSG_CHECKING([for MCA types])
found_types="allocator coll common gpr io mpool ns one oob op pcm pml ptl topo"
found_types="allocator coll common gpr io llm mpool ns one oob op pcm pml ptl topo"
AC_MSG_RESULT([$found_types])
# Get the list of all the non-configure MCA components that were found by
@ -265,6 +265,11 @@ AC_SUBST(MCA_gpr_STATIC_SUBDIRS)
AC_SUBST(MCA_gpr_DSO_SUBDIRS)
AC_SUBST(MCA_gpr_STATIC_LTLIBS)
AC_SUBST(MCA_llm_ALL_SUBDIRS)
AC_SUBST(MCA_llm_STATIC_SUBDIRS)
AC_SUBST(MCA_llm_DSO_SUBDIRS)
AC_SUBST(MCA_llm_STATIC_LTLIBS)
AC_SUBST(MCA_ns_ALL_SUBDIRS)
AC_SUBST(MCA_ns_STATIC_SUBDIRS)
AC_SUBST(MCA_ns_DSO_SUBDIRS)

Просмотреть файл

@ -602,6 +602,11 @@ WRAPPER_EXTRA_LIBS="$WRAPPER_EXTRA_LIBS $THREAD_LIBS"
AC_PROG_LN_S
#
# We need lex
#
AM_PROG_LEX
#
# File system case sensitivity
#
@ -879,6 +884,9 @@ AC_CONFIG_FILES([
src/mca/pcm/Makefile
src/mca/pcm/base/Makefile
src/mca/llm/Makefile
src/mca/llm/base/Makefile
src/mca/allocator/Makefile
src/mca/allocator/base/Makefile
src/mca/coll/Makefile
@ -904,6 +912,7 @@ AC_CONFIG_FILES([
src/dynamic-mca/oob/Makefile
src/dynamic-mca/pcm/Makefile
src/dynamic-mca/llm/Makefile
src/dynamic-mca/Makefile
src/dynamic-mca/allocator/Makefile
@ -938,6 +947,8 @@ AC_CONFIG_FILES([
test/mca/Makefile
test/mca/oob/Makefile
test/mca/ns/Makefile
test/mca/llm/Makefile
test/mca/llm/base/Makefile
test/threads/Makefile
test/util/Makefile
test/rte/Makefile

Просмотреть файл

@ -10,6 +10,7 @@ SUBDIRS = \
common \
io \
mpool \
llm \
ns \
one \
oob \

14
src/dynamic-mca/llm/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,14 @@
#
# $HEADER$
#
include $(top_srcdir)/config/Makefile.options
SUBDIRS = $(MCA_llm_DSO_SUBDIRS)
DISTCLEANFILES = $(SUBDIRS)
# Every directory under here is a sym link to something in the main
# share/ssi tree. Hence, we don't want to distribute anything under
# here.
DIST_SUBDIRS =

Просмотреть файл

@ -10,6 +10,7 @@ SUBDIRS = \
coll \
common \
io \
llm \
mpool \
ns \
one \
@ -35,6 +36,7 @@ libmca_la_LIBADD = \
allocator/libmca_allocator.la \
base/libmca_base.la \
coll/libmca_coll.la \
llm/libmca_llm.la \
mpool/libmca_mpool.la \
ns/libmca_ns.la \
oob/libmca_oob.la \

31
src/mca/llm/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,31 @@
#
# $HEADER$
#
include $(top_srcdir)/config/Makefile.options
SUBDIRS = base $(MCA_llm_STATIC_SUBDIRS)
DIST_SUBDIRS = base $(MCA_llm_ALL_SUBDIRS)
noinst_LTLIBRARIES = libmca_llm.la
# Source code files
headers = llm.h
# Library
libmca_llm_la_SOURCES = $(headers)
libmca_llm_la_LIBADD = \
$(MCA_llm_STATIC_LTLIBS) \
base/libmca_llm_base.la
libmca_llm_la_DEPENDENCIES = $(libmca_llm_la_LIBADD)
# Conditionally install the header files
if WANT_INSTALL_HEADERS
ompidir = $(includedir)/openmpi/mca/llm
ompi_HEADERS = $(headers)
else
ompidir = $(includedir)
endif

45
src/mca/llm/base/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,45 @@
#
# $HEADER$
#
include $(top_srcdir)/config/Makefile.options
noinst_LTLIBRARIES = libmca_llm_base.la
# For VPATH builds, have to specify where static-modules.h will be found
AM_CPPFLAGS = -I$(top_builddir)/src
# Source code files
noinst_PROGRAMS = \
hostparse
hostparse_SOURCES = \
hostparse.c
hostparse_LDADD = \
libmca_llm_base.la
headers = \
base.h \
base_internal.h \
llm_base_parse_hostfile_lex.h
libmca_llm_base_la_SOURCES = \
$(headers) \
llm_base_map.c \
llm_base_collapse.c \
llm_base_close.c \
llm_base_open.c \
llm_base_parse_hostfile.c \
llm_base_parse_hostfile_lex.l \
llm_base_select.c
# Conditionally install the header files
if WANT_INSTALL_HEADERS
ompidir = $(includedir)/openmpi/mca/llm/base
ompi_HEADERS = $(headers)
else
ompidir = $(includedir)
endif

44
src/mca/llm/base/base.h Обычный файл
Просмотреть файл

@ -0,0 +1,44 @@
/* -*- C -*-
*
* $HEADER$
*/
#ifndef MCA_LLM_BASE_H_
#define MCA_LLM_BASE_H_
#include "ompi_config.h"
#include "mca/mca.h"
#include "mca/llm/llm.h"
/*
* Forward define
*/
/*
* Global functions for the LLM
*/
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
int mca_llm_base_open(void);
int mca_llm_base_select(const char *active_pcm,
mca_llm_base_module_t *selected,
bool *allow_multi_user_threads,
bool *have_hidden_threads);
int mca_llm_base_close(void);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
/*
* Globals
*/
extern int mca_llm_base_output;
extern ompi_list_t mca_llm_base_components_available;
extern mca_llm_base_component_t mca_llm_base_selected_component;
extern mca_llm_base_module_t mca_llm;
#endif /* MCA_LLM_BASE_H */

52
src/mca/llm/base/base_internal.h Обычный файл
Просмотреть файл

@ -0,0 +1,52 @@
/* -*- C -*-
*
* $HEADER$
*/
/**
* @file@
*/
#ifndef MCA_LLM_BASE_INTERNAL_H_
#define MCA_LLM_BASE_INTERNAL_H_
#include "ompi_config.h"
#include "mca/mca.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "class/ompi_value_array.h"
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
/**
* Parse input file and return a list of host entries
*/
ompi_list_t *mca_llm_base_parse_hostfile(const char* filename);
/**
* Rearrage the provide hostlist to meet the requirements of
* nodes / procs
*/
int mca_llm_base_map_resources(int nodes,
int procs,
ompi_list_t *hostlist);
/**
* Remove duplicate host entries from the list, editing
* the count as appropriate and merging key=value pairs.
*
* \note If the same key is used with different values, the hosts
* are considered different.
*/
int mca_llm_base_collapse_resources(ompi_list_t *hostlist);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
extern ompi_mutex_t mca_llm_base_parse_mutex;
#endif

34
src/mca/llm/base/hostparse.c Обычный файл
Просмотреть файл

@ -0,0 +1,34 @@
/* -*- C -*-
*
* $HEADER$
*
*/
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
#include "mca/llm/base/llm_base_parse_hostfile_lex.h"
#include <stdio.h>
#include <stdlib.h>
extern int yylex(void);
extern FILE *yyin;
int
main(int argc, char *argv[])
{
int ret;
if (argc != 2) {
printf("usage: %s <hostfile>\n", argv[0]);
exit(1);
}
yyin = fopen(argv[1], "r");
while (!mca_llm_base_parse_done) {
ret = yylex();
printf("%d: %s\n", ret, mca_llm_base_string);
}
return 0;
}

38
src/mca/llm/base/llm_base_close.c Обычный файл
Просмотреть файл

@ -0,0 +1,38 @@
/*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "include/constants.h"
#include "mca/mca.h"
#include "mca/base/base.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
int mca_llm_base_close(void)
{
OBJ_DESTRUCT(&mca_llm_base_parse_mutex);
/* Blatently ignore the return code (what would we do to recover,
anyway? This module is going away, so errors don't matter
anymore) */
if (NULL != mca_llm_base_selected_component.llm_finalize) {
mca_llm_base_selected_component.llm_finalize();
}
/* Close all remaining available modules (may be one if this is a
OMPI RTE program, or [possibly] multiple if this is ompi_info) */
mca_base_components_close(mca_llm_base_output,
&mca_llm_base_components_available, NULL);
/* All done */
return OMPI_SUCCESS;
}

89
src/mca/llm/base/llm_base_collapse.c Обычный файл
Просмотреть файл

@ -0,0 +1,89 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
#include <stdio.h>
static
bool
has_conflicts(mca_llm_base_node_t *a, mca_llm_base_node_t *b)
{
mca_llm_base_valuepair_t *a_val, *b_val;
ompi_list_item_t *a_item, *b_item;
for (a_item = ompi_list_get_first(&(a->info)) ;
a_item != ompi_list_get_end(&(a->info)) ;
a_item = ompi_list_get_next(a_item)) {
a_val = (mca_llm_base_valuepair_t*) a_item;
for (b_item = ompi_list_get_first(&(b->info)) ;
b_item != ompi_list_get_end(&(b->info)) ;
b_item = ompi_list_get_next(b_item)) {
b_val = (mca_llm_base_valuepair_t*) b_item;
/* if both a_val and b_val have the same key but different
values, we have a conflict */
if ((strcmp(a_val->key, b_val->key) == 0) &&
(strcmp(a_val->value, b_val->value) != 0)) {
return true;
}
}
}
return false;
}
static
void
keyval_merge(mca_llm_base_node_t *new, mca_llm_base_node_t *old)
{
ompi_list_item_t *old_item;
while (NULL != (old_item = ompi_list_remove_first(&(old->info)))) {
ompi_list_append(&(new->info), old_item);
}
}
int
mca_llm_base_collapse_resources(ompi_list_t *hostlist)
{
mca_llm_base_node_t *curr_node, *check_node;
ompi_list_item_t *curr_nodeitem, *check_nodeitem, *tmp;
for (curr_nodeitem = ompi_list_get_first(hostlist) ;
curr_nodeitem != ompi_list_get_end(hostlist) ;
curr_nodeitem = ompi_list_get_next(curr_nodeitem)) {
curr_node = (mca_llm_base_node_t*) curr_nodeitem;
for (check_nodeitem = ompi_list_get_next(curr_nodeitem) ;
check_nodeitem != ompi_list_get_end(hostlist) ;
check_nodeitem = ompi_list_get_next(check_nodeitem)) {
check_node = (mca_llm_base_node_t*) check_nodeitem;
if ((strcmp(curr_node->hostname, check_node->hostname) == 0) &&
(!has_conflicts(curr_node, check_node))) {
/* they are mergeable */
curr_node->count += check_node->count;
keyval_merge(curr_node, check_node);
/* delete from the list */
tmp = ompi_list_remove_item(hostlist,
check_nodeitem);
OBJ_RELEASE(check_nodeitem);
check_nodeitem = tmp;
}
}
}
return OMPI_SUCCESS;
}

78
src/mca/llm/base/llm_base_map.c Обычный файл
Просмотреть файл

@ -0,0 +1,78 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
#include <stdio.h>
int
mca_llm_base_map_resources(int nodes,
int procs,
ompi_list_t *hostlist)
{
mca_llm_base_node_t *node;
ompi_list_item_t *nodeitem, *tmp;
if (NULL == hostlist) {
return OMPI_ERROR;
}
/* do the four cases of allocation */
if (0 == nodes && 0 == procs) {
/* allocate as much as we can, so we don't change the list at
all */
} else if (0 == nodes && 0 != procs) {
/* allocate procs process count as dense as possible */
int alloc_procs = 0;
for (nodeitem = ompi_list_get_first(hostlist);
nodeitem != ompi_list_get_end(hostlist);
nodeitem = ompi_list_get_next(nodeitem)) {
node = (mca_llm_base_node_t*) nodeitem;
if (alloc_procs >= procs) {
/* we've allocated enough - release this guy from the
list */
tmp = ompi_list_remove_item(hostlist, nodeitem);
OBJ_RELEASE(nodeitem);
nodeitem = tmp;
} else if (alloc_procs + node->count < procs) {
/* the entire host allocation is needed... */
alloc_procs += node->count;
} else {
/* the entire host allocation isn't needed. dump the
unneeded parts */
node->count = procs - alloc_procs;
alloc_procs = procs;
}
}
} else if (0 != nodes && 0 == procs) {
/* allocate as many nodes as possible with each node having
one slot */
for (nodeitem = ompi_list_get_first(hostlist);
nodeitem != ompi_list_get_end(hostlist);
nodeitem = ompi_list_get_next(nodeitem)) {
node = (mca_llm_base_node_t*) nodeitem;
node->count = 1;
}
} else if (0 != nodes && 0 != procs) {
/* allocate as best we can */
/* BWB - implement me */
return OMPI_ERR_FATAL;
} else {
return OMPI_ERR_FATAL;
}
return OMPI_SUCCESS;
}

93
src/mca/llm/base/llm_base_open.c Обычный файл
Просмотреть файл

@ -0,0 +1,93 @@
/*
* $HEADER$
*/
#include "ompi_config.h"
#include "mca/mca.h"
#include "mca/base/base.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
/*
* The following file was created by configure. It contains extern
* statements and the definition of an array of pointers to each
* module's public mca_base_module_t struct.
*/
#include "mca/llm/base/static-components.h"
/*
* Global variables
*/
int mca_llm_base_output = -1;
ompi_list_t mca_llm_base_components_available;
mca_llm_base_component_t mca_llm_base_selected_component;
mca_llm_base_module_t mca_llm;
/*
* LLM interface type support
*/
static
void
mca_llm_base_node_construct(ompi_object_t *obj)
{
mca_llm_base_node_t *node = (mca_llm_base_node_t*) obj;
OBJ_CONSTRUCT(&(node->info), ompi_list_t);
}
static
void
mca_llm_base_node_destruct(ompi_object_t *obj)
{
mca_llm_base_node_t *node = (mca_llm_base_node_t*) obj;
OBJ_DESTRUCT(&(node->info));
}
static
void
mca_llm_base_valuepair_construct(ompi_object_t *obj)
{
mca_llm_base_valuepair_t *valpair = (mca_llm_base_valuepair_t*) obj;
valpair->key = NULL;
valpair->value = NULL;
}
static
void
mca_llm_base_valuepair_destruct(ompi_object_t *obj)
{
mca_llm_base_valuepair_t *valpair = (mca_llm_base_valuepair_t*) obj;
if (NULL != valpair->key) free(valpair->key);
if (NULL != valpair->value) free(valpair->value);
}
OBJ_CLASS_INSTANCE(mca_llm_base_node_t, ompi_list_item_t,
mca_llm_base_node_construct, mca_llm_base_node_destruct);
OBJ_CLASS_INSTANCE(mca_llm_base_valuepair_t, ompi_list_item_t,
mca_llm_base_valuepair_construct,
mca_llm_base_valuepair_destruct);
ompi_mutex_t mca_llm_base_parse_mutex;
/**
* Function for finding and opening either all MCA modules, or the one
* that was specifically requested via a MCA parameter.
*/
int mca_llm_base_open(void)
{
/* initialize the internal mutex */
OBJ_CONSTRUCT(&mca_llm_base_parse_mutex, ompi_mutex_t);
/* Open up all available components */
if (OMPI_SUCCESS !=
mca_base_components_open("llm", 0, mca_llm_base_static_components,
&mca_llm_base_components_available)) {
return OMPI_ERROR;
}
/* All done */
return OMPI_SUCCESS;
}

197
src/mca/llm/base/llm_base_parse_hostfile.c Обычный файл
Просмотреть файл

@ -0,0 +1,197 @@
/*
* $HEADER$
*/
#include "ompi_config.h"
#include "class/ompi_list.h"
#include "runtime/runtime.h"
#include "util/output.h"
#include "mca/mca.h"
#include "mca/base/base.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
#include "mca/llm/base/llm_base_parse_hostfile_lex.h"
static void parse_error(void);
static int parse_keyval(int, mca_llm_base_node_t*);
static void
parse_error()
{
printf("hostfile: error reading hostfile at line %d, %s\n",
yynewlines, mca_llm_base_string);
}
static
int
parse_keyval(int first, mca_llm_base_node_t *node)
{
int val;
char *key, *value;
mca_llm_base_valuepair_t *keyval;
if (MCA_LLM_BASE_STRING != first) {
return OMPI_ERROR;
}
/* grab the key */
key = strdup(mca_llm_base_string);
if (NULL == key) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* find the equals */
if (MCA_LLM_BASE_EQUAL != yylex()) {
free(key);
return OMPI_ERROR;
}
/* make sure we have a value */
val = yylex();
if (MCA_LLM_BASE_STRING != val && MCA_LLM_BASE_QUOTED_STRING != val) {
free(key);
return OMPI_ERROR;
}
/* grab the value */
value = strdup(mca_llm_base_string);
if (NULL == value) {
free(key);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* make a keyval and store it */
keyval = OBJ_NEW(mca_llm_base_valuepair_t);
keyval->key = key;
keyval->value = value;
ompi_list_append(&(node->info), (ompi_list_item_t *) keyval);
return OMPI_SUCCESS;
}
static
int
parse_count(void)
{
/* find the equals */
if (MCA_LLM_BASE_EQUAL != yylex()) return -1;
/* and now the string */
if (MCA_LLM_BASE_STRING != yylex()) return -1;
return atoi(mca_llm_base_string);
}
static
int
parse_line(int first, mca_llm_base_node_t *node)
{
int val;
int ret;
if (MCA_LLM_BASE_STRING == first) {
strncpy(node->hostname, mca_llm_base_string, MAXHOSTNAMELEN);
node->count = 1;
} else {
parse_error();
return OMPI_ERROR;
}
while (!mca_llm_base_parse_done) {
val = yylex();
switch (val) {
case MCA_LLM_BASE_DONE:
return OMPI_SUCCESS;
break;
case MCA_LLM_BASE_NEWLINE:
return OMPI_SUCCESS;
break;
case MCA_LLM_BASE_COUNT:
ret = parse_count();
if (ret < 0) return OMPI_ERROR;
node->count = ret;
break;
case MCA_LLM_BASE_STRING:
ret = parse_keyval(val, node);
if (OMPI_SUCCESS != ret) return ret;
break;
default:
parse_error();
return OMPI_ERROR;
break;
}
}
return OMPI_SUCCESS;
}
ompi_list_t *
mca_llm_base_parse_hostfile(const char *hostfile)
{
mca_llm_base_node_t *newnode;
ompi_list_t *list;
int val, ret;
OMPI_LOCK(&mca_llm_base_parse_mutex);
list = OBJ_NEW(ompi_list_t);
mca_llm_base_parse_done = 0;
yyin = fopen(hostfile, "r");
if (NULL == yyin) {
printf("hostfile: could not open %s\n", hostfile);
OBJ_RELEASE(list);
list = NULL;
goto parse_exit;
}
while (!mca_llm_base_parse_done) {
val = yylex();
switch (val) {
case MCA_LLM_BASE_DONE:
goto parse_exit;
break;
case MCA_LLM_BASE_NEWLINE:
/* blank line! ignore it */
break;
case MCA_LLM_BASE_STRING:
newnode = OBJ_NEW(mca_llm_base_node_t);
ret = parse_line(val, newnode);
if (OMPI_SUCCESS != ret) {
OBJ_RELEASE(newnode);
OBJ_RELEASE(list);
list = NULL;
goto parse_exit;
}
ompi_list_append(list, (ompi_list_item_t *)newnode);
break;
default:
parse_error();
OBJ_RELEASE(list);
list = NULL;
goto parse_exit;
break;
}
}
parse_exit:
OMPI_UNLOCK(&mca_llm_base_parse_mutex);
return list;
}

Просмотреть файл

@ -0,0 +1,25 @@
/* -*- C -*-
*
*/
#ifndef MCA_LLM_BASE_PARSE_HOSTFILE_LEX_H_
#define MCA_LLM_BASE_PARSE_HOSTFILE_LEX_H_
#include <stdio.h>
extern int yylex(void);
extern FILE *yyin;
extern int mca_llm_base_parse_done;
extern char *mca_llm_base_string;
extern int yynewlines;
#define MCA_LLM_BASE_DONE 0
#define MCA_LLM_BASE_ERROR 1
#define MCA_LLM_BASE_QUOTED_STRING 2
#define MCA_LLM_BASE_EQUAL 3
#define MCA_LLM_BASE_STRING 4
#define MCA_LLM_BASE_COUNT 5
#define MCA_LLM_BASE_NEWLINE 6
#endif

Просмотреть файл

@ -0,0 +1,55 @@
%{ /* -*- C -*- */
#include <stdio.h>
#include "mca/llm/base/llm_base_parse_hostfile_lex.h"
/*
* local functions
*/
static int yyerror(void);
int yywrap(void);
/*
* global variables
*/
int yynewlines=1;
int mca_llm_base_parse_done = 0;
char *mca_llm_base_string = NULL;
%}
%%
\n { yynewlines++; return MCA_LLM_BASE_NEWLINE; }
\"[^\"]*\" { mca_llm_base_string = yytext; return MCA_LLM_BASE_QUOTED_STRING; }
[\f\t\v ] ; /* whitespace */
"=" { return MCA_LLM_BASE_EQUAL; }
cpu { mca_llm_base_string = yytext; return MCA_LLM_BASE_COUNT; }
count { mca_llm_base_string = yytext; return MCA_LLM_BASE_COUNT; }
[A-Za-z0-9_\-\.]* { mca_llm_base_string = yytext; return MCA_LLM_BASE_STRING; }
. { mca_llm_base_string = yytext; return MCA_LLM_BASE_ERROR; }
%%
static
int
yyerror()
{
printf("%d: Invalid input (%s)\n", yynewlines, yytext);
return MCA_LLM_BASE_ERROR;
}
int
yywrap()
{
mca_llm_base_parse_done = 1;
return 1;
}

152
src/mca/llm/base/llm_base_select.c Обычный файл
Просмотреть файл

@ -0,0 +1,152 @@
/*
* $HEADER$
*/
#include "ompi_config.h"
#include "class/ompi_list.h"
#include "runtime/runtime.h"
#include "util/output.h"
#include "mca/mca.h"
#include "mca/base/base.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
typedef struct opened_component_t {
ompi_list_item_t super;
mca_llm_base_component_t *oc_component;
} opened_component_t;
/**
* Function for selecting one module from all those that are
* available.
*
* Call the init function on all available modules and get their
* priorities. Select the module with the highest priority. All
* other modules will be closed and unloaded. The selected module
* will have all of its function pointers saved and returned to the
* caller.
*/
int
mca_llm_base_select(const char *active_pcm,
mca_llm_base_module_t *selected,
bool *allow_multi_user_threads,
bool *have_hidden_threads)
{
int priority, best_priority;
bool user_threads, hidden_threads;
bool best_user_threads, best_hidden_threads;
ompi_list_item_t *item;
mca_base_component_list_item_t *cli;
mca_llm_base_component_t *component, *best_component;
mca_llm_base_module_t *module, *best_module;
ompi_list_t opened;
opened_component_t *oc;
/* Traverse the list of available components; call their init
functions. */
best_priority = -1;
best_component = NULL;
OBJ_CONSTRUCT(&opened, ompi_list_t);
for (item = ompi_list_get_first(&mca_llm_base_components_available);
ompi_list_get_end(&mca_llm_base_components_available) != item;
item = ompi_list_get_next(item)) {
cli = (mca_base_component_list_item_t *) item;
component = (mca_llm_base_component_t *) cli->cli_component;
ompi_output_verbose(10, mca_llm_base_output,
"select: initializing %s component %s",
component->llm_version.mca_type_name,
component->llm_version.mca_component_name);
if (NULL == component->llm_init) {
ompi_output_verbose(10, mca_llm_base_output,
"select: no init function; ignoring component");
} else {
module = component->llm_init(active_pcm, &priority, &user_threads,
&hidden_threads);
if (NULL == module) {
ompi_output_verbose(10, mca_llm_base_output,
"select: init returned failure");
} else {
ompi_output_verbose(10, mca_llm_base_output,
"select: init returned priority %d", priority);
if (priority > best_priority) {
best_priority = priority;
best_user_threads = user_threads;
best_hidden_threads = hidden_threads;
best_component = component;
best_module = module;
}
oc = malloc(sizeof(opened_component_t));
if (NULL == oc) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
OBJ_CONSTRUCT(oc, ompi_list_item_t);
oc->oc_component = component;
ompi_list_append(&opened, (ompi_list_item_t*) oc);
}
}
}
/* Finished querying all components. Check for the bozo case. */
if (NULL == best_component) {
/* JMS Replace with show_help */
ompi_abort(1, "No llm component available. This shouldn't happen.");
}
/* Finalize all non-selected components */
for (item = ompi_list_remove_first(&opened);
NULL != item;
item = ompi_list_remove_first(&opened)) {
oc = (opened_component_t *) item;
if (oc->oc_component != best_component) {
/* Finalize */
if (NULL != oc->oc_component->llm_finalize) {
/* Blatently ignore the return code (what would we do to
recover, anyway? This component is going away, so errors
don't matter anymore) */
oc->oc_component->llm_finalize();
ompi_output_verbose(10, mca_llm_base_output,
"select: component %s not selected / finalized",
component->llm_version.mca_component_name);
}
}
free(oc);
}
/* This base function closes, unloads, and removes from the
available list all unselected components. The available list will
contain only the selected component. */
mca_base_components_close(mca_llm_base_output,
&mca_llm_base_components_available,
(mca_base_component_t *) best_component);
/* Save the winner */
mca_llm_base_selected_component = *best_component;
mca_llm = *best_module;
*selected = *best_module;
*allow_multi_user_threads = best_user_threads;
*have_hidden_threads = best_hidden_threads;
ompi_output_verbose(10, mca_llm_base_output,
"select: component %s selected",
component->llm_version.mca_component_name);
OBJ_DESTRUCT(&opened);
/* All done */
return OMPI_SUCCESS;
}

34
src/mca/llm/hostfile/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,34 @@
#
# $HEADER$
#
# Use the top-level Makefile.options
include $(top_ompi_srcdir)/config/Makefile.options
SUBDIRS = src etc
EXTRA_DIST = VERSION
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
# (for static builds).
if OMPI_BUILD_llm_hostfile_DSO
component_noinst =
component_install = mca_llm_hostfile.la
else
component_noinst = libmca_llm_hostfile.la
component_install =
endif
mcacomponentdir = $(libdir)/openmpi
mcacomponent_LTLIBRARIES = $(component_install)
mca_llm_hostfile_la_SOURCES =
mca_llm_hostfile_la_LIBADD = src/libmca_llm_hostfile.la
mca_llm_hostfile_la_LDFLAGS = -module -avoid-version
noinst_LTLIBRARIES = $(component_noinst)
libmca_llm_hostfile_la_SOURCES =
libmca_llm_hostfile_la_LIBADD = src/libmca_llm_hostfile.la
libmca_llm_hostfile_la_LDFLAGS = -module -avoid-version

6
src/mca/llm/hostfile/VERSION Обычный файл
Просмотреть файл

@ -0,0 +1,6 @@
major=1
minor=0
release=0
alpha=0
beta=0
svn=1

9
src/mca/llm/hostfile/configure.params Обычный файл
Просмотреть файл

@ -0,0 +1,9 @@
# -*- shell-script -*-
#
# $HEADER$
#
# Specific to this module
PARAM_INIT_FILE=src/llm_hostfile.c
PARAM_CONFIG_FILES="Makefile src/Makefile etc/Makefile"

11
src/mca/llm/hostfile/etc/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,11 @@
#
# $HEADER$
#
# Use the top-level Makefile.options
include $(top_ompi_srcdir)/config/Makefile.options
sysconf_DATA = \
llm_hostfile

1
src/mca/llm/hostfile/etc/llm_hostfile Обычный файл
Просмотреть файл

@ -0,0 +1 @@
localhost

15
src/mca/llm/hostfile/src/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,15 @@
#
# $HEADER$
#
include $(top_ompi_srcdir)/config/Makefile.options
AM_CPPFLAGS = \
-DOMPI_SYSCONFDIR="\"$(sysconfdir)\""
noinst_LTLIBRARIES = libmca_llm_hostfile.la
libmca_llm_hostfile_la_SOURCES = \
llm_hostfile.c \
llm_hostfile_component.c \
llm_hostfile_allocate.c \
llm_hostfile_deallocate.c

38
src/mca/llm/hostfile/src/llm_hostfile.c Обычный файл
Просмотреть файл

@ -0,0 +1,38 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "llm_hostfile.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
struct mca_llm_base_module_1_0_0_t mca_llm_hostfile_module = {
mca_llm_hostfile_allocate_resources,
mca_llm_hostfile_deallocate_resources
};
char *mca_llm_hostfile_filename = NULL;
struct mca_llm_module_1_0_0_t*
mca_llm_hostfile_component_init(const char *active_pcm,
int *priority,
bool *allow_multiple_user_threads,
bool *have_hidden_threads)
{
*allow_multiple_user_threads = true;
*have_hidden_threads = false;
*priority = 1;
return &mca_llm_hostfile_module;
}
int
mca_llm_hostfile_component_finalize(void)
{
return OMPI_SUCCESS;
}

53
src/mca/llm/hostfile/src/llm_hostfile.h Обычный файл
Просмотреть файл

@ -0,0 +1,53 @@
/* -*- C -*-
*
* $HEADER$
*/
#ifndef LLM_HOSTFILE_H
#define LLM_HOSTFILE_H
#include "ompi_config.h"
#include "mca/mca.h"
#include "mca/llm/llm.h"
/*
* Globally exported variable
*/
extern const mca_llm_base_component_1_0_0_t mca_llm_hostfile_component;
extern char *mca_llm_hostfile_filename;
/*
* llm API functions
*/
#ifdef __cplusplus
extern "C" {
#endif
int mca_llm_hostfile_component_open(void);
int mca_llm_hostfile_component_close(void);
struct mca_llm_module_1_0_0_t*
mca_llm_hostfile_component_init(const char *active_pcm,
int *priority,
bool *allow_multiple_user_threads,
bool *have_hidden_threads);
int mca_llm_hostfile_component_finalize(void);
int mca_llm_hostfile_allocate_resources(int jobid,
int nodes,
int procs,
ompi_list_t **nodelist);
int mca_llm_hostfile_deallocate_resources(int jobid,
ompi_list_t *nodelist);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,40 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "llm_hostfile.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
#include <stdio.h>
extern char *mca_llm_hostfile_filename;
int
mca_llm_hostfile_allocate_resources(int jobid,
int nodes,
int procs,
ompi_list_t **nodelist)
{
ompi_list_t *hostlist = NULL;
int ret;
/* start by getting the full list of available resources */
hostlist = mca_llm_base_parse_hostfile(mca_llm_hostfile_filename);
if (NULL == hostlist) {
return OMPI_ERROR;
}
ret = mca_llm_base_collapse_resources(hostlist);
if (OMPI_SUCCESS != ret) {
return ret;
}
ret = mca_llm_base_map_resources(nodes, procs, hostlist);
*nodelist = hostlist;
return ret;
}

Просмотреть файл

@ -0,0 +1,74 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "llm_hostfile.h"
#include "util/os_path.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
#include "mca/base/mca_base_param.h"
/*
* Instantiate the public struct with all of our public information
* and pointers to our public functions in it
*/
const mca_llm_base_component_1_0_0_t mca_llm_hostfile_component = {
/* First, the mca_module_t struct containing meta information
about the module itself */
{
/* Indicate that we are a llm v1.0.0 module (which also implies a
specific MCA version) */
MCA_LLM_BASE_VERSION_1_0_0,
/* Module name and version */
"hostfile",
MCA_llm_hostfile_MAJOR_VERSION,
MCA_llm_hostfile_MINOR_VERSION,
MCA_llm_hostfile_RELEASE_VERSION,
/* Module open and close functions */
mca_llm_hostfile_component_open,
mca_llm_hostfile_component_close
},
/* Next the MCA v1.0.0 module meta data */
{
/* Whether the module is checkpointable or not */
false
},
/* Initialization / shutdown functions */
mca_llm_hostfile_component_init,
mca_llm_hostfile_component_finalize
};
int
mca_llm_hostfile_component_open(void)
{
char *default_path = ompi_os_path(false, OMPI_SYSCONFDIR,
"llm_hostfile", NULL);
int id = mca_base_param_register_string("llm",
"hostfile",
"hostfile",
NULL,
default_path);
mca_base_param_lookup_string(id, &mca_llm_hostfile_filename);
if (NULL != default_path) free(default_path);
return OMPI_SUCCESS;
}
int
mca_llm_hostfile_component_close(void)
{
return OMPI_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,28 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "llm_hostfile.h"
#include "mca/llm/llm.h"
#include "mca/llm/base/base.h"
int
mca_llm_hostfile_deallocate_resources(int jobid,
ompi_list_t *nodelist)
{
mca_llm_base_node_t *node;
ompi_list_item_t *item;
while (NULL != (item = ompi_list_remove_first(nodelist))) {
node = (mca_llm_base_node_t*) item;
OBJ_RELEASE(node);
}
OBJ_RELEASE(nodelist);
return OMPI_SUCCESS;
}

168
src/mca/llm/llm.h Обычный файл
Просмотреть файл

@ -0,0 +1,168 @@
/* -*- C -*-
*
* $HEADER$
*/
/**
* @file
*
* Location List Manager (LLM)
*
* The Location List Manager (LLM) is an MCA component that provides
* resource allocation for the Process Control Manager (PCM). The LLM
* is intended to be used by the PCM and should not be used outside of
* the PCM framework.
*
*/
#ifndef MCA_LLM_H
#define MCA_LLM_H
#include "ompi_config.h"
#include "mca/mca.h"
#include "class/ompi_list.h"
#include <sys/param.h>
/*
* MCA component management functions
*/
/**
* LLM initialization function
*
* Called by the MCA framework to initialize the component. Will
* be called exactly once in the lifetime of the process.
*
* @param active_pcm (IN) Name of the currently active PCM module,
* as it might be useful in determining
* useability.
* @param priority (OUT) Relative priority or ranking use by MCA to
* select a module.
* @param allow_multiple_user_threads (OUT) Whether this module can
* run with multiple threads making calls into
* the library (equivalent of MPI_THREAD_MULTIPLE
* from MPI-land).
* @param have_hidden_threads (OUT) Whether this module needs to start
* a background thread for operation.
*/
typedef struct mca_llm_base_module_1_0_0_t*
(*mca_llm_base_component_init_fn_t)(const char *active_pcm,
int *priority,
bool *allow_multiple_user_threads,
bool *have_hidden_threads);
/**
* LLM finalization function
*
* Called by the MCA framework to finalize the component. Will be
* called once per successful call to llm_base_compoenent_init.
*/
typedef int (*mca_llm_base_component_finalize_fn_t)(void);
/**
* LLM module version and interface functions
*
* \note the first two entries have type names that are a bit
* misleading. The plan is to rename the mca_base_module_*
* types in the future.
*/
struct mca_llm_base_component_1_0_0_t {
mca_base_component_t llm_version;
mca_base_component_data_1_0_0_t llm_data;
mca_llm_base_component_init_fn_t llm_init;
mca_llm_base_component_finalize_fn_t llm_finalize;
};
typedef struct mca_llm_base_component_1_0_0_t mca_llm_base_component_1_0_0_t;
typedef mca_llm_base_component_1_0_0_t mca_llm_base_component_t;
/*
* LLM interface types
*/
struct mca_llm_base_valuepair_t {
ompi_list_item_t super;
char *key;
char *value;
};
typedef struct mca_llm_base_valuepair_t mca_llm_base_valuepair_t;
OBJ_CLASS_DECLARATION(mca_llm_base_valuepair_t);
struct mca_llm_base_node_t {
ompi_list_item_t super;
char hostname[MAXHOSTNAMELEN];
int count;
ompi_list_t info;
};
typedef struct mca_llm_base_node_t mca_llm_base_node_t;
OBJ_CLASS_DECLARATION(mca_llm_base_node_t);
/*
* LLM interface functions
*/
/**
* Allocate requested resources
*
* Allocate the specified nodes / processes for use in a new job.
* Requires a jobid from the PCM interface. The allocation returned
* may be smaller than requested - it is up to the caller to proceed
* as appropriate should this occur. This function should only be
* called once per jobid.
*
* @param jobid (IN) Jobid with which to associate the given resources.
* @param nodes (IN) Number of nodes to try to allocate. If 0,
* the LLM will try to allocate <code>procs</code>
* processes on as many nodes as are needed. If non-zero,
* will try to fairly distribute <code>procs</code>
* processes over the nodes. If <code>procs</code> is 0,
* will attempt to allocate all cpus on
* <code>nodes</code> nodes
* @param procs (IN) Number of processors to try to allocate. See the note
* for <code>nodes</code> for usage.
* @param nodelist (OUT) List of <code>mca_llm_node_t</code>s describing
* the allocated resources.
*
* @warning The type for jobid will change in the near future
*/
typedef int (*mca_llm_base_allocate_resources_fn_t)(int jobid,
int nodes,
int procs,
ompi_list_t **nodelist);
/**
* Deallocate requested resources
*
* Return the resources for the given jobid to the system.
*
* @param jobid (IN) Jobid associated with the resources to be freed.
* @param nodes (IN) Nodelist from associated allocate_resource call.
* All associated memory will be freed as appropriate.
*
* @warning The type for jobid will change in the near future.
*/
typedef int (*mca_llm_base_deallocate_resources_fn_t)(int jobid,
ompi_list_t *nodelist);
struct mca_llm_base_module_1_0_0_t {
mca_llm_base_allocate_resources_fn_t llm_allocate_resources;
mca_llm_base_deallocate_resources_fn_t llm_deallocate_resources;
};
typedef struct mca_llm_base_module_1_0_0_t mca_llm_base_module_1_0_0_t;
typedef struct mca_llm_base_module_1_0_0_t mca_llm_base_module_t;
/*
* Macro for use in modules that are of type pml v1.0.0
*/
#define MCA_LLM_BASE_VERSION_1_0_0 \
/* llm v1.0 is chained to MCA v1.0 */ \
MCA_BASE_VERSION_1_0_0, \
/* llm v1.0 */ \
"llm", 1, 0, 0
#endif /* MCA_LLM_H */

Просмотреть файл

@ -5,6 +5,6 @@
include $(top_srcdir)/config/Makefile.options
SUBDIRS = oob
SUBDIRS = oob llm
DIST_SUBDIRS = $(SUBDIRS) ns

8
test/mca/llm/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,8 @@
# -*- makefile -*-
#
# $HEADER$
#
include $(top_srcdir)/config/Makefile.options
SUBDIRS = base

17
test/mca/llm/base/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,17 @@
# -*- makefile -*-
#
# $HEADER$
#
include $(top_srcdir)/config/Makefile.options
AM_CPPFLAGS = -I$(top_srcdir)/test/support -DOMPI_ENABLE_DEBUG_OVERRIDE=1
noinst_PROGRAMS = \
parse_hostfile
parse_hostfile_SOURCES = \
parse_hostfile.c
parse_hostfile_LDADD = \
$(top_builddir)/src/libmpi.la \
$(top_builddir)/test/support/libsupport.la
parse_hostfile_DEPENDENCIES = $(parse_hostfile_LDADD)

60
test/mca/llm/base/parse_hostfile.c Обычный файл
Просмотреть файл

@ -0,0 +1,60 @@
/* -*- C -*-
*
* $HEADER$
*/
#include "ompi_config.h"
#include "mca/llm/base/base.h"
#include "mca/llm/base/base_internal.h"
int
main(int argc, char *argv[])
{
ompi_list_t *hostlist;
mca_llm_base_node_t *node;
mca_llm_base_valuepair_t *valpair;
ompi_list_item_t *nodeitem, *valpairitem;
hostlist = mca_llm_base_parse_hostfile("testfile");
assert(hostlist != NULL);
printf("Original hostfile\n");
for (nodeitem = ompi_list_get_first(hostlist);
nodeitem != ompi_list_get_end(hostlist);
nodeitem = ompi_list_get_next(nodeitem)) {
node = (mca_llm_base_node_t*) nodeitem;
printf("\t%s %d\n", node->hostname, node->count);
for (valpairitem = ompi_list_get_first(&(node->info));
valpairitem != ompi_list_get_end(&(node->info));
valpairitem = ompi_list_get_next(valpairitem)) {
valpair = (mca_llm_base_valuepair_t*) valpairitem;
printf("\t\t%s = %s\n", valpair->key, valpair->value);
}
}
mca_llm_base_collapse_resources(hostlist);
printf("Compressed hostfile\n");
for (nodeitem = ompi_list_get_first(hostlist);
nodeitem != ompi_list_get_end(hostlist);
nodeitem = ompi_list_get_next(nodeitem)) {
node = (mca_llm_base_node_t*) nodeitem;
printf("\t%s %d\n", node->hostname, node->count);
for (valpairitem = ompi_list_get_first(&(node->info));
valpairitem != ompi_list_get_end(&(node->info));
valpairitem = ompi_list_get_next(valpairitem)) {
valpair = (mca_llm_base_valuepair_t*) valpairitem;
printf("\t\t%s = %s\n", valpair->key, valpair->value);
}
}
OBJ_RELEASE(hostlist);
return 0;
}

11
test/mca/llm/base/testfile Обычный файл
Просмотреть файл

@ -0,0 +1,11 @@
host1.example.com key = val
host2.example.com count = 3 user = anju string = "I am a string"
host3.example.com count = 1
192.168.1.1
192.168.2.1 count = 4 user=brbarret string="Go away"
host2.example.com count = 2 user = bbarrett
host3.example.com count = 2
host4.example.com count = 2 user = bbarrett foo = bar
host4.example.com count = 5 user = bbarrett bar = foo
host5.example.com foo = bar
host5.example.com bar = foo