Skip to content

add support for request_get_status_any/all/some #13279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@ OMPI_MAN3 = \
MPI_Request_f2c.3 \
MPI_Request_free.3 \
MPI_Request_get_status.3 \
MPI_Request_get_status_all.3 \
MPI_Request_get_status_any.3 \
MPI_Request_get_status_some.3 \
MPI_Rget.3 \
MPI_Rget_accumulate.3 \
MPI_Rput.3 \
Expand Down
48 changes: 48 additions & 0 deletions docs/man-openmpi/man3/MPI_Request_get_status_all.3.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.. _mpi_request_get_status_all:


MPI_Request_get_status_all
==========================

.. include_body

:ref:`MPI_Request_get_status_all` |mdash| Access information associated with a
request without freeing the request.

.. The following file was automatically generated
.. include:: ./bindings/mpi_request_get_status_all.rst

INPUT PARAMETER
---------------
* ``count``: List length (non-negative integer)
* ``array_of_requests``: Array of requests (array of handles).

OUTPUT PARAMETERS
-----------------
* ``flag``: Boolean flag, same as from :ref:`MPI_Test` (logical).
* ``array_of_statuses``: Array of ``MPI_Status`` objects if flag is true (array of status).
* ``ierror``: Fortran only: Error status (integer).

DESCRIPTION
-----------

:ref:`MPI_Request_get_status_all` sets ``flag = true`` if all
operations associated with *active* handles in the array have completed.
In this case, each status entry that corresponds to an active request
is set to the status of the corresponding operation. It
does not deallocate or deactivate the request; a subsequent call to
test, wait, or free should be executed with each of those requests.

Each status entry that corresponds to a null or inactive handle is set
to empty. Otherwise, ``flag = false`` is returned and the values of the
status entries are undefined.

If your application does not need to examine the *status* field, you can
save resources by using the predefined constant ``MPI_STATUS_IGNORE`` as a
special value for the ``array_of_statuses`` argument.


ERRORS
------

.. include:: ./ERRORS.rst
53 changes: 53 additions & 0 deletions docs/man-openmpi/man3/MPI_Request_get_status_any.3.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.. _mpi_request_get_status_any:


MPI_Request_get_status_any
==========================

.. include_body

:ref:`MPI_Request_get_status_any` |mdash| Access information associated with a
request without freeing the request.

.. The following file was automatically generated
.. include:: ./bindings/mpi_request_get_status_any.rst

INPUT PARAMETER
---------------
* ``count``: List length (non-negative integer)
* ``array_of_requests``: Array of requests (array of handles).

OUTPUT PARAMETERS
-----------------
* ``index``: Index of operation that completed (integer).
* ``flag``: Boolean flag, same as from :ref:`MPI_Test` (logical).
* ``status``: ``MPI_Status`` object if flag is true (status).
* ``ierror``: Fortran only: Error status (integer).

DESCRIPTION
-----------

:ref:`MPI_Request_get_status_any` sets ``flag = true`` if either one
of the operations associated with active handles has completed. In
this case it returns in ``index`` the index of this request in the
array and the status of the operation in ``status``. It does not
deallocate or deactivate the request; a subsequent call to test, wait,
or free should be executed with that request.

If no operation completed, it returns ``flag = false`` and a value of
``MPI_UNDEFINED`` in ``index``. ``status`` is undefined in this
scenario.

If ``array_of_requests`` contains no active handles then the call
returns immediately with ``flag = true``, ``index = MPI_UNDEFINED``,
and an empty status.

If your application does not need to examine the *status* field, you can
save resources by using the predefined constant ``MPI_STATUS_IGNORE`` as a
special value for the ``status`` argument.


ERRORS
------

.. include:: ./ERRORS.rst
52 changes: 52 additions & 0 deletions docs/man-openmpi/man3/MPI_Request_get_status_some.3.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.. _mpi_request_get_status_some:


MPI_Request_get_status_some
===========================

.. include_body

:ref:`MPI_Request_get_status_some` |mdash| Access information associated with a
request without freeing the request.

.. The following file was automatically generated
.. include:: ./bindings/mpi_request_get_status_some.rst

INPUT PARAMETER
---------------
* ``incount``: List length (non-negative integer).
* ``array_of_requests``: Array of requests (array of handles).

OUTPUT PARAMETERS
-----------------
* ``outcount``: Number of completed requests (integer).
* ``array_of_indices``: Array of indices of operations that completed (array of integers).
* ``array_of_statuses``: Array of ``MPI_Status`` objects for operations that completed (array of status).
* ``ierror``: Fortran only: Error status (integer).

DESCRIPTION
-----------

:ref:`MPI_Request_get_status_some` returns in outcount the number of
requests from the list ``array_of_requests`` that have completed. The
first ``outcount`` locations of the array ``array_of_indices`` and
``array_of_statuses`` will contain the indices of the operations
within the array ``array_of_requests`` and the status of these
operations respectively. The array is indexed from zero in C and from
one in Fortran. It does not deallocate or deactivate the request; a
subsequent call to test, wait, or free should be executed with each completed
request.

If no operation in ``array_of_requests`` is complete, it returns
``outcount = 0``. If all operations in ``array_of_requests`` are either
``MPI_REQUEST_NULL`` or inactive, ``outcount`` will be set to ``MPI_UNDEFINED``.

If your application does not need to examine the *status* field, you can
save resources by using the predefined constant ``MPI_STATUS_IGNORE`` as a
special value for the ``array_of_statuses`` argument.


ERRORS
------

.. include:: ./ERRORS.rst
3 changes: 3 additions & 0 deletions docs/man-openmpi/man3/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ MPI API manual pages (section 3)
MPI_Request_f2c.3.rst
MPI_Request_free.3.rst
MPI_Request_get_status.3.rst
MPI_Request_get_status_all.3.rst
MPI_Request_get_status_any.3.rst
MPI_Request_get_status_some.3.rst
MPI_Rget.3.rst
MPI_Rget_accumulate.3.rst
MPI_Rput.3.rst
Expand Down
18 changes: 18 additions & 0 deletions ompi/include/mpi.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,15 @@ OMPI_DECLSPEC MPI_Request MPI_Request_f2c(MPI_Fint request);
OMPI_DECLSPEC int MPI_Request_free(MPI_Request *request);
OMPI_DECLSPEC int MPI_Request_get_status(MPI_Request request, int *flag,
MPI_Status *status);
/* should be 'const MPI_Request array_of_requests[]' */
OMPI_DECLSPEC int MPI_Request_get_status_all(int count, const MPI_Request array_of_requests[], int *flag,
MPI_Status array_of_statuses[]);
/* should be 'const MPI_Request array_of_requests[]' */
OMPI_DECLSPEC int MPI_Request_get_status_any(int count, const MPI_Request array_of_requests[], int *index,
int *flag, MPI_Status *status);
/* should be 'const MPI_Request array_of_requests[]' */
OMPI_DECLSPEC int MPI_Request_get_status_some(int incount, const MPI_Request array_of_requests[], int *outcount,
int array_of_indices[], MPI_Status array_of_statuses[]);
OMPI_DECLSPEC int MPI_Rget(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype,
MPI_Win win, MPI_Request *request);
Expand Down Expand Up @@ -3385,6 +3394,15 @@ OMPI_DECLSPEC MPI_Request PMPI_Request_f2c(MPI_Fint request);
OMPI_DECLSPEC int PMPI_Request_free(MPI_Request *request);
OMPI_DECLSPEC int PMPI_Request_get_status(MPI_Request request, int *flag,
MPI_Status *status);
/* should be 'const MPI_Request array_of_requests[]' */
OMPI_DECLSPEC int PMPI_Request_get_status_all(int count, const MPI_Request array_of_requests[], int *flag,
MPI_Status array_of_statuses[]);
/* should be 'const MPI_Request array_of_requests[]' */
OMPI_DECLSPEC int PMPI_Request_get_status_any(int count, const MPI_Request array_of_requests[], int *index,
int *flag, MPI_Status *status);
/* should be 'const MPI_Request array_of_requests[]' */
OMPI_DECLSPEC int PMPI_Request_get_status_some(int incount, const MPI_Request array_of_requests[], int *outcount,
int array_of_indices[], MPI_Status array_of_statuses[]);
OMPI_DECLSPEC int PMPI_Rget(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype,
MPI_Win win, MPI_Request *request);
Expand Down
27 changes: 25 additions & 2 deletions ompi/mpi/bindings/ompi_bindings/c_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,38 @@ def type_text(self, enable_count=False):
def argument(self):
return f'(MPI_Request) {self.name}'

@Type.add_type('REQUEST_CONST', abi_type=['ompi'])
class TypeConstRequest(TypeRequest):

def type_text(self, enable_count=False):
return f'const MPI_Request *'

def parameter(self, enable_count=False, **kwargs):
if self.count_param is None:
return f'const MPI_Request {self.name}'
else:
return f'const MPI_Request {self.name}[]'

#
# TODO ABI NEEDS WORK
#
@Type.add_type('REQUEST_CONST', abi_type=['standard'])
class TypeConstRequestStandard(TypeRequestStandard):

def type_text(self, enable_count=False):
name = self.mangle_name('MPI_Request')
return f'const {name}'

@property
def argument(self):
return f'(MPI_Request) {self.name}'

@Type.add_type('REQUEST_INOUT', abi_type=['ompi'])
class TypeRequestInOut(Type):

def type_text(self, enable_count=False):
return 'MPI_Request *'


@Type.add_type('REQUEST_INOUT', abi_type=['standard'])
class TypeRequestInOutStandard(Type):

Expand Down Expand Up @@ -593,7 +617,6 @@ def parameter(self, enable_count=False, **kwargs):
else:
return f'{type_name} {self.name}[]'


@Type.add_type('STATUS', abi_type=['ompi'])
class TypeStatus(Type):

Expand Down
3 changes: 3 additions & 0 deletions ompi/mpi/c/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ prototype_sources = \
request_f2c.c.in \
request_free.c.in \
request_get_status.c.in \
request_get_status_all.c.in \
request_get_status_any.c.in \
request_get_status_some.c.in \
rget_accumulate.c.in \
rget.c.in \
rput.c.in \
Expand Down
131 changes: 131 additions & 0 deletions ompi/mpi/c/request_get_status_all.c.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2021 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006-2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2015 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2024 Triad National Security, LLC. All rights
* reserved.
* Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>

#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/request/request.h"
#include "ompi/request/grequest.h"
#include "ompi/memchecker.h"

/* Non blocking test for the request status. Upon completion, the request will
* not be freed (unlike the test function). A subsequent call to test, wait
* or free should be executed on the request.
*/
PROTOTYPE ERROR_CLASS request_get_status_all(INT count, REQUEST_CONST requests:count, INT_OUT flag,
STATUS_OUT statuses:count)
{
MEMCHECKER(
int j;
for (j = 0; j< count; j++) {
memchecker_request(&requests[j]);
}
);

if( MPI_PARAM_CHECK ) {
int rc = MPI_SUCCESS;

OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (NULL == requests) {
rc = MPI_ERR_REQUEST;
} else {
if(!ompi_request_check_same_instance((MPI_Request *)requests, count) ) {
rc = MPI_ERR_REQUEST;
}
}
if ((NULL == flag) || (count < 0)) {
rc = MPI_ERR_ARG;
}
OMPI_ERRHANDLER_NOHANDLE_CHECK(rc, rc, FUNC_NAME);
}

if (OPAL_UNLIKELY(0 == count)) {
*flag = true;
return MPI_SUCCESS;
}

bool all_done;
bool one_done;

#if OPAL_ENABLE_PROGRESS_THREADS == 0
int do_it_once = 0;
recheck_request_status:
#endif

opal_atomic_mb();
int i;
all_done = true;
for (i = 0; i < count; i++) {
one_done = false;
if( (requests[i] == MPI_REQUEST_NULL) || (requests[i]->req_state == OMPI_REQUEST_INACTIVE) ||
(requests[i]->req_complete) ) {
continue;
}
if (!one_done) {
all_done = false;
break;
}
}

if (!all_done) {
#if OPAL_ENABLE_PROGRESS_THREADS == 0
if( 0 == do_it_once ) {
/* If we run the opal_progress then check the status of the
request before leaving. We will call the opal_progress only
once per call. */
opal_progress();
do_it_once++;
goto recheck_request_status;
}
#endif
*flag = false;
return MPI_SUCCESS;
}

for (i = 0; i < count; i++) {
if( (requests[i] == MPI_REQUEST_NULL) || (requests[i]->req_state == OMPI_REQUEST_INACTIVE) ) {
if (MPI_STATUS_IGNORE != statuses) {
OMPI_COPY_STATUS(&statuses[i], ompi_status_empty, false);
}
}
if (requests[i]->req_complete ) {
/* If this is a generalized request, we *always* have to call
the query function to get the status (MPI-2:8.2), even if
the user passed STATUS_IGNORE. */
if (OMPI_REQUEST_GEN == requests[i]->req_type) {
ompi_grequest_invoke_query(requests[i], &requests[i]->req_status);
}
if (MPI_STATUS_IGNORE != statuses) {
OMPI_COPY_STATUS(&statuses[i], requests[i]->req_status, false);
}
}
}

*flag = true;
return MPI_SUCCESS;
}
Loading