2020-05-12 14:40:18 -07:00
|
|
|
/*************************************************************************
|
2022-01-07 06:39:55 -08:00
|
|
|
* Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved.
|
2022-04-18 11:14:51 -07:00
|
|
|
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
2020-05-12 14:40:18 -07:00
|
|
|
*
|
|
|
|
|
* See LICENSE.txt for license information
|
|
|
|
|
************************************************************************/
|
|
|
|
|
|
2023-09-26 05:47:28 -07:00
|
|
|
#include "device.h"
|
2020-05-12 14:40:18 -07:00
|
|
|
#include "collectives.h"
|
2021-07-08 14:12:04 -07:00
|
|
|
#include "primitives.h"
|
2022-06-21 05:30:19 +08:00
|
|
|
#if defined(ENABLE_NPKIT)
|
|
|
|
|
#include "npkit/npkit.h"
|
|
|
|
|
#endif
|
2020-05-12 14:40:18 -07:00
|
|
|
|
2021-07-08 14:12:04 -07:00
|
|
|
template<typename T, typename RedOp>
|
|
|
|
|
struct RunWork<ncclFuncSendRecv, T, RedOp, NCCL_ALGO_RING, NCCL_PROTO_SIMPLE> {
|
2022-08-18 02:53:17 -07:00
|
|
|
template<typename Proto>
|
2023-04-03 05:32:07 -07:00
|
|
|
__device__ void runSend(const int tid, const int nthreads, const uint8_t group, struct ncclWorkElemP2p* args) {
|
2022-05-24 02:02:31 -07:00
|
|
|
void* buff = reinterpret_cast<void*>(uintptr_t(args->buffHi32)<<32 | args->buffLo32);
|
2023-02-27 02:48:21 -08:00
|
|
|
ssize_t count = reinterpret_cast<size_t>(size_t(args->countHi32)<<32 | args->countLo32);
|
2022-06-21 05:30:19 +08:00
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT)
|
|
|
|
|
bool isNpKitThread = (tid == 0);
|
2023-08-09 08:30:40 +08:00
|
|
|
int npKitCtxIdx = blockIdx.x * NCCL_MAX_WORK_ELEMENTS_P2P + group;
|
2022-06-21 05:30:19 +08:00
|
|
|
#endif
|
|
|
|
|
|
2023-05-24 22:41:05 +08:00
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_TIME_SYNC_CPU)
|
|
|
|
|
if (isNpKitThread) {
|
|
|
|
|
uint64_t* cpuTimestamp = ncclShmem.comm.cpuTimestamp;
|
|
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_TIME_SYNC_CPU, 0, 0, *cpuTimestamp,
|
|
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_TIME_SYNC_GPU)
|
|
|
|
|
if (isNpKitThread) {
|
|
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_TIME_SYNC_GPU, 0, 0, NPKIT_GET_GPU_TIMESTAMP(),
|
|
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-09-20 09:00:20 -07:00
|
|
|
if (args->peer == ncclShmem.comm.rank) {
|
2022-01-07 06:39:55 -08:00
|
|
|
struct ncclWorkElemP2p* recvArgs = args-1;
|
2022-05-24 02:02:31 -07:00
|
|
|
void* recvBuff = reinterpret_cast<void*>(uintptr_t(recvArgs->buffHi32)<<32 | recvArgs->buffLo32);
|
|
|
|
|
if (buff != recvBuff) {
|
2022-06-21 05:30:19 +08:00
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_SEND_RECV_LOCAL_COPY_ENTRY)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_SEND_RECV_LOCAL_COPY_ENTRY, count*sizeof(T), 0, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_PRIM_SIMPLE_REDUCE_OR_COPY_MULTI_ENTRY)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_PRIM_SIMPLE_REDUCE_OR_COPY_MULTI_ENTRY, count*sizeof(T), 0, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-01-19 12:16:05 -06:00
|
|
|
#if defined(__gfx940__) || defined(__gfx941__) || defined(__gfx942__)
|
|
|
|
|
reduceCopy<COLL_UNROLL*2, RedOp, T, 0,1,1, 0,1,1, /*PreOpSrcs=*/0>
|
|
|
|
|
(tid, nthreads, 0, nullptr, false, 1, &buff, 1, &recvBuff, count);
|
|
|
|
|
#else
|
2023-04-03 05:32:07 -07:00
|
|
|
reduceCopy<COLL_UNROLL, RedOp, T, 0,1,1, 0,1,1, /*PreOpSrcs=*/0>
|
2023-04-25 15:38:04 -07:00
|
|
|
(tid, nthreads, 0, nullptr, false, 1, &buff, 1, &recvBuff, count);
|
2024-01-19 12:16:05 -06:00
|
|
|
#endif
|
|
|
|
|
|
2022-06-21 05:30:19 +08:00
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_PRIM_SIMPLE_REDUCE_OR_COPY_MULTI_EXIT)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_PRIM_SIMPLE_REDUCE_OR_COPY_MULTI_EXIT, count*sizeof(T), 0, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_SEND_RECV_LOCAL_COPY_EXIT)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_SEND_RECV_LOCAL_COPY_EXIT, count*sizeof(T), 0, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
2022-01-07 06:39:55 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
2022-08-18 02:53:17 -07:00
|
|
|
int chunkSize = args->chunkSize/sizeof(T);
|
|
|
|
|
if (args->proto == NCCL_PROTO_LL) chunkSize /= 2;
|
2022-01-07 06:39:55 -08:00
|
|
|
int const peer = args->peer;
|
2024-01-24 16:23:53 -08:00
|
|
|
Primitives<T, RedOp, FanAsymmetric<0, 1>, 0, Proto, 1> prims
|
2024-04-23 13:33:19 -07:00
|
|
|
(tid, nthreads, nullptr, &peer, buff, nullptr, /*redOpArg(ignored)=*/0, group, args->connIndex, args->connIndex, nullptr, args, ncclShmem.comm.p2pChunkSize/sizeof(T));
|
2022-06-21 05:30:19 +08:00
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT)
|
|
|
|
|
if (isNpKitThread) {
|
|
|
|
|
prims.npKitCtxIdx = npKitCtxIdx;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_SEND_RECV_SEND_ENTRY)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_SEND_RECV_SEND_ENTRY, count*sizeof(T), 0, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
prims.npKitDataProcessTotalTime = 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-05-24 02:02:31 -07:00
|
|
|
size_t offset = 0;
|
2022-01-07 06:39:55 -08:00
|
|
|
do {
|
2022-05-24 02:02:31 -07:00
|
|
|
int nelem = min(size_t(chunkSize), count-offset);
|
2022-01-07 06:39:55 -08:00
|
|
|
prims.directSend(offset, offset, nelem);
|
|
|
|
|
offset += nelem;
|
2024-02-05 05:06:02 -08:00
|
|
|
} while(offset < count && args->reg == 0);
|
2022-06-21 05:30:19 +08:00
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_SEND_RECV_SEND_EXIT)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_SEND_RECV_SEND_EXIT, count*sizeof(T), prims.npKitDataProcessTotalTime, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-01-07 06:39:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-12 14:40:18 -07:00
|
|
|
|
2022-08-18 02:53:17 -07:00
|
|
|
template<typename Proto>
|
2023-04-03 05:32:07 -07:00
|
|
|
__device__ void runRecv(const int tid, const int nthreads, const uint8_t group, struct ncclWorkElemP2p* args) {
|
2022-06-21 05:30:19 +08:00
|
|
|
#if defined(ENABLE_NPKIT)
|
|
|
|
|
bool isNpKitThread = (tid == 0);
|
2023-08-09 08:30:40 +08:00
|
|
|
int npKitCtxIdx = blockIdx.x * NCCL_MAX_WORK_ELEMENTS_P2P + group;
|
2022-06-21 05:30:19 +08:00
|
|
|
#endif
|
|
|
|
|
|
2023-05-24 22:41:05 +08:00
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_TIME_SYNC_CPU)
|
|
|
|
|
if (isNpKitThread) {
|
|
|
|
|
uint64_t* cpuTimestamp = ncclShmem.comm.cpuTimestamp;
|
|
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_TIME_SYNC_CPU, 0, 0, *cpuTimestamp,
|
|
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_TIME_SYNC_GPU)
|
|
|
|
|
if (isNpKitThread) {
|
|
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_TIME_SYNC_GPU, 0, 0, NPKIT_GET_GPU_TIMESTAMP(),
|
|
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-09-20 09:00:20 -07:00
|
|
|
if (args->peer != ncclShmem.comm.rank) {
|
2022-05-24 02:02:31 -07:00
|
|
|
void* buff = reinterpret_cast<void*>(uintptr_t(args->buffHi32)<<32 | args->buffLo32);
|
|
|
|
|
ssize_t count = reinterpret_cast<size_t>(size_t(args->countHi32)<<32 | args->countLo32);
|
2022-08-18 02:53:17 -07:00
|
|
|
int chunkSize = args->chunkSize/sizeof(T);
|
|
|
|
|
if (args->proto == NCCL_PROTO_LL) chunkSize /= 2; // This is to account for chunkEffectiveSize
|
2022-01-07 06:39:55 -08:00
|
|
|
int const peer = args->peer;
|
2024-01-24 16:23:53 -08:00
|
|
|
Primitives<T, RedOp, FanAsymmetric<1, 0>, 0, Proto, 1> prims
|
2024-04-23 13:33:19 -07:00
|
|
|
(tid, nthreads, &peer, nullptr, nullptr, buff, /*redOpArg(ignored)=*/0, group, args->connIndex, args->connIndex, nullptr, args, ncclShmem.comm.p2pChunkSize/sizeof(T));
|
2022-06-21 05:30:19 +08:00
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT)
|
|
|
|
|
if (isNpKitThread) {
|
|
|
|
|
prims.npKitCtxIdx = npKitCtxIdx;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_SEND_RECV_RECV_ENTRY)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_SEND_RECV_RECV_ENTRY, count*sizeof(T), 0, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
prims.npKitDataProcessTotalTime = 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-05-24 02:02:31 -07:00
|
|
|
size_t offset = 0;
|
2022-01-07 06:39:55 -08:00
|
|
|
do {
|
2022-05-24 02:02:31 -07:00
|
|
|
int nelem = min(size_t(chunkSize), count-offset);
|
2022-01-07 06:39:55 -08:00
|
|
|
prims.directRecv(offset, nelem);
|
|
|
|
|
offset += nelem;
|
2024-02-05 05:06:02 -08:00
|
|
|
} while(offset < count && args->reg == 0);
|
2022-06-21 05:30:19 +08:00
|
|
|
|
|
|
|
|
#if defined(ENABLE_NPKIT) && defined(ENABLE_NPKIT_EVENT_SEND_RECV_RECV_EXIT)
|
|
|
|
|
if (isNpKitThread) {
|
2023-02-18 03:26:57 +08:00
|
|
|
NpKit::CollectGpuEvent(NPKIT_EVENT_SEND_RECV_RECV_EXIT, count*sizeof(T), prims.npKitDataProcessTotalTime, NPKIT_GET_GPU_TIMESTAMP(),
|
2022-09-20 09:00:20 -07:00
|
|
|
ncclShmem.comm.npKitEventCollectContexts + npKitCtxIdx);
|
2022-06-21 05:30:19 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-01-07 06:39:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-12 14:40:18 -07:00
|
|
|
|
2023-12-02 18:49:52 -07:00
|
|
|
#if defined(USE_INDIRECT_FUNCTION_CALL) && !defined(__gfx940__) && !defined(__gfx941__) && !defined(__gfx942__)
|
2023-02-14 13:59:48 -08:00
|
|
|
__device__ void run(ncclWork *work) {
|
|
|
|
|
#else
|
2022-09-20 09:00:20 -07:00
|
|
|
__device__ __attribute__((noinline)) void run(ncclWork *work) {
|
2023-02-14 13:59:48 -08:00
|
|
|
#endif
|
2022-01-07 06:39:55 -08:00
|
|
|
struct ncclWorkElemP2p* args = work->p2pElems;
|
|
|
|
|
int ngroups = args->ngroups;
|
|
|
|
|
int tid = threadIdx.x;
|
|
|
|
|
int wid = tid / WARP_SIZE;
|
|
|
|
|
// This has to work even for groups of 2.5 warps (which is 8 groups, and means 3
|
|
|
|
|
// warps for send, 2 warps for recv).
|
|
|
|
|
// warpStarts were rounded thanks to int division, but for group number we need to round the other way around
|
|
|
|
|
// So we mirror wid then mirror again the group.
|
|
|
|
|
#define NWARPS (NCCL_MAX_NTHREADS/WARP_SIZE)
|
2023-04-03 05:32:07 -07:00
|
|
|
uint8_t group = ngroups-1- (NWARPS-1-wid) * ngroups / NWARPS;
|
2022-01-07 06:39:55 -08:00
|
|
|
args += group;
|
|
|
|
|
tid -= args->warpStart * WARP_SIZE;
|
|
|
|
|
int nthreads = args->nWarps * WARP_SIZE;
|
2022-05-24 02:02:31 -07:00
|
|
|
|
|
|
|
|
if (args->p2pType == ncclWorkP2pTypeUnused) return;
|
2022-01-07 06:39:55 -08:00
|
|
|
if (tid >= nthreads || args->peer == -1) return;
|
2022-08-18 02:53:17 -07:00
|
|
|
|
|
|
|
|
// Select Proto here
|
|
|
|
|
// This is to allow the same kernel to run multiple primitives on different warps (thread groups)
|
2022-01-07 06:39:55 -08:00
|
|
|
if ((group%2) == 0) {
|
2022-08-18 02:53:17 -07:00
|
|
|
if (args->proto == NCCL_PROTO_LL) {
|
|
|
|
|
runRecv<ProtoLL>(tid, nthreads, group, args);
|
|
|
|
|
} else {
|
2023-07-17 21:45:52 -05:00
|
|
|
#if defined(__gfx90a__)
|
|
|
|
|
runRecv<ProtoSimple<1,1,8>>(tid, nthreads, group, args);
|
2024-01-19 12:16:05 -06:00
|
|
|
#elif defined(__gfx908__) || defined(__gfx940__) || defined(__gfx941__) || defined(__gfx942__)
|
2023-08-29 12:49:06 -04:00
|
|
|
runRecv<ProtoSimple<1,1,4>>(tid, nthreads, group, args);
|
2023-07-17 21:45:52 -05:00
|
|
|
#else
|
2022-08-18 02:53:17 -07:00
|
|
|
runRecv<ProtoSimple<1,1>>(tid, nthreads, group, args);
|
2023-07-17 21:45:52 -05:00
|
|
|
#endif
|
2022-08-18 02:53:17 -07:00
|
|
|
}
|
2022-01-07 06:39:55 -08:00
|
|
|
} else {
|
2022-08-18 02:53:17 -07:00
|
|
|
if (args->proto == NCCL_PROTO_LL) {
|
|
|
|
|
runSend<ProtoLL>(tid, nthreads, group, args);
|
|
|
|
|
} else {
|
2023-07-17 21:45:52 -05:00
|
|
|
#if defined(__gfx90a__)
|
|
|
|
|
runSend<ProtoSimple<1,1,8>>(tid, nthreads, group, args);
|
2024-01-19 12:16:05 -06:00
|
|
|
#elif defined(__gfx908__) || defined(__gfx940__) || defined(__gfx941__) || defined(__gfx942__)
|
2023-08-29 12:49:06 -04:00
|
|
|
runSend<ProtoSimple<1,1,4>>(tid, nthreads, group, args);
|
2023-07-17 21:45:52 -05:00
|
|
|
#else
|
2022-08-18 02:53:17 -07:00
|
|
|
runSend<ProtoSimple<1,1>>(tid, nthreads, group, args);
|
2023-07-17 21:45:52 -05:00
|
|
|
#endif
|
2022-08-18 02:53:17 -07:00
|
|
|
}
|
2020-05-12 14:40:18 -07:00
|
|
|
}
|
2021-07-08 14:12:04 -07:00
|
|
|
}
|
2024-04-23 13:33:19 -07:00
|
|
|
};
|