Files
rocm-systems/projects/rccl/src/include/strongstream.h
T

138 lines
4.5 KiB
C
Raw Normal View History

2022-05-24 02:02:31 -07:00
/*************************************************************************
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* See LICENSE.txt for license information
************************************************************************/
#ifndef NCCL_STRONGSTREAM_H_
#define NCCL_STRONGSTREAM_H_
#include "nccl.h"
#include "checks.h"
2025-03-12 13:46:21 -07:00
#include <cuda.h>
#include <cuda_runtime.h>
2022-05-24 02:02:31 -07:00
#include <stdint.h>
2025-03-12 13:46:21 -07:00
// ncclCudaContext: wraps a CUDA context with per-context state.
struct ncclCudaContext;
// Get a ncclCudaContext to track the currently active CUDA context.
ncclResult_t ncclCudaContextTrack(struct ncclCudaContext** out);
// Drop reference.
void ncclCudaContextDrop(struct ncclCudaContext* cxt);
2022-05-24 02:02:31 -07:00
/* ncclCudaGraph: Wraps a cudaGraph_t so that we can support pre-graph CUDA runtimes
* easily.
*/
struct ncclCudaGraph {
#if ROCM_VERSION >= 60100
2025-03-12 13:46:21 -07:00
cudaStream_t origin;
2022-05-24 02:02:31 -07:00
cudaGraph_t graph;
2022-10-25 00:55:55 -07:00
unsigned long long graphId;
2022-05-24 02:02:31 -07:00
#endif
};
2022-09-27 02:31:13 -07:00
inline struct ncclCudaGraph ncclCudaGraphNone() {
2022-05-24 02:02:31 -07:00
struct ncclCudaGraph tmp;
#if ROCM_VERSION >= 60100
2025-03-12 13:46:21 -07:00
tmp.origin = nullptr;
2022-05-24 02:02:31 -07:00
tmp.graph = nullptr;
tmp.graphId = ULLONG_MAX;
#endif
return tmp;
}
inline bool ncclCudaGraphValid(struct ncclCudaGraph graph) {
#if ROCM_VERSION >= 60100
2025-03-12 13:46:21 -07:00
return graph.graphId != ULLONG_MAX;
2022-05-24 02:02:31 -07:00
#else
return false;
#endif
}
inline bool ncclCudaGraphSame(struct ncclCudaGraph a, struct ncclCudaGraph b) {
#if ROCM_VERSION >= 60100
2022-05-24 02:02:31 -07:00
return a.graphId == b.graphId;
#else
return true;
#endif
}
ncclResult_t ncclCudaGetCapturingGraph(struct ncclCudaGraph* graph, cudaStream_t stream);
ncclResult_t ncclCudaGraphAddDestructor(struct ncclCudaGraph graph, cudaHostFn_t fn, void* arg);
/* ncclStrongStream: An abstraction over CUDA streams that do not lose their
* identity while being captured. Regular streams have the deficiency that the
* captured form of a stream in one graph launch has no relation to the
* uncaptured stream or to the captured form in other graph launches. This makes
* streams unfit for the use of serializing access to a persistent resource.
* Strong streams have been introduced to address this need.
*
2025-03-12 13:46:21 -07:00
* All updates to a strong stream must be enclosed by a Acquire/Release pair.
2022-05-24 02:02:31 -07:00
*
2025-03-12 13:46:21 -07:00
* Acquire retrieves a "work" stream (cudaStream_t) which may be used to add
* work.
2022-05-24 02:02:31 -07:00
*
2025-03-12 13:46:21 -07:00
* Release publishes the work streams work into the strong stream. The Release
* must be issued by the same thread that did the Acquire.
2022-05-24 02:02:31 -07:00
*/
struct ncclStrongStream;
ncclResult_t ncclStrongStreamConstruct(struct ncclStrongStream* ss);
ncclResult_t ncclStrongStreamDestruct(struct ncclStrongStream* ss);
2025-03-12 13:46:21 -07:00
// Acquire the strong stream. Upon return `*workStream` will be usable to add work.
// `concurrent` indicates if other threads may be using the strong stream.
2022-05-24 02:02:31 -07:00
ncclResult_t ncclStrongStreamAcquire(
2025-03-12 13:46:21 -07:00
struct ncclCudaGraph graph, struct ncclStrongStream* ss, bool concurrent, cudaStream_t* workStream
2022-05-24 02:02:31 -07:00
);
2025-03-12 13:46:21 -07:00
// Get the workStream for an already acquired strong stream.
// `concurrent` indicates if other threads may be using the strong stream.
ncclResult_t ncclStrongStreamAcquiredWorkStream(
struct ncclCudaGraph graph, struct ncclStrongStream* ss, bool concurrent, cudaStream_t* workStream
2022-05-24 02:02:31 -07:00
);
2025-03-12 13:46:21 -07:00
// Release of the strong stream.
// `concurrent` indicates if other threads may be using the strong stream.
ncclResult_t ncclStrongStreamRelease(struct ncclCudaGraph graph, struct ncclStrongStream* ss, bool concurrent);
2022-05-24 02:02:31 -07:00
2025-03-12 13:46:21 -07:00
ncclResult_t ncclStreamWaitStream(
cudaStream_t a, cudaStream_t b, cudaEvent_t scratchEvent
2022-05-24 02:02:31 -07:00
);
2022-10-25 00:55:55 -07:00
2025-04-22 13:50:40 -07:00
// Like cudaStreamWaitEvent except `e` must be strictly ahead of everything in `s`.
ncclResult_t ncclStreamAdvanceToEvent(struct ncclCudaGraph g, cudaStream_t s, cudaEvent_t e);
2022-05-24 02:02:31 -07:00
// Synchrnoization does not need the strong stream to be acquired.
ncclResult_t ncclStrongStreamSynchronize(struct ncclStrongStream* ss);
////////////////////////////////////////////////////////////////////////////////
2025-03-12 13:46:21 -07:00
struct ncclStrongStreamCapture; // internal to ncclStrongStream
2022-10-25 00:55:55 -07:00
2022-05-24 02:02:31 -07:00
struct ncclStrongStream {
2025-03-12 13:46:21 -07:00
// The stream to use for non-captured work.
cudaStream_t liveStream;
void* liveAcquiredBy;
#if ROCM_VERSION >= 60100
2025-03-12 13:46:21 -07:00
// This stream ever appeared in a graph capture.
bool everCaptured;
pthread_mutex_t lock;
struct ncclStrongStreamCapture* captureHead;
2022-10-25 00:55:55 -07:00
// The event used to establish order between graphs and streams. During acquire
// this event is waited on, during release it is recorded to.
cudaEvent_t serialEvent;
#endif
2022-05-24 02:02:31 -07:00
};
2025-03-12 13:46:21 -07:00
struct ncclCudaContext {
struct ncclCudaContext* next;
CUcontext hcontext;
int refCount;
struct ncclStrongStream launchOrder;
};
2022-05-24 02:02:31 -07:00
#endif