[logic-rewrite-hip] Fix memory ordering bug causing HSA_STATUS_ERROR_MEMORY_FAULT on MI300X#292
Open
maarquitos14 wants to merge 1 commit into
Open
Conversation
…MEMORY_FAULT on MI300X
Collaborator
|
Thank you for the analysis and explanation. I browsed the changes. There are some HIP intrinsic functions I am not familiar with. Can the high-level APIs (e.g. atomicCAS) address the issue ? |
Contributor
Author
As far as I know, there is no way to express order and scope in the high-level API: https://rocm.docs.amd.com/projects/HIP/en/latest/how-to/hip_cpp_language_extensions.html#atomic-functions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The benchmark was crashing with HSA_STATUS_ERROR_MEMORY_FAULT on MI300X (gfx942). However, it was running fine on MI250X (gfx90a). According to my investigation, the problem is a missing memory ordering guarantee in the linked-list hash table used by the ReplaceSubgr kernel.
More specifically,
TableInsertwrites a.valusing a plain store, and then publishes a pointer to that entry usingatomicCASon.next.TableLookupfollows the.nextchain, reads.val, and uses it as an index for some global arrays (e.g. fanin0, fanin1). On AMD GPUs,atomicCAShas relaxed memory ordering, which means that it guarantees atomicity of the CAS'd word, but does not order surrounding plain stores. This works for gfx90a because a single kernel runs on a single GCD with a shared L2 cache, so.valstore likely propagates quickly enough that no thread ever observes a wrong value. However, on gfx942, a single kernel can run on up to 8 XCDs, each of them using their own L2. Under this scenario, a thread on one XCD can follow a valid.nextpointer, while.valupdate wasn't propagated yet. The thread reads an unititialized.valand uses it as an array index, causing the memory fault.To confirm the hypothesis above I added some instrumentation and extra checks to the kernel, and found that
.val = -1was read hundreds of times, and later used as an index to the arrays mentioned above. After applying the fix, this never happened in 20+ runs.The fix replaces the relaxed
atomicCASinTableInsertwith a release-CAS (i.e. explicitly use__ATOMIC_RELEASEas order), and replaces plain load of.nextinTableLookupwith acquire-loads (i.e. explicit use of__ATOMIC_ACQUIREas order). Both use__HIP_MEMORY_SCOPE_AGENTas scope, the narrowest scope that covers cross-XCD communication. The release on the CAS ensures all prior stores (including.val) are globally visible before.nextis published. The acquire on the load ensures the reader sees those stores after following.next.__threadfence()was also considered as an alternative, but the release-acquire approach handles this case more efficiently.