Repository navigation
test(rccl): add host microtests for the GIN host proxy #13596
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
Merged
aduforest
merged 21 commits into
develop
from
users/aduforest/aicomrccl-2807-gin-host-proxy-host-microtests
Oct 26, 2026
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
c6fe342
test(rccl): add host microtests for the GIN host proxy
aduforest 53517f8
test(rccl): address ARGUS review of the GIN host proxy microtests
aduforest ce9ba3c
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest 488dabe
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest 7c99f7c
test(rccl): guard the GIN DMA-BUF export fake and tests on HIP >= 7.0
aduforest 84d01cb
test(rccl): link the shared HIP and logging fakes into the GIN host p…
aduforest caa3d4a
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest c754099
test(rccl): move the DMA-BUF export hook next to the other export sea…
aduforest a1d0df3
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest dfbfcd9
test(rccl): host-only suites declare num_gpus 0
aduforest 12c7fdd
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest af1169b
test(rccl): address review on the GIN host proxy microtests
aduforest 37937e7
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest 842d79e
test(rccl): GIN host proxy microtests per review
aduforest 2f5d178
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest b4fddeb
test(rccl): free what a failed GIN proxy CreateContext leaves behind …
aduforest d03e8e7
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest 1045a3e
test(rccl): turn Won't Do bug pins into plain tests (pre-merge harden…
aduforest edb6f7f
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest 87935e0
test(rccl): leave ci-precheckin.json to the CI owners
aduforest a4c3914
Merge remote-tracking branch 'origin/develop' into users/aduforest/ai…
aduforest File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,256 @@ | ||
| /************************************************************************* | ||
| * Copyright (c) 2026 Advanced Micro Devices, Inc. All rights reserved. | ||
| * | ||
| * See LICENSE.txt for license information | ||
| ************************************************************************/ | ||
|
|
||
| // One scripted ncclRma_t vtable for the host microtests that drive an RMA plugin. Every entry point records | ||
| // its arguments and returns its *Result knob; gin-host-proxy-test.cc is the first user. | ||
|
|
||
| #ifndef RCCL_TEST_HOST_RMA_VTABLE_FAKE_H_ | ||
| #define RCCL_TEST_HOST_RMA_VTABLE_FAKE_H_ | ||
|
|
||
| #include <cstdint> | ||
| #include <cstring> | ||
| #include <deque> | ||
| #include <set> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include "nccl.h" | ||
| #include "plugin/nccl_rma.h" | ||
|
|
||
| struct FakeRmaVtable { | ||
| // The handles the plugin hands out. | ||
| static inline void* const kListenComm = reinterpret_cast<void*>(0x20); | ||
| static inline void* const kCollComm = reinterpret_cast<void*>(0x30); | ||
| static inline void* const kRmaCtx = reinterpret_cast<void*>(0x40); | ||
|
|
||
| struct MrReg { | ||
| void* collComm; | ||
| void* addr; | ||
| size_t size; | ||
| int type; | ||
| uint64_t mrFlags; | ||
| int fd; // -1 for a plain registration | ||
| void* mhandle; | ||
| }; | ||
|
|
||
| struct Op { | ||
| char kind; // 'p' iput, 's' iputSignal, 'g' iget, 'f' iflush | ||
| void* rmaCtx; | ||
| int context; | ||
| uint64_t srcOff; | ||
| void* srcHandle; | ||
| size_t size; | ||
| uint64_t dstOff; | ||
| void* dstHandle; | ||
| uint32_t rank; | ||
| uint64_t signalOff; | ||
| void* signalHandle; | ||
| uint64_t signalValue; | ||
| uint32_t signalOp; | ||
| bool isStrong; | ||
| uint32_t optFlags; | ||
| void* request; | ||
| }; | ||
|
|
||
| int maxRecvs = 1; | ||
| int ptrSupport = NCCL_PTR_HOST | NCCL_PTR_CUDA; | ||
| bool flushesAll = false; | ||
| bool pluginHasError = false; | ||
| bool flushReturnsNullRequest = false; | ||
| ncclResult_t listenResult = ncclSuccess, connectResult = ncclSuccess, getPropertiesResult = ncclSuccess, | ||
| closeListenResult = ncclSuccess, closeCollResult = ncclSuccess, createContextResult = ncclSuccess, | ||
| destroyContextResult = ncclSuccess, getRmaPropertiesResult = ncclSuccess, regMrSymResult = ncclSuccess, | ||
| deregMrSymResult = ncclSuccess, opResult = ncclSuccess, testResult = ncclSuccess, | ||
| queryLastErrorResult = ncclSuccess; | ||
| std::deque<ncclResult_t> regMrSymDmaBufResults; // empty means success | ||
|
|
||
| int listenDev = -1; | ||
| void* listenHandle = nullptr; | ||
| void* connectListenComm = nullptr; | ||
| int connectNranks = -1, connectRank = -1; | ||
| int getPropertiesDev = -1; | ||
| std::vector<void*> closedListens, closedColls, destroyedContexts, progressed, queried, tested; | ||
| ncclRmaConfig_t createConfig{}; | ||
| std::vector<MrReg> regs; | ||
| std::vector<std::pair<void*, void*>> deregs; | ||
| std::vector<Op> ops; | ||
| std::set<void*> done; | ||
|
|
||
| ncclRma_t vtable{}; | ||
|
|
||
| static FakeRmaVtable*& currentPtr() { | ||
| static FakeRmaVtable* p = nullptr; | ||
| return p; | ||
| } | ||
| static FakeRmaVtable& current() { return *currentPtr(); } | ||
| static void setCurrent(FakeRmaVtable* p) { currentPtr() = p; } | ||
|
|
||
| static ncclResult_t Init(void**, uint64_t, ncclDebugLogger_t) { return ncclSuccess; } | ||
| static ncclResult_t Devices(int* ndev) { | ||
| *ndev = 1; | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t Finalize(void*) { return ncclSuccess; } | ||
| static ncclResult_t GetProperties(int dev, ncclNetProperties_t* props) { | ||
| FakeRmaVtable& f = current(); | ||
| f.getPropertiesDev = dev; | ||
| std::memset(props, 0, sizeof(*props)); | ||
| props->maxRecvs = f.maxRecvs; | ||
| props->ptrSupport = f.ptrSupport; | ||
| return f.getPropertiesResult; | ||
| } | ||
| // Entry points taking a collComm reject the proxy's wrapper: the plugin must get its own back. | ||
| static ncclResult_t GetRmaProperties(void* collComm, ncclRmaProperties_t* rmaProps) { | ||
| FakeRmaVtable& f = current(); | ||
| if (collComm != kCollComm) return ncclInternalError; | ||
| rmaProps->flushesAllPutsOnAnySignal = f.flushesAll; | ||
| return f.getRmaPropertiesResult; | ||
| } | ||
| static ncclResult_t Listen(void*, int dev, void* handle, void** listenComm) { | ||
| FakeRmaVtable& f = current(); | ||
| f.listenDev = dev; | ||
| f.listenHandle = handle; | ||
| if (f.listenResult != ncclSuccess) return f.listenResult; | ||
| *listenComm = kListenComm; | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t Connect(void*, void**, int nranks, int rank, void* listenComm, void** collComm) { | ||
| FakeRmaVtable& f = current(); | ||
| f.connectNranks = nranks; | ||
| f.connectRank = rank; | ||
| f.connectListenComm = listenComm; | ||
| if (f.connectResult != ncclSuccess) return f.connectResult; | ||
| *collComm = kCollComm; | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t CreateContext(void* collComm, ncclRmaConfig_t* config, void** rmaCtx) { | ||
| FakeRmaVtable& f = current(); | ||
| if (collComm != kCollComm) return ncclInternalError; | ||
| f.createConfig = *config; | ||
| if (f.createContextResult != ncclSuccess) return f.createContextResult; | ||
| *rmaCtx = kRmaCtx; | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t RegMrSym(void* collComm, void* data, size_t size, int type, uint64_t mrFlags, void** mhandle) { | ||
| FakeRmaVtable& f = current(); | ||
| if (f.regMrSymResult != ncclSuccess) return f.regMrSymResult; | ||
| *mhandle = reinterpret_cast<void*>(0xA000 + f.regs.size()); | ||
| f.regs.push_back({collComm, data, size, type, mrFlags, -1, *mhandle}); | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t RegMrSymDmaBuf(void* collComm, void* data, size_t size, int type, uint64_t offset, int fd, | ||
| uint64_t mrFlags, void** mhandle) { | ||
| FakeRmaVtable& f = current(); | ||
| ncclResult_t res = ncclSuccess; | ||
| if (!f.regMrSymDmaBufResults.empty()) { | ||
| res = f.regMrSymDmaBufResults.front(); | ||
| f.regMrSymDmaBufResults.pop_front(); | ||
| } | ||
| if (offset != 0 || fd < 0) return ncclInternalError; | ||
| if (res != ncclSuccess) return res; | ||
| *mhandle = reinterpret_cast<void*>(0xA000 + f.regs.size()); | ||
| f.regs.push_back({collComm, data, size, type, mrFlags, fd, *mhandle}); | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t DeregMrSym(void* collComm, void* mhandle) { | ||
| FakeRmaVtable& f = current(); | ||
| f.deregs.push_back({collComm, mhandle}); | ||
| return f.deregMrSymResult; | ||
| } | ||
| static ncclResult_t DestroyContext(void* rmaCtx) { | ||
| FakeRmaVtable& f = current(); | ||
| f.destroyedContexts.push_back(rmaCtx); | ||
| return f.destroyContextResult; | ||
| } | ||
| static ncclResult_t CloseColl(void* collComm) { | ||
| FakeRmaVtable& f = current(); | ||
| f.closedColls.push_back(collComm); | ||
| return f.closeCollResult; | ||
| } | ||
| static ncclResult_t CloseListen(void* listenComm) { | ||
| FakeRmaVtable& f = current(); | ||
| f.closedListens.push_back(listenComm); | ||
| return f.closeListenResult; | ||
| } | ||
| static ncclResult_t Submit(Op op, void** request) { | ||
| FakeRmaVtable& f = current(); | ||
| op.request = reinterpret_cast<void*>(0x5000 + f.ops.size()); | ||
| if (op.kind == 'f' && f.flushReturnsNullRequest) op.request = nullptr; | ||
| f.ops.push_back(op); | ||
| if (f.opResult != ncclSuccess) return f.opResult; | ||
| *request = op.request; | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t Iput(void* rmaCtx, int context, uint64_t srcOff, void* srcMhandle, size_t size, uint64_t dstOff, | ||
| void* dstMhandle, uint32_t rank, uint32_t optFlags, void** request) { | ||
| return Submit({'p', rmaCtx, context, srcOff, srcMhandle, size, dstOff, dstMhandle, rank, 0, nullptr, 0, 0, false, | ||
| optFlags, nullptr}, | ||
| request); | ||
| } | ||
| static ncclResult_t IputSignal(void* rmaCtx, int context, uint64_t srcOff, void* srcMhandle, size_t size, | ||
| uint64_t dstOff, void* dstMhandle, uint32_t rank, uint64_t signalOff, | ||
| void* signalMhandle, uint64_t signalValue, uint32_t signalOp, bool isStrongSignal, | ||
| uint32_t optFlags, void** request) { | ||
| return Submit({'s', rmaCtx, context, srcOff, srcMhandle, size, dstOff, dstMhandle, rank, signalOff, signalMhandle, | ||
| signalValue, signalOp, isStrongSignal, optFlags, nullptr}, | ||
| request); | ||
| } | ||
| static ncclResult_t Iget(void* rmaCtx, int context, uint64_t remoteOff, void* remoteMhandle, size_t size, | ||
| uint64_t localOff, void* localMhandle, uint32_t rank, uint32_t optFlags, void** request) { | ||
| return Submit({'g', rmaCtx, context, remoteOff, remoteMhandle, size, localOff, localMhandle, rank, 0, nullptr, 0, | ||
| 0, false, optFlags, nullptr}, | ||
| request); | ||
| } | ||
| static ncclResult_t Iflush(void* rmaCtx, int context, void* mhandle, uint32_t rank, void** request) { | ||
| return Submit({'f', rmaCtx, context, 0, nullptr, 0, 0, mhandle, rank, 0, nullptr, 0, 0, false, 0, nullptr}, | ||
| request); | ||
| } | ||
| static ncclResult_t Test(void* collComm, void* request, int* done) { | ||
| FakeRmaVtable& f = current(); | ||
| f.tested.push_back(request); | ||
| if (collComm != kCollComm) return ncclInternalError; | ||
| if (f.testResult != ncclSuccess) return f.testResult; | ||
| *done = f.done.count(request) ? 1 : 0; | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t RmaProgress(void* rmaCtx) { | ||
| current().progressed.push_back(rmaCtx); | ||
| return ncclSuccess; | ||
| } | ||
| static ncclResult_t QueryLastError(void* rmaCtx, bool* hasError) { | ||
| FakeRmaVtable& f = current(); | ||
| f.queried.push_back(rmaCtx); | ||
| *hasError = f.pluginHasError; | ||
| return f.queryLastErrorResult; | ||
| } | ||
|
|
||
| FakeRmaVtable() { | ||
| vtable.name = "FakeRmaVtable"; | ||
| vtable.init = &Init; | ||
| vtable.devices = &Devices; | ||
| vtable.getRmaProperties = &GetRmaProperties; | ||
| vtable.getProperties = &GetProperties; | ||
| vtable.listen = &Listen; | ||
| vtable.connect = &Connect; | ||
| vtable.createContext = &CreateContext; | ||
| vtable.regMrSym = &RegMrSym; | ||
| vtable.regMrSymDmaBuf = &RegMrSymDmaBuf; | ||
| vtable.deregMrSym = &DeregMrSym; | ||
| vtable.destroyContext = &DestroyContext; | ||
| vtable.closeColl = &CloseColl; | ||
| vtable.closeListen = &CloseListen; | ||
| vtable.iput = &Iput; | ||
| vtable.iputSignal = &IputSignal; | ||
| vtable.iget = &Iget; | ||
| vtable.iflush = &Iflush; | ||
| vtable.test = &Test; | ||
| vtable.rmaProgress = &RmaProgress; | ||
| vtable.queryLastError = &QueryLastError; | ||
| vtable.finalize = &Finalize; | ||
| } | ||
| }; | ||
|
|
||
| #endif // RCCL_TEST_HOST_RMA_VTABLE_FAKE_H_ |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.