Fix for GPU-aware MPI bug#1595
Conversation
| tioga-rocmcc_6_3_1_hip-gpu-aware-src: | ||
| variables: | ||
| COMPILER: "rocmcc@6.3.1_hip" | ||
| HOST_CONFIG: "tioga-toss_4_x86_64_ib_cray-${COMPILER}.cmake" | ||
| ALLOC_TIME: "60" | ||
| NUM_NODES: "2" | ||
| extends: .src_build_on_tioga | ||
| before_script: | ||
| - module load cmake/3.21.1 | ||
| - export MPICH_GPU_SUPPORT_ENABLED=1 |
There was a problem hiding this comment.
This is the CI job I added to replicate the failure. Notably this does require more than one node (2) allocation to reproduce the error.
My concern is there are only 4 nodes in the special partition CI queue: https://lc.llnl.gov/confluence/spaces/GITLAB/pages/785285769/Special+partitions+for+CI+batch+jobs, so adding this job will make an entire CI run take up most of the queue.
I am leaning towards removing the additional CI job from this PR for that reason.
There was a problem hiding this comment.
@bmhan12 can you reproduce the error on two nodes? If so, then maybe we can re-enable the test when we move our CI off tioga to tuolumne where there may be more nodes available for CI. Hopefully, the issue will be fixed in Cray mpich -- I believe Guy submitted an issue with a reproducer that doesn't rely on Axom. Alternatively, we could try to modify the Lumberjack implementation that is causing the issue.
There was a problem hiding this comment.
Yes, I was able reproduce the error with two nodes, and the workaround in this PR resolves the issue in Lumberjack. That's a good point, I could comment out this job, and move it to tuolumne once we're setup there.
However, from what I can see here: https://lc.llnl.gov/confluence/spaces/GITLAB/pages/785285769/Special+partitions+for+CI+batch+jobs
tuolumne will also only have 4 nodes in the CI queue (and I verified with sinfo that is in fact the case on the machine), which seems small relative to the total overall number of nodes.
There was a problem hiding this comment.
We may be able to get LC to bump the number of CI nodes.
There was a problem hiding this comment.
Commented out the GPI-aware MPI job for now.
| const char* const zeroMessage = "0"; | ||
| // GPU-aware MPI issue: | ||
| // https://rzlc.llnl.gov/jira/browse/ELCAP-851 | ||
| // const char * zeroMessage = "0"; |
There was a problem hiding this comment.
Is the idea that this will be reverted when it's fixed? If so, we should have a comment here to go delete the added lines.
There was a problem hiding this comment.
If it were reverted, then it would cause variable shadowing with line 365 below.
There was a problem hiding this comment.
Right, hence the desire for a comment =) I was assuming the reverting would also remove the added lines and a comment would stop that hopefully.
There was a problem hiding this comment.
Is the idea that this will be reverted when it's fixed? If so, we should have a comment here to go delete the added lines.
I'm not sure what the cleanest way to organize this, so it is definitely messy.
Right now from the JIRA ticket discussion, I'm not sure if the problem that is causing this will get fixed soon or if the workaround is just the new reality.
Additionally, more importantly, I would like to preserve the comment above about zeroMessage :
/*!
*****************************************************************************
* \brief Message to indicate no messages need to be sent from child node.
*****************************************************************************
*/
but without a snippet/comment block/??? it doesn't really make any sense by itself.
Maybe it would be better to have this comment for every zeroMessage variable?
There was a problem hiding this comment.
Changed it to comment per zeroMessage declaration.
| * \brief Message to indicate no messages need to be sent from child node. | ||
| ***************************************************************************** | ||
| */ | ||
| const char* const zeroMessage = "0"; |
There was a problem hiding this comment.
If I'm understanding the issue properly, would another possible fix be to keep the global variable zeroMessage as is, but copy it to a local variable before each usage?
(Not necessarily requesting any changes, just trying to understand the issue).
There was a problem hiding this comment.
Yes, that should work, and the local variable should be a char array instead of a pointer (Following this bulletpoint from the JIRA ticket: use local variables (although for the CHAR type, local constant needs to be a char array))
There was a problem hiding this comment.
Would it make sense to still have this pointer but point it to the storage that was added in Message.cpp with the same name? That way there is only one place that this is stored.
There was a problem hiding this comment.
Would it make sense to still have this pointer but point it to the storage that was added in Message.cpp with the same name? That way there is only one place that this is stored.
I'll give this a try.
Based on previous discussion from yesterday, this current iteration has zeroMessage be a function that returns a std::string.
There was a problem hiding this comment.
I tried the following:
// Message.hpp
extern const char * zeroMessage;
---------------------------------------------------------
// Message.cpp
const char * zeroMessage = "0";
The same bug appears in this case. (Code-wise, I'm not sure if this is what you had in mind, if so, let me know!)
There was a problem hiding this comment.
I was thinking something more like this.
// Message.hpp
extern const char * const zeroMessage;
---------------------------------------------------------
// Message.cpp
char zeroMessageStorage[] = "0";
const char * const zeroMessage = zeroMessageStorage;
There was a problem hiding this comment.
You could also use a std::array<char, 2> zeroMessage{"0"}; instead of a std::string to make it easy to make a local copy. Then use zeroMessage.data() when you need the pointer.
There was a problem hiding this comment.
I was thinking something more like this.
Thanks @MrBurmark, that works and is pretty clean!
|
@MrBurmark please take a look at this and offer suggestions/corrections, etc. |
…ocation in packMessages for the case of a message of size 0 (zeroMessage is not in static storage)
| // Allocate space for zero and null character | ||
| char* zeroString = new char[zeroMessage().size() + 1]; | ||
| std::memcpy(zeroString, zeroMessage().c_str(), zeroMessage().size()); | ||
| zeroString[zeroMessage().size()] = '\0'; | ||
| return zeroString; |
There was a problem hiding this comment.
@bmhan12 -- looks like this will leak memory each time it's called.
Can zeroMessage == "0" be a class member of Message? (or even better, a static class member?)
There was a problem hiding this comment.
Also, we probably don't want an allocation each time this is called with no messages.
kennyweiss
left a comment
There was a problem hiding this comment.
Thanks @bmhan12 and @MrBurmark for working through this -- this is a nice solution
|
|
||
| // Global workaround: https://rzlc.llnl.gov/jira/browse/ELCAP-851 | ||
| char zeroMessageStorage[] = "0"; | ||
| const char* const zeroMessage = zeroMessageStorage; |
There was a problem hiding this comment.
Aren't you still treating zeroMessage as global data in this case? If I remember correctly, that was the main issue stated later in the ticket.
There was a problem hiding this comment.
Aren't you still treating zeroMessage as global data in this case? If I remember correctly, that was the main issue stated later in the ticket.
I think we're still hitting one of the working cases in this scenario: "use global non-constant (for CHAR type this has to be either a char array or a pointer to malloc'ed memory)".
There was a problem hiding this comment.
My understanding is that global constants and global non-constants are put in different sections of memory with different permissions. So it may only be the case that global constants are affected but global non-constants are not.
This PR:
- (Tentatively?) Added a CI job on tioga that replicates the bug conditions. Job run illustrating the bug: https://lc.llnl.gov/gitlab/axom/axom/-/jobs/2706859