1
1

Submitted by: Jeff "I love MPI attributes" Squyres

Reviewed by: Brian "MPI attributes ROCK" Barrett

Bunches of changes to the attribute engine:

- After many hours of discussion about MPI attributes, we came to the
  conclusion that MPI-2 Example 4.13 (the C->Fortran example) is just
  wrong.  If you accept that, the rest of the text makes much more
  sense.  
- There are 9 inter-language cases: all combinations of (read, write)
  with C, Fortran MPI-1, and Fortran MPI-2 for each value.  Each of
  the 9 cases have specific code for what is supposed to happen (and
  is labeled in the code with comments).  There is a *lengthy* comment
  at the top of src/attribute/attribute.c that describes all of this. 
- All predefined attributes are now treated as if they were put from
  MPI-1 Fortran calls, with the exception of the window predefined
  attributes (which are irrelevant on the beta, because there is no
  one-sided support; preliminary fixes included in this patch, but
  will be fully addressed on the trunk)
- MPI API calls (particularly the Fortran wrappers) are now
  fundamentally simpler -- they do *not* call the back-end MPI C API
  calls; instead, they call directly back into the attribute engine.
- The MPI_LASTUSEDCODE attribute only exists on MPI_COMM_WORLD and is
  updated appropriately when user error classes are added.  
  --> Note: Edgar made a suggestion that for communicator attributes,
      we ignore the communicator argument when retrieving attributes
      and simply return the value.  This will likely only happen on
      the trunk, and will alleviate (from the user's perspective) the
      restriction that LASTUSEDCODE is only on MPI_COMM_WORLD.

- The predefined attributes are now "better".  We create keyvals
  separately than assigning values, and correctly distinguish between
  comm, type, and win attributes.  Initial values are now set as if
  they were called from MPI-1 fortran.
- Added a comment to the top of src/attribute/attribute_predefined.c
  explaining what each of the predefined attributes were and what OMPI
  sets them to be.

This commit was SVN r6193.
Этот коммит содержится в:
Jeff Squyres 2005-06-27 19:17:11 +00:00
родитель 9a2cfbc7f7
Коммит 225c20162e
20 изменённых файлов: 1159 добавлений и 491 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -35,16 +35,19 @@
#define ATTR_HASH_SIZE 10
/* Flags for attribute will contain these */
#define OMPI_KEYVAL_PREDEFINED 1
#define OMPI_KEYVAL_F77 2
#define OMPI_KEYVAL_F77_OLD 4
/*
* Flags for keyvals
*/
#define OMPI_KEYVAL_PREDEFINED 0x0001
#define OMPI_KEYVAL_F77 0x0002
#define OMPI_KEYVAL_F77_MPI1 0x0004
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
enum ompi_attribute_type_t{
enum ompi_attribute_type_t {
COMM_ATTR = 1, /**< The attribute belongs to a comm object. Starts
with 1 so that we can have it initialized to 0
using memset in the constructor */
@ -239,7 +242,8 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
bool predefined);
/**
* Set an attribute on the comm/win/datatype
* Set an attribute on the comm/win/datatype in a form valid for C.
*
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN/OUT)
@ -257,14 +261,101 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
* function is invoked internally (i.e., when we already hold the
* relevant locks, and we don't want to try to lock them again,
* recursively).
*
* All three of these functions (ompi_attr_set_c(),
* ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
* could have been combined into one function that took some kind of
* (void*) and an enum to indicate which way to translate the final
* representation, but that just seemed to make an already complicated
* situation more complicated through yet another layer of
* indirection.
*
* So yes, this is more code, but it's clearer and less error-prone
* (read: better) this way.
*/
int ompi_attr_set(ompi_attribute_type_t type, void *object,
ompi_hash_table_t **keyhash,
int key, void *attribute, bool predefined, bool need_lock);
int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
ompi_hash_table_t **keyhash,
int key, void *attribute, bool predefined, bool need_lock);
/**
* Get an attribute on the comm/win/datatype
* Set an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-1.
*
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN/OUT)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (IN)
* @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code
*
* If (*keyhash) == NULL, a new keyhash will be created and
* initialized.
*
* Note that need_lock should *always* be true when this function is
* invoked from an top-level MPI function. It is only false when this
* function is invoked internally (i.e., when we already hold the
* relevant locks, and we don't want to try to lock them again,
* recursively).
*
* All three of these functions (ompi_attr_set_c(),
* ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
* could have been combined into one function that took some kind of
* (void*) and an enum to indicate which way to translate the final
* representation, but that just seemed to make an already complicated
* situation more complicated through yet another layer of
* indirection.
*
* So yes, this is more code, but it's clearer and less error-prone
* (read: better) this way.
*/
int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
ompi_hash_table_t **keyhash,
int key, MPI_Fint attribute,
bool predefined, bool need_lock);
/**
* Set an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-2.
*
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN/OUT)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (IN)
* @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code
*
* If (*keyhash) == NULL, a new keyhash will be created and
* initialized.
*
* Note that need_lock should *always* be true when this function is
* invoked from an top-level MPI function. It is only false when this
* function is invoked internally (i.e., when we already hold the
* relevant locks, and we don't want to try to lock them again,
* recursively).
*
* All three of these functions (ompi_attr_set_c(),
* ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
* could have been combined into one function that took some kind of
* (void*) and an enum to indicate which way to translate the final
* representation, but that just seemed to make an already complicated
* situation more complicated through yet another layer of
* indirection.
*
* So yes, this is more code, but it's clearer and less error-prone
* (read: better) this way.
*/
int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
ompi_hash_table_t **keyhash,
int key, MPI_Aint attribute,
bool predefined, bool need_lock);
/**
* Get an attribute on the comm/win/datatype in a form valid for C.
*
* @param keyhash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT)
@ -272,10 +363,74 @@ int ompi_attr_set(ompi_attribute_type_t type, void *object,
* with the key (OUT)
* @return OMPI error code
*
* All three of these functions (ompi_attr_get_c(),
* ompi_attr_get_fortran_mpi1(), and ompi_attr_get_fortran_mpi2())
* could have been combined into one function that took some kind of
* (void*) and an enum to indicate which way to translate the final
* representation, but that just seemed to make an already complicated
* situation more complicated through yet another layer of
* indirection.
*
* So yes, this is more code, but it's clearer and less error-prone
* (read: better) this way.
*/
int ompi_attr_get(ompi_hash_table_t *keyhash, int key,
void *attribute, int *flag);
int ompi_attr_get_c(ompi_hash_table_t *keyhash, int key,
void **attribute, int *flag);
/**
* Get an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-1.
*
* @param keyhash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated
* with the key (OUT)
* @return OMPI error code
*
* All three of these functions (ompi_attr_get_c(),
* ompi_attr_get_fortran_mpi1(), and ompi_attr_get_fortran_mpi2())
* could have been combined into one function that took some kind of
* (void*) and an enum to indicate which way to translate the final
* representation, but that just seemed to make an already complicated
* situation more complicated through yet another layer of
* indirection.
*
* So yes, this is more code, but it's clearer and less error-prone
* (read: better) this way.
*/
int ompi_attr_get_fortran_mpi1(ompi_hash_table_t *keyhash, int key,
MPI_Fint *attribute, int *flag);
/**
* Get an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-2.
*
* @param keyhash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated
* with the key (OUT)
* @return OMPI error code
*
* All three of these functions (ompi_attr_get_c(),
* ompi_attr_get_fortran_mpi1(), and ompi_attr_get_fortran_mpi2())
* could have been combined into one function that took some kind of
* (void*) and an enum to indicate which way to translate the final
* representation, but that just seemed to make an already complicated
* situation more complicated through yet another layer of
* indirection.
*
* So yes, this is more code, but it's clearer and less error-prone
* (read: better) this way.
*/
int ompi_attr_get_fortran_mpi2(ompi_hash_table_t *keyhash, int key,
MPI_Aint *attribute, int *flag);
/**

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

@ -14,6 +14,66 @@
* $HEADER$
*/
/**
* @file
*
* Setup the predefined attributes in MPI.
*
* A number of pre-defined attributes are created here, most of which
* are exactly what one would expect, but there are a few exceptions
* -- so they're documented here.
*
* Predefined attributes are integer-valued or address-valued (per
* MPI-2; see section 4.12.7, keeping in mind that Example 4.13 is
* totally wrong -- see src/attribute/attribute.h for a lengthy
* explanation of this).
*
* The only address-valued attribute is MPI_WIN_BASE. We treat it as
* if it were set from C. All other attributes are integer-valued.
* We treat them as if they were set from Fortran MPI-1 (i.e.,
* MPI_ATTR_PUT) or Fortran MPI-2 (i.e., MPI_xxx_ATTR_SET). Most
* attributes are MPI-1 integer-valued, meaning that they are the size
* of MPI_Fint (INTEGER). But MPI_WIN_SIZE and MPI_WIN_DISP_UNIT are
* MPI-2 integer-valued, meaning that they are the size of MPI_Aint
* (INTEGER(KIND=MPI_ADDRESS_KIND)).
*
* MPI_TAG_UB is set to a fixed upper limit.
*
* MPI_HOST is set to MPI_PROC_NULL (per MPI-1, see 7.1.1, p192).
*
* MPI_IO is set to 1 because OMPI provides IO forwarding.
*
* MPI_WTIME_IS_GLOBAL is set to 0 (a conservative answer).
*
* MPI_APPNUM is set as the result of a GPR subscription.
*
* MPI_LASTUSEDCODE is set to an initial value and is reset every time
* MPI_ADD_ERROR_CLASS is invoked. Its copy function is set to
* MPI_COMM_NULL_COPY_FN, meaning that *only* MPI_COMM_WORLD will have
* this attribute value. As such, we only have to update
* MPI_COMM_WORLD when this value changes (i.e., since this is an
* integer-valued attribute, we have to update this attribute on every
* communicator -- using NULL_COPY_FN ensures that only MPI_COMM_WORLD
* has this attribute value set).
*
* MPI_UNIVERSE_SIZE is set as the result of a GPR subscription.
*
* MPI_WIN_BASE is an address-valued attribute, and is set directly
* from MPI_WIN_CREATE. MPI_WIN_SIZE and MPI_WIN_DISP_UNIT are both
* integer-valued attributes, *BUT* at least the MPI_WIN_SIZE is an
* MPI_Aint, so in terms of consistency, both should be the same --
* hence, we treat them as MPI-2 Fortran integer-valued attributes.
* All three of these atrributes have NULL_COPY_FN copy functions; it
* doesn't make sense to copy them to new windows (because they're
* values specific and unique to each window) -- especially when
* WIN_CREATE will explicitly set them on new windows anyway.
*
* These are not supported yet, but are included here for consistency:
*
* MPI_IMPI_CLIENT_SIZE, MPI_IMPI_CLIENT_COLOR, MPI_IMPI_HOST_SIZE,
* and MPI_IMPI_HOST_COLOR are integer-valued attributes.
*/
#include "ompi_config.h"
#include "mpi.h"
@ -23,6 +83,7 @@
#include "errhandler/errclass.h"
#include "communicator/communicator.h"
#include "util/proc_info.h"
#include "util/sys_info.h"
#include "mca/ns/ns.h"
#include "mca/gpr/gpr.h"
#include "mca/errmgr/errmgr.h"
@ -32,46 +93,80 @@
/*
* Private functions
*/
static int set(int keyval, void *value);
/*
* Back-end for attribute values
*/
static int attr_tag_ub = MPI_TAG_UB_VALUE;
static char *attr_host = NULL;
static int attr_io = 1;
static int attr_wtime_is_global = 0;
/* Filled in at run-time, below */
static int attr_appnum = -1;
/* Filled in at run-time, below */
static int attr_universe_size = -1;
#if 0
static int create_comm(int target_keyval, bool want_inherit);
#if OMPI_WANT_MPI2_ONE_SIDED
/* JMS for when we implement windows */
static int attr_win_base = 0;
static int attr_win_size = 0;
static int attr_win_disp_unit = 0;
#endif
#if 0
/* JMS for when we implement IMPI */
static int attr_impi_client_size = 0;
static int attr_impi_client_color = 0;
static int attr_impi_host_size = 0;
static int attr_impi_host_color = 0;
static int create_win(int target_keyval);
#endif
static int set_f(int keyval, MPI_Fint value);
int ompi_attr_create_predefined(void)
{
int rc;
int rc, ret;
orte_gpr_trigger_t trig, *trig1;
orte_gpr_value_t value, *values;
orte_gpr_subscription_t sub, *sub1;
orte_jobid_t job;
/* Create all the keyvals */
/* DO NOT CHANGE THE ORDER OF CREATING THESE KEYVALS! This order
strictly adheres to the order in mpi.h. If you change the
order here, you must change the order in mpi.h as well! */
if (OMPI_SUCCESS != (ret = create_comm(MPI_TAG_UB, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_HOST, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_IO, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_WTIME_IS_GLOBAL, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_APPNUM, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_LASTUSEDCODE, false)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_UNIVERSE_SIZE, true)) ||
#if OMPI_WANT_MPI2_ONE_SIDED
/* JMS for when we implement windows */
OMPI_SUCCESS != (ret = create_win(MPI_WIN_BASE)) ||
OMPI_SUCCESS != (ret = create_win(MPI_WIN_SIZE)) ||
OMPI_SUCCESS != (ret = create_win(MPI_WIN_DISP_UNIT)) ||
#endif
#if 0
/* JMS For when we implement IMPI */
OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_CLIENT_SIZE, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_CLIENT_COLOR, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_HOST_SIZE, true)) ||
OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_HOST_COLOR, true)) ||
#endif
0) {
return ret;
}
/* Set default values for everything except UNIVERSE_SIZE and
APPNUM. */
if (OMPI_SUCCESS != (ret = set_f(MPI_TAG_UB, MPI_TAG_UB_VALUE)) ||
OMPI_SUCCESS != (ret = set_f(MPI_HOST, MPI_PROC_NULL)) ||
OMPI_SUCCESS != (ret = set_f(MPI_IO, 1)) ||
OMPI_SUCCESS != (ret = set_f(MPI_WTIME_IS_GLOBAL, 0)) ||
OMPI_SUCCESS != (ret = set_f(MPI_LASTUSEDCODE,
ompi_errclass_lastused)) ||
#if 0
/* JMS For when we implement IMPI */
OMPI_SUCCESS != (ret = set(MPI_IMPI_CLIENT_SIZE,
&attr_impi_client_size)) ||
OMPI_SUCCESS != (ret = set(MPI_IMPI_CLIENT_COLOR,
&attr_impi_client_color)) ||
OMPI_SUCCESS != (ret = set(MPI_IMPI_HOST_SIZE,
&attr_impi_host_size)) ||
OMPI_SUCCESS != (ret = set(MPI_IMPI_HOST_COLOR,
&attr_impi_host_color)) ||
#endif
0) {
return ret;
}
/* Now that those are all created, setup the trigger to get the
UNIVERSE_SIZE and APPNUM values once everyone has passed
stg1. */
if (ORTE_SUCCESS != (rc = orte_ns.get_jobid(&job, orte_process_info.my_name))) {
ORTE_ERROR_LOG(rc);
return rc;
@ -177,11 +272,11 @@ void ompi_attr_create_predefined_callback(
orte_gpr_notify_data_t *data,
void *cbdata)
{
int err;
size_t i, j;
orte_gpr_keyval_t **keyval;
orte_gpr_value_t **value;
orte_jobid_t job;
unsigned int universe_size = 0;
/* Set some default values */
@ -189,11 +284,13 @@ void ompi_attr_create_predefined_callback(
return;
}
/* Per conversation between Jeff, Edgar, and Ralph - this needs
* to be fixed to properly determine the appnum
/* Per conversation between Jeff, Edgar, and Ralph - this needs to
* be fixed to properly determine the appnum. Ignore errors here;
* there's no way to propagate the error up, so just try to keep
* going.
*/
attr_appnum = (int)job;
set_f(MPI_APPNUM, (MPI_Fint) job);
/* Query the gpr to find out how many CPUs there will be.
This will only return a non-empty list in a persistent
universe. If we don't have a persistent universe, then just
@ -215,9 +312,8 @@ void ompi_attr_create_predefined_callback(
* happens in-between anyway, so this shouldn't cause a problem.
*/
attr_universe_size = 0;
if (0 == data->cnt) { /* no data returned */
attr_universe_size = ompi_comm_size(MPI_COMM_WORLD);
universe_size = ompi_comm_size(MPI_COMM_WORLD);
} else {
value = data->values;
for (i=0; i < data->cnt; i++) {
@ -229,54 +325,22 @@ void ompi_attr_create_predefined_callback(
*/
if (ORTE_SIZE == keyval[j]->type) {
/* Process slot count */
attr_universe_size += keyval[j]->value.size;
universe_size += keyval[j]->value.size;
}
}
}
}
}
/* DO NOT CHANGE THE ORDER OF CREATING THESE KEYVALS! This order
strictly adheres to the order in mpi.h. If you change the
order here, you must change the order in mpi.h as well! */
if (OMPI_SUCCESS != (err = set(MPI_TAG_UB, &attr_tag_ub)) ||
OMPI_SUCCESS != (err = set(MPI_HOST, &attr_host)) ||
OMPI_SUCCESS != (err = set(MPI_IO, &attr_io)) ||
OMPI_SUCCESS != (err = set(MPI_WTIME_IS_GLOBAL,
&attr_wtime_is_global)) ||
OMPI_SUCCESS != (err = set(MPI_APPNUM, &attr_appnum)) ||
OMPI_SUCCESS != (err = set(MPI_LASTUSEDCODE,
&ompi_errclass_lastused)) ||
OMPI_SUCCESS != (err = set(MPI_UNIVERSE_SIZE, &attr_universe_size)) ||
#if 0
/* JMS for when we implement windows */
/* JMS BE SURE TO READ ALL OF MPI-2 4.12.7 BEFORE IMPLEMENTING
THESE ADDRESS-VALUED ATTRIBUTES! */
OMPI_SUCCESS != (err = set(MPI_WIN_BASE, &attr_win_base)) ||
OMPI_SUCCESS != (err = set(MPI_WIN_SIZE, &attr_win_size)) ||
OMPI_SUCCESS != (err = set(MPI_WIN_DISP_UNIT, &attr_win_disp_unit)) ||
#endif
#if 0
/* JMS For when we implement IMPI */
OMPI_SUCCESS != (err = set(MPI_IMPI_CLIENT_SIZE,
&attr_impi_client_size)) ||
OMPI_SUCCESS != (err = set(MPI_IMPI_CLIENT_COLOR,
&attr_impi_client_color)) ||
OMPI_SUCCESS != (err = set(MPI_IMPI_HOST_SIZE,
&attr_impi_host_size)) ||
OMPI_SUCCESS != (err = set(MPI_IMPI_HOST_COLOR,
&attr_impi_host_color)) ||
#endif
0) {
return;
}
/* Same as above -- ignore errors here because there's nothing we
can do if there's any error anyway */
set_f(MPI_UNIVERSE_SIZE, universe_size);
return;
}
static int set(int target_keyval, void *value)
static int create_comm(int target_keyval, bool want_inherit)
{
int err;
int keyval;
@ -284,18 +348,50 @@ static int set(int target_keyval, void *value)
ompi_attribute_fn_ptr_union_t del;
keyval = -1;
copy.attr_communicator_copy_fn = MPI_COMM_DUP_FN;
copy.attr_communicator_copy_fn =
want_inherit ? MPI_COMM_DUP_FN : MPI_COMM_NULL_COPY_FN;
del.attr_communicator_delete_fn = MPI_COMM_NULL_DELETE_FN;
err = ompi_attr_create_keyval(COMM_ATTR, copy, del,
&keyval, NULL, OMPI_KEYVAL_PREDEFINED);
if (keyval != target_keyval || OMPI_SUCCESS != err) {
if (MPI_SUCCESS != err) {
return err;
}
err = ompi_attr_set(COMM_ATTR, MPI_COMM_WORLD,
&MPI_COMM_WORLD->c_keyhash, keyval, value, true, true);
if (OMPI_SUCCESS != err) {
return err;
if (target_keyval != keyval) {
return OMPI_ERR_BAD_PARAM;
}
return OMPI_SUCCESS;
}
#if OMPI_WANT_MPI2_ONE_SIDED
/* JMS for when we implement windows */
static int create_win(int target_keyval)
{
int err;
int keyval;
ompi_attribute_fn_ptr_union_t copy;
ompi_attribute_fn_ptr_union_t del;
keyval = -1;
copy.attr_win_copy_fn = MPI_WIN_NULL_COPY_FN;
del.attr_win_delete_fn = MPI_WIN_NULL_DELETE_FN;
err = ompi_attr_create_keyval(WIN_ATTR, copy, del,
&keyval, NULL, OMPI_KEYVAL_PREDEFINED);
if (MPI_SUCCESS != err) {
return err;
}
if (target_keyval != keyval) {
return OMPI_ERR_BAD_PARAM;
}
return OMPI_SUCCESS;
}
#endif
static int set_f(int keyval, MPI_Fint value)
{
return ompi_attr_set_fortran_mpi1(COMM_ATTR, MPI_COMM_WORLD,
&MPI_COMM_WORLD->c_keyhash,
keyval, value,
true, true);
}

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

@ -402,6 +402,11 @@ int ompi_errclass_add(void)
newerrclass = OBJ_NEW(ompi_errclass_t);
newerrclass->cls = ompi_errclass_lastused;
ompi_errclass_lastused++;
/* Now need to reset the MPI_LASTUSEDCODE attribute on
MPI_COMM_WORLD */
ompi_pointer_array_set_item(&ompi_errclasses, newerrclass->cls, newerrclass);
return OMPI_SUCCESS;

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

@ -44,9 +44,11 @@ int MPI_Attr_get(MPI_Comm comm, int keyval, void *attribute_val, int *flag)
}
}
/* This stuff is very confusing. Be sure to see MPI-2 4.12.7. */
/* This stuff is very confusing. Be sure to see
src/attribute/attribute.c for a lengthy comment explaining Open
MPI attribute behavior. */
ret = ompi_attr_get(comm->c_keyhash, keyval, attribute_val, flag);
ret = ompi_attr_get_c(comm->c_keyhash, keyval, attribute_val, flag);
OMPI_ERRHANDLER_RETURN(ret, comm, ret, FUNC_NAME);
}

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

@ -44,8 +44,8 @@ int MPI_Attr_put(MPI_Comm comm, int keyval, void *attribute_val)
}
}
ret = ompi_attr_set(COMM_ATTR, comm, &comm->c_keyhash,
keyval, attribute_val, false, true);
ret = ompi_attr_set_c(COMM_ATTR, comm, &comm->c_keyhash,
keyval, attribute_val, false, true);
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
}

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

@ -44,8 +44,11 @@ int MPI_Comm_get_attr(MPI_Comm comm, int comm_keyval,
}
}
ret = ompi_attr_get(comm->c_keyhash, comm_keyval,
attribute_val, flag);
/* This stuff is very confusing. Be sure to see
src/attribute/attribute.c for a lengthy comment explaining Open
MPI attribute behavior. */
ret = ompi_attr_get_c(comm->c_keyhash, comm_keyval,
attribute_val, flag);
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
}

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

@ -44,7 +44,7 @@ int MPI_Comm_set_attr(MPI_Comm comm, int comm_keyval, void *attribute_val)
}
}
ret = ompi_attr_set(COMM_ATTR, comm, &comm->c_keyhash,
comm_keyval, attribute_val, false, true);
ret = ompi_attr_set_c(COMM_ATTR, comm, &comm->c_keyhash,
comm_keyval, attribute_val, false, true);
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
}

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

@ -52,8 +52,12 @@ int MPI_Type_get_attr (MPI_Datatype type,
}
}
ret = ompi_attr_get(type->d_keyhash, type_keyval,
attribute_val, flag);
/* This stuff is very confusing. Be sure to see
src/attribute/attribute.c for a lengthy comment explaining Open
MPI attribute behavior. */
ret = ompi_attr_get_c(type->d_keyhash, type_keyval,
attribute_val, flag);
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD,
MPI_ERR_OTHER, FUNC_NAME);
}

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

@ -48,8 +48,8 @@ int MPI_Type_set_attr (MPI_Datatype type,
}
}
ret = ompi_attr_set(TYPE_ATTR, type, &type->d_keyhash,
type_keyval, attribute_val, false, true);
ret = ompi_attr_set_c(TYPE_ATTR, type, &type->d_keyhash,
type_keyval, attribute_val, false, true);
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD,
MPI_ERR_OTHER, FUNC_NAME);

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

@ -45,7 +45,11 @@ int MPI_Win_get_attr(MPI_Win win, int win_keyval,
}
}
ret = ompi_attr_get(win->w_keyhash, win_keyval,
attribute_val, flag);
/* This stuff is very confusing. Be sure to see
src/attribute/attribute.c for a lengthy comment explaining Open
MPI attribute behavior. */
ret = ompi_attr_get_c(win->w_keyhash, win_keyval,
attribute_val, flag);
OMPI_ERRHANDLER_RETURN(ret, win, MPI_ERR_OTHER, FUNC_NAME);
}

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "communicator/communicator.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_ATTR_GET = mpi_attr_get_f
@ -59,39 +61,15 @@ void mpi_attr_get_f(MPI_Fint *comm, MPI_Fint *keyval,
MPI_Fint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
{
int c_err, c_flag;
MPI_Comm c_comm;
ompi_attribute_fortran_ptr_t value;
c_comm = MPI_Comm_f2c(*comm);
MPI_Comm c_comm = MPI_Comm_f2c(*comm);
/* This stuff is very confusing. Be sure to see MPI-2 4.12.7. */
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
/* Didn't use all the FINT macros that could have prevented a few
extra variables in this function, but I figured that the
clarity of code, and the fact that this is not expected to be a
high-performance function, was worth it */
/* Note that this function deals with attribute values that are
the size of Fortran INTEGERS; the C function MPI_Attr_get deals
with attribute values that are the size of address integers.
Hence, it is possible that you'll lose some precision upon the
cast. Per MPI-2 4.12.7, use MPI_xxx_GET/SET_ATTR when you need
lossless conversion. */
c_err = MPI_Attr_get(c_comm, OMPI_FINT_2_INT(*keyval),
&value.c_ptr, &c_flag);
c_err = ompi_attr_get_fortran_mpi1(c_comm->c_keyhash,
OMPI_FINT_2_INT(*keyval),
attribute_val,
&c_flag);
*ierr = OMPI_INT_2_FINT(c_err);
*flag = OMPI_INT_2_FINT(c_flag);
/* Note that MPI-2 4.12.7 specifically says that Fortran's
ATTR_GET function will take the address returned from C and
"convert it to an integer". This compliments ATTR_PUT, who,
since we need to save Fortran attributes by value, saves only
the MPI_Fint (regardless of the size of the back-end attribute
storeage). So here we simply extract that MPI_Fint and get the
value back. */
if (MPI_SUCCESS == c_err && 1 == c_flag) {
*attribute_val = value.f_integer;
}
}

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "communicator/communicator.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_ATTR_PUT = mpi_attr_put_f
@ -58,32 +60,17 @@ OMPI_GENERATE_F77_BINDINGS (MPI_ATTR_PUT,
void mpi_attr_put_f(MPI_Fint *comm, MPI_Fint *keyval, MPI_Fint *attribute_val,
MPI_Fint *ierr)
{
MPI_Comm c_comm;
ompi_attribute_fortran_ptr_t convert;
int c_err;
MPI_Comm c_comm = MPI_Comm_f2c(*comm);
c_comm = MPI_Comm_f2c(*comm);
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
/* This stuff is very confusing. Be sure to see MPI-2 4.12.7. */
/* Note that this function deals with attribute values that are
the size of Fortran INTEGERS; the C function MPI_Attr_put deals
with attribute values that are the size of address integers.
Hence, it is possible that the C value is larger than the
Fortran value. MPI says that we sign-extend in this case. */
/* Fortran attributes are integers. So we need to save those by
value -- not by reference. Hence, we don't save the pointer to
the fortran parameter that came in, but rather its dereferenced
value. Assign to the c_ptr member first, filling out the sign
extension. */
if (OMPI_FINT_2_INT(*attribute_val) >= 0) {
convert.c_ptr = (void*) 0;
} else {
convert.c_ptr = (void*) -1;
}
convert.f_integer = *attribute_val;
*ierr = OMPI_INT_2_FINT(MPI_Attr_put(c_comm,
OMPI_FINT_2_INT(*keyval),
convert.c_ptr));
c_err = ompi_attr_set_fortran_mpi1(COMM_ATTR,
c_comm,
&c_comm->c_keyhash,
OMPI_FINT_2_INT(*keyval),
*attribute_val,
false, true);
*ierr = OMPI_INT_2_FINT(c_err);
}

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "communicator/communicator.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_COMM_GET_ATTR = mpi_comm_get_attr_f
@ -56,38 +58,19 @@ OMPI_GENERATE_F77_BINDINGS (MPI_COMM_GET_ATTR,
#endif
void mpi_comm_get_attr_f(MPI_Fint *comm, MPI_Fint *comm_keyval,
MPI_Aint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
MPI_Aint *attribute_val, MPI_Fint *flag,
MPI_Fint *ierr)
{
int c_err, c_flag;
MPI_Comm c_comm;
int *c_value;
MPI_Comm c_comm = MPI_Comm_f2c(*comm);
c_comm = MPI_Comm_f2c(*comm);
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
/* This stuff is very confusing. Be sure to see MPI-2 4.12.7. */
/* Didn't use all the FINT macros that could have prevented a few
extra variables in this function, but I figured that the
clarity of code, and the fact that this is not expected to be a
high-performance function, was worth it */
/* Note that there is no conversion on attribute_val -- MPI-2 says
that it is supposed to be the right size already */
c_err = MPI_Comm_get_attr(c_comm, OMPI_FINT_2_INT(*comm_keyval),
&c_value, &c_flag);
c_err = ompi_attr_get_fortran_mpi2(c_comm->c_keyhash,
OMPI_FINT_2_INT(*comm_keyval),
attribute_val,
&c_flag);
*ierr = OMPI_INT_2_FINT(c_err);
*flag = OMPI_INT_2_FINT(c_flag);
/* Note that MPI-2 4.12.7 specifically says that Fortran's
xxx_GET_ATTR functions will take the address returned from C
and "convert it to an integer". Since we stored the *value* of
the attribute in the corresponding xxx_SET_ATTR function, we
simply cast here to get the value back (remember, MPI
guarantess that xxx_SET_ATTR fortran parameters are the right
size). */
if (MPI_SUCCESS == c_err && 1 == c_flag) {
*attribute_val = (MPI_Aint) c_value;
}
}

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "communicator/communicator.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_COMM_SET_ATTR = mpi_comm_set_attr_f
@ -58,15 +60,17 @@ OMPI_GENERATE_F77_BINDINGS (MPI_COMM_SET_ATTR,
void mpi_comm_set_attr_f(MPI_Fint *comm, MPI_Fint *comm_keyval,
MPI_Aint *attribute_val, MPI_Fint *ierr)
{
int c_err;
MPI_Comm c_comm = MPI_Comm_f2c(*comm);
/* We save fortran attributes by value, so dereference
attribute_val. MPI-2 guarantees that xxx_SET_ATTR will be
called in fortran with an address-sized integer parameter for
the attribute, so there's no need to do any size conversions
before calling the back-end C function. */
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
*ierr = OMPI_INT_2_FINT(MPI_Comm_set_attr(c_comm,
OMPI_FINT_2_INT(*comm_keyval),
(void*) *attribute_val));
c_err = ompi_attr_set_fortran_mpi2(COMM_ATTR,
c_comm,
&c_comm->c_keyhash,
OMPI_FINT_2_INT(*comm_keyval),
*attribute_val,
false, true);
*ierr = OMPI_INT_2_FINT(c_err);
}

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

@ -77,7 +77,7 @@ void mpi_keyval_create_f(ompi_mpi1_fortran_copy_attr_function* copy_attr_fn,
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, del_fn,
keyval, extra_state,
OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_OLD);
OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_MPI1);
if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "datatype/datatype.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_TYPE_GET_ATTR = mpi_type_get_attr_f
@ -56,38 +58,19 @@ OMPI_GENERATE_F77_BINDINGS (MPI_TYPE_GET_ATTR,
#endif
void mpi_type_get_attr_f(MPI_Fint *type, MPI_Fint *type_keyval,
MPI_Aint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
MPI_Aint *attribute_val, MPI_Fint *flag,
MPI_Fint *ierr)
{
int c_err, c_flag;
MPI_Datatype c_type;
int *c_value;
MPI_Datatype c_type = MPI_Type_f2c(*type);
c_type = MPI_Type_f2c(*type);
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
/* This stuff is very confusing. Be sure to see MPI-2 4.12.7. */
/* Didn't use all the FINT macros that could have prevented a few
extra variables in this function, but I figured that the
clarity of code, and the fact that this is not expected to be a
high-performance function, was worth it */
/* Note that there is no conversion on attribute_val -- MPI-2 says
that it is supposed to be the right size already */
c_err = MPI_Type_get_attr(c_type, OMPI_FINT_2_INT(*type_keyval),
&c_value, &c_flag);
c_err = ompi_attr_get_fortran_mpi2(c_type->d_keyhash,
OMPI_FINT_2_INT(*type_keyval),
attribute_val,
&c_flag);
*ierr = OMPI_INT_2_FINT(c_err);
*flag = OMPI_INT_2_FINT(c_flag);
/* Note that MPI-2 4.12.7 specifically says that Fortran's
xxx_GET_ATTR functions will take the address returned from C
and "convert it to an integer". Since we stored the *value* of
the attribute in the corresponding xxx_SET_ATTR function, we
simply cast here to get the value back (remember, MPI
guarantess that xxx_SET_ATTR fortran parameters are the right
size). */
if (MPI_SUCCESS == c_err && 1 == c_flag) {
*attribute_val = (MPI_Aint) c_value;
}
}

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "datatype/datatype.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_TYPE_SET_ATTR = mpi_type_set_attr_f
@ -55,17 +57,19 @@ OMPI_GENERATE_F77_BINDINGS (MPI_TYPE_SET_ATTR,
#include "mpi/f77/profile/defines.h"
#endif
void mpi_type_set_attr_f(MPI_Fint *type, MPI_Fint *type_keyval, MPI_Aint *attr_val, MPI_Fint *ierr)
void mpi_type_set_attr_f(MPI_Fint *type, MPI_Fint *type_keyval, MPI_Aint *attribute_val, MPI_Fint *ierr)
{
MPI_Datatype c_type = MPI_Type_f2c( *type );
int c_err;
MPI_Datatype c_type = MPI_Type_f2c(*type);
/* We save fortran attributes by value, so dereference
attribute_val. MPI-2 guarantees that xxx_SET_ATTR will be
called in fortran with an address-sized integer parameter for
the attribute, so there's no need to do any size conversions
before calling the back-end C function. */
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
*ierr = OMPI_INT_2_FINT(MPI_Type_set_attr( c_type,
OMPI_FINT_2_INT(*type_keyval),
(void*) *attr_val ));
c_err = ompi_attr_set_fortran_mpi2(TYPE_ATTR,
c_type,
&c_type->d_keyhash,
OMPI_FINT_2_INT(*type_keyval),
*attribute_val,
false, true);
*ierr = OMPI_INT_2_FINT(c_err);
}

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

@ -17,6 +17,8 @@
#include "ompi_config.h"
#include "mpi/f77/bindings.h"
#include "attribute/attribute.h"
#include "win/win.h"
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
#pragma weak PMPI_WIN_GET_ATTR = mpi_win_get_attr_f
@ -59,35 +61,15 @@ void mpi_win_get_attr_f(MPI_Fint *win, MPI_Fint *win_keyval,
MPI_Aint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
{
int c_err, c_flag;
MPI_Win c_win;
int *c_value;
MPI_Win c_win = MPI_Win_f2c(*win);
c_win = MPI_Win_f2c(*win);
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
/* This stuff is very confusing. Be sure to see MPI-2 4.12.7. */
/* Didn't use all the FINT macros that could have prevented a few
extra variables in this function, but I figured that the
clarity of code, and the fact that this is not expected to be a
high-performance function, was worth it */
/* Note that there is no conversion on attribute_val -- MPI-2 says
that it is supposed to be the right size already */
c_err = MPI_Win_get_attr(c_win, OMPI_FINT_2_INT(*win_keyval),
&c_value, &c_flag);
c_err = ompi_attr_get_fortran_mpi2(c_win->w_keyhash,
OMPI_FINT_2_INT(*keyhash),
attribute_val,
&c_flag)
*ierr = OMPI_INT_2_FINT(c_err);
*flag = OMPI_INT_2_FINT(c_flag);
/* Note that MPI-2 4.12.7 specifically says that Fortran's
xxx_GET_ATTR functions will take the address returned from C
and "convert it to an integer" Since we stored the *value* of
the attribute in the corresponding xxx_SET_ATTR function, we
simply cast here to get the value back (remember, MPI
guarantess that xxx_SET_ATTR fortran parameters are the right
size). */
if (MPI_SUCCESS == c_err && 1 == c_flag) {
*attribute_val = (MPI_Aint) c_value;
}
}

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

@ -58,15 +58,17 @@ OMPI_GENERATE_F77_BINDINGS (MPI_WIN_SET_ATTR,
void mpi_win_set_attr_f(MPI_Fint *win, MPI_Fint *win_keyval,
MPI_Aint *attribute_val, MPI_Fint *ierr)
{
MPI_Win c_win = MPI_Win_f2c( *win );
int c_err;
MPI_Win c_win = MPI_Win_f2c(*win);
/* We save fortran attributes by value, so dereference
attribute_val. MPI-2 guarantees that xxx_SET_ATTR will be
called in fortran with an address-sized integer parameter for
the attribute, so there's no need to do any size conversions
before calling the back-end C function. */
/* This stuff is very confusing. Be sure to see the comment at
the top of src/attributes/attributes.c. */
*ierr = OMPI_INT_2_FINT(MPI_Win_set_attr( c_win,
OMPI_FINT_2_INT(*win_keyval),
(void*) *attribute_val ));
c_err = ompi_attr_set_fortran_mpi2(WIN_ATTR,
c_win,
&c_win->w_keyhash,
OMPI_FINT_2_INT(*win_keyval),
*attribute_val,
false, true);
*ierr = OMPI_INT_2_FINT(c_err);
}