Skip to content
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

ompi_mpi_init: fix race condition #5234

Merged
merged 2 commits into from
Jun 6, 2018

Conversation

jsquyres
Copy link
Member

@jsquyres jsquyres commented Jun 6, 2018

There was a race condition in 35438ae: if multiple threads invoked
ompi_mpi_init() simultaneously (which could happen from both MPI and
OSHMEM), the code did not catch this condition -- Bad Things would
happen.

Now use an atomic cmp/set to ensure that only one thread is able to
advance ompi_mpi_init from NOT_INITIALIZED to INIT_STARTED.

Additionally, change the prototype of ompi_mpi_init() so that
oshmem_init() can safely invoke ompi_mpi_init() multiple times (as
long as MPI_FINALIZE has not started) without displaying an error. If
multiple threads invoke oshmem_init() simultaneously, one of them will
actually do the initialization, and the rest will loop waiting for it
to complete.

Signed-off-by: Jeff Squyres jsquyres@cisco.com

There was a race condition in 35438ae: if multiple threads invoked
ompi_mpi_init() simultaneously (which could happen from both MPI and
OSHMEM), the code did not catch this condition -- Bad Things would
happen.

Now use an atomic cmp/set to ensure that only one thread is able to
advance ompi_mpi_init from NOT_INITIALIZED to INIT_STARTED.

Additionally, change the prototype of ompi_mpi_init() so that
oshmem_init() can safely invoke ompi_mpi_init() multiple times (as
long as MPI_FINALIZE has not started) without displaying an error.  If
multiple threads invoke oshmem_init() simultaneously, one of them will
actually do the initialization, and the rest will loop waiting for it
to complete.

Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
// silently return successfully.
if (reinit_ok) {
return MPI_SUCCESS;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't the threads that failed to initialize expected to wait until the one that is currently doing the init succesfully complete the initialization ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put that check in oshmem_shmem_init() (vs. here). I guess it's better to move it here.

Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
@bosilca
Copy link
Member

bosilca commented Jun 6, 2018

Thanks @jsquyres

@bosilca bosilca merged commit fa13867 into open-mpi:master Jun 6, 2018
@jsquyres
Copy link
Member Author

jsquyres commented Jun 6, 2018

Blarg. You merged before I squashed. 😦

@jsquyres jsquyres deleted the pr/oshmem-init-race branch June 6, 2018 16:28
@bosilca
Copy link
Member

bosilca commented Jun 6, 2018

sorry, I thought we were done with the discussion, and the patch was looking good.

// did that, and we should return.
if (expected >= OMPI_MPI_STATE_FINALIZE_STARTED) {
opal_show_help("help-mpi-runtime.txt",
"mpi_init: already finalized", true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsquyres @bosilca Does that mean that one application is only allowed to call MPI_Init/Finalize sequence once?
I thought that, in general, it is ok to do that multiple times.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would be heresy ;)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct: MPI defines that you are only allowed to call MPI_INIT / MPI_FINALIZE once.

We added this ompi_mpi_init() ability to "re-init" just for OSHMEM (I put it in quotes because it's not actually re-initializing -- it's just returning safely if MPI is already initialized... but not yet finalized).

But we can't help you if MPI has already been finalized -- there's way too much infrastructure that has been shut down, and ompi_mpi_init() was not designed to actually re-initialize. MPI sessions may change this reality, but that's still a ways off. And definitely outside the scope of this PR. 😄

// silently return successfully once the initializing
// thread has completed.
if (reinit_ok) {
while (ompi_mpi_state < OMPI_MPI_STATE_INIT_COMPLETED) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a read memory barrier here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ompi_mpi_state is volatile and we are using a usleep(1). I don't think the rmb would be necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And there was a write memory barrier every time we wrote to ompi_mpi_state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants