Add MSCCLPP user buffer registration APIs and integrate with RCCL (#1477)
* ext-src: add MSCCLPP memory registration APIs * update mem-reg patch with mscclpp helper routine to check if buffer is registered * RCCL integration of MSCCL++ user-buffer registration APIs * only include mscclpp_nccl header if ENABLE_MSCCLPP is defined * ext-src: update mscclpp mem-reg patch * add helper routine to patch * check handle before MSCCL++ deregister * fix typo to replace send buff with recv buff * in case of no mscclpp registration, dduring deRegister call, ont fall back to rccl deRegister which will return an error * Apply suggestions from code review Whitespace suggestions and reducing diffs to avoid future merge conflicts Co-authored-by: corey-derochie-amd <161367113+corey-derochie-amd@users.noreply.github.com> * rename helper functions and change their return type * set RCCL user-buffer registration to occur if attempting MSCCL++ registration with a buffer in managed memory --------- Co-authored-by: isaki001 <Ioannis.Sakiotis@amd.com> Co-authored-by: isaki001 <36317038+isaki001@users.noreply.github.com> Co-authored-by: corey-derochie-amd <161367113+corey-derochie-amd@users.noreply.github.com>
Esse commit está contido em:
@@ -38,6 +38,14 @@ extern "C" {
|
||||
/* See ncclAllGather. */
|
||||
ncclResult_t mscclpp_ncclAllGather(const void* sendbuff, void* recvbuff, size_t sendcount,
|
||||
ncclDataType_t datatype, mscclppComm_t comm, hipStream_t stream);
|
||||
|
||||
ncclResult_t mscclpp_ncclCommRegister(mscclppComm_t comm, void* buff, size_t size, void** handle);
|
||||
|
||||
ncclResult_t mscclpp_ncclCommDeregister(mscclppComm_t comm, void* handle);
|
||||
|
||||
bool mscclpp_BuffIsRegistered(mscclppComm_t comm, const void* buff, size_t count);
|
||||
|
||||
size_t mscclpp_BufferSize(mscclppComm_t comm, void* handle);
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
@@ -524,8 +524,13 @@ ncclResult_t mscclEnqueueCheck(
|
||||
NCCLCHECK(mscclGetCaptureStatus(comm->rank, stream));
|
||||
}
|
||||
|
||||
const bool sendBuffRegistered = mscclpp_BuffIsRegistered(comm->mscclpp_comm, sendBuff, count);
|
||||
const bool recvBuffRegistered = mscclpp_BuffIsRegistered(comm->mscclpp_comm, recvBuff, count);
|
||||
const bool graphMode = threadLocalStatus.captureStatus != mscclNoCapture;
|
||||
const bool buffsRegistedNonGraphMode = !graphMode && sendBuffRegistered && recvBuffRegistered;
|
||||
|
||||
/* check if one rank per GPU and graph mode is enabled */
|
||||
if ((threadLocalStatus.captureStatus != mscclNoCapture) && comm->mscclCompatible && nBytes > 0 && (nBytes & 31) == 0) {
|
||||
if ((graphMode || buffsRegistedNonGraphMode) && comm->mscclCompatible && nBytes > 0 && (nBytes & 31) == 0) {
|
||||
bool isManagedBuffer = false;
|
||||
if (sendBuff) CUDACHECK(hipPointerGetAttribute(&isManagedBuffer, HIP_POINTER_ATTRIBUTE_IS_MANAGED, const_cast<void*>(sendBuff)));
|
||||
if (!isManagedBuffer && recvBuff) CUDACHECK(hipPointerGetAttribute(&isManagedBuffer, HIP_POINTER_ATTRIBUTE_IS_MANAGED, const_cast<void*>(recvBuff)));
|
||||
@@ -565,8 +570,13 @@ ncclResult_t mscclEnqueueCheck(
|
||||
NCCLCHECK(mscclGetCaptureStatus(comm->rank, stream));
|
||||
}
|
||||
|
||||
const bool sendBuffRegistered = mscclpp_BuffIsRegistered(comm->mscclpp_comm, sendBuff, count);
|
||||
const bool recvBuffRegistered = mscclpp_BuffIsRegistered(comm->mscclpp_comm, recvBuff, count);
|
||||
const bool graphMode = threadLocalStatus.captureStatus != mscclNoCapture;
|
||||
const bool buffsRegistedNonGraphMode = !graphMode && sendBuffRegistered && recvBuffRegistered;
|
||||
|
||||
/* check if one rank per GPU and graph mode is enabled */
|
||||
if ((threadLocalStatus.captureStatus != mscclNoCapture) && comm->mscclCompatible && nBytes > 0 && (nBytes & 31) == 0) {
|
||||
if ((graphMode || buffsRegistedNonGraphMode) && comm->mscclCompatible && nBytes > 0 && (nBytes & 31) == 0) {
|
||||
bool isManagedBuffer = false;
|
||||
if (sendBuff) CUDACHECK(hipPointerGetAttribute(&isManagedBuffer, HIP_POINTER_ATTRIBUTE_IS_MANAGED, const_cast<void*>(sendBuff)));
|
||||
if (!isManagedBuffer && recvBuff) CUDACHECK(hipPointerGetAttribute(&isManagedBuffer, HIP_POINTER_ATTRIBUTE_IS_MANAGED, const_cast<void*>(recvBuff)));
|
||||
|
||||
@@ -30,3 +30,5 @@ ncclRedOpDestroy mscclpp_ncclRedOpDestroy
|
||||
ncclReduce mscclpp_ncclReduce
|
||||
ncclReduceScatter mscclpp_ncclReduceScatter
|
||||
ncclSend mscclpp_ncclSend
|
||||
ncclCommRegister mscclpp_ncclCommRegister
|
||||
ncclCommDeregister mscclpp_ncclCommDeregister
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#include "net.h"
|
||||
#include "register.h"
|
||||
#include "api_trace.h"
|
||||
#ifdef ENABLE_MSCCLPP
|
||||
#include "mscclpp/mscclpp_nccl.h"
|
||||
#endif
|
||||
|
||||
ncclResult_t ncclNetDeregister(struct ncclComm* comm, struct ncclReg* reg) {
|
||||
struct ncclRegCache* cache = &comm->regCache;
|
||||
@@ -155,12 +158,36 @@ NCCL_API(ncclResult_t, ncclCommRegister, const ncclComm_t comm, void* buff, size
|
||||
ncclResult_t ncclCommRegister_impl(const ncclComm_t comm, void* buff, size_t size, void** handle) {
|
||||
NCCLCHECK(CommCheck(comm, "ncclCommRegister", "comm"));
|
||||
if (comm->checkPointers) NCCLCHECK(CudaPtrCheck(buff, comm, "buff", "ncclCommRegister"));
|
||||
#ifdef ENABLE_MSCCLPP
|
||||
if (comm->mscclCompatible && size > 0 && (size & 31) == 0 && size <= comm->mscclpp_threshold){
|
||||
bool isManagedBuffer = false;
|
||||
CUDACHECK(hipPointerGetAttribute(&isManagedBuffer, HIP_POINTER_ATTRIBUTE_IS_MANAGED, const_cast<void*>(buff)));
|
||||
if(!isManagedBuffer){
|
||||
INFO(NCCL_INIT, "MSCCL++: ncclCommRegister");
|
||||
NCCLCHECK(mscclpp_ncclCommRegister(comm->mscclpp_comm, buff, size, handle));
|
||||
return ncclSuccess;
|
||||
}
|
||||
else{
|
||||
WARN("MSCCL++: Cannot register user-buffers on managed memory. RCCL user-buffer registration will occur.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
INFO(NCCL_INIT, "RCCL: ncclCommRegister");
|
||||
NCCLCHECK(ncclRegister(comm, buff, size, handle));
|
||||
return ncclSuccess;
|
||||
}
|
||||
|
||||
NCCL_API(ncclResult_t, ncclCommDeregister, const ncclComm_t comm, void* handle);
|
||||
ncclResult_t ncclCommDeregister_impl(const ncclComm_t comm, void* handle) {
|
||||
|
||||
#ifdef ENABLE_MSCCLPP
|
||||
const size_t size = mscclpp_BufferSize(comm->mscclpp_comm, handle);
|
||||
if (comm->mscclCompatible && size > 0 && (size & 31) == 0 && size <= comm->mscclpp_threshold) {
|
||||
NCCLCHECK(mscclpp_ncclCommDeregister(comm->mscclpp_comm, handle));
|
||||
return ncclSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
NCCLCHECK(CommCheck(comm, "ncclCommRegister", "comm"));
|
||||
struct ncclReg* reg = (struct ncclReg*)handle;
|
||||
struct ncclRegCache* cache = &comm->regCache;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário