Update RCCL-tests in examples folder (#261)
- Create a local copy for ROCm/rccl-tests for our examples.
- Update argument parsing to no longer use getopt_long.
- Workaround for Dyninst instrumentation.
---------
Co-authored-by: David Galiffi <David.Galiffi@amd.com>
[ROCm/rocprofiler-systems commit: 4e5029221b]
这个提交包含在:
@@ -0,0 +1,174 @@
|
||||
#
|
||||
# Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
# Modifications are Copyright (c) 2019-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# See LICENSE.txt for license information
|
||||
#
|
||||
|
||||
ROCM_PATH ?= /opt/rocm
|
||||
MPI_HOME ?= /usr/lib/x86_64-linux-gnu
|
||||
PREFIX ?= /usr/local
|
||||
VERBOSE ?= 0
|
||||
DEBUG ?= 0
|
||||
NCCL_HOME ?= ""
|
||||
CUSTOM_RCCL_LIB ?= ""
|
||||
|
||||
HIPCC ?= $(ROCM_PATH)/bin/amdclang++
|
||||
HIPCONFIG = $(ROCM_PATH)/bin/hipconfig
|
||||
CXX = $(HIPCC)
|
||||
|
||||
HIPCUFLAGS := -std=c++14
|
||||
LDFLAGS :=
|
||||
HIPLDFLAGS :=
|
||||
|
||||
HIP_VERSION = $(strip $(shell which $(HIPCONFIG) >/dev/null && $(HIPCONFIG) --version))
|
||||
HIP_MAJOR = $(shell echo $(HIP_VERSION) | cut -d "." -f 1)
|
||||
HIP_MINOR = $(shell echo $(HIP_VERSION) | cut -d "." -f 2)
|
||||
|
||||
# Better define GPU_TARGETS in your environment to the minimal set
|
||||
# of archs to reduce compile time.
|
||||
# Currently, supports gfx906,gfx908,gfx90a,gfx942,gfx950,gfx1030,gfx1100,gfx1101,gfx1102,gfx1200,gfx1201
|
||||
ifndef GPU_TARGETS
|
||||
GPU_TARGETS = gfx906 gfx908 gfx90a
|
||||
ifeq ($(shell test "0$(HIP_MAJOR)" -eq 6; echo $$?),0)
|
||||
# Include gfx942 support if we're using ROCm 6.0 or above
|
||||
GPU_TARGETS += gfx942
|
||||
ifeq ($(shell test "0$(HIP_MINOR)" -ge 5; echo $$?),0)
|
||||
# Include gfx950 support if we're using ROCm 6.5 or above
|
||||
GPU_TARGETS += gfx950
|
||||
endif
|
||||
endif
|
||||
GPU_TARGETS += gfx1030 gfx1100 gfx1101 gfx1102 gfx1200 gfx1201
|
||||
endif
|
||||
|
||||
GPU_TARGETS_FLAGS = $(foreach target,$(GPU_TARGETS),"--offload-arch=$(target)")
|
||||
|
||||
#CUDA_VERSION = $(strip $(shell which $(NVCC) >/dev/null && $(NVCC) --version | grep release | sed 's/.*release //' | sed 's/\,.*//'))
|
||||
#CUDA_MAJOR = $(shell echo $(CUDA_VERSION) | cut -d "." -f 1)
|
||||
#CUDA_MINOR = $(shell echo $(CUDA_VERSION) | cut -d "." -f 2)
|
||||
#
|
||||
## Better define NVCC_GENCODE in your environment to the minimal set
|
||||
## of archs to reduce compile time.
|
||||
#ifeq ($(shell test "0$(CUDA_MAJOR)" -eq 12 -a "0$(CUDA_MINOR)" -ge 8 -o "0$(CUDA_MAJOR)" -ge 13; echo $$?),0)
|
||||
## Include Blackwell support if we're using CUDA12.8 or above
|
||||
#NVCC_GENCODE ?= -gencode=arch=compute_80,code=sm_80 \
|
||||
# -gencode=arch=compute_90,code=sm_90 \
|
||||
# -gencode=arch=compute_100,code=sm_100 \
|
||||
# -gencode=arch=compute_120,code=sm_120 \
|
||||
# -gencode=arch=compute_120,code=compute_120
|
||||
#else ifeq ($(shell test "0$(CUDA_MAJOR)" -ge 12; echo $$?),0)
|
||||
#NVCC_GENCODE ?= -gencode=arch=compute_60,code=sm_60 \
|
||||
# -gencode=arch=compute_61,code=sm_61 \
|
||||
# -gencode=arch=compute_70,code=sm_70 \
|
||||
# -gencode=arch=compute_80,code=sm_80 \
|
||||
# -gencode=arch=compute_90,code=sm_90 \
|
||||
# -gencode=arch=compute_90,code=compute_90
|
||||
#else ifeq ($(shell test "0$(CUDA_MAJOR)" -ge 11; echo $$?),0)
|
||||
#NVCC_GENCODE ?= -gencode=arch=compute_60,code=sm_60 \
|
||||
# -gencode=arch=compute_61,code=sm_61 \
|
||||
# -gencode=arch=compute_70,code=sm_70 \
|
||||
# -gencode=arch=compute_80,code=sm_80 \
|
||||
# -gencode=arch=compute_80,code=compute_80
|
||||
#else
|
||||
#NVCC_GENCODE ?= -gencode=arch=compute_35,code=sm_35 \
|
||||
# -gencode=arch=compute_50,code=sm_50 \
|
||||
# -gencode=arch=compute_60,code=sm_60 \
|
||||
# -gencode=arch=compute_61,code=sm_61 \
|
||||
# -gencode=arch=compute_70,code=sm_70 \
|
||||
# -gencode=arch=compute_70,code=compute_70
|
||||
#endif
|
||||
|
||||
ifneq ($(NCCL_HOME), "")
|
||||
HIPCUFLAGS += -I$(NCCL_HOME)/ -I$(NCCL_HOME)/include
|
||||
HIPLDFLAGS += -Wl,-rpath,$(NCCL_HOME) -L$(NCCL_HOME) -L$(NCCL_HOME)/lib
|
||||
endif
|
||||
|
||||
HIPCUFLAGS += -I$(ROCM_PATH)/include
|
||||
HIPCUFLAGS += -I$(ROCM_PATH)/include/hip
|
||||
HIPCUFLAGS += -x hip -D__HIP_PLATFORM_AMD__ -D__HIPCC__ $(GPU_TARGETS_FLAGS)
|
||||
LDFLAGS += -L$(ROCM_PATH)/lib -lhsa-runtime64 -lrt
|
||||
ifneq ($(CUSTOM_RCCL_LIB), "")
|
||||
HIPLDFLAGS += -L$(CUSTOM_RCCL_LIB)
|
||||
endif
|
||||
HIPLDFLAGS += -L$(ROCM_PATH)/lib -lhsa-runtime64 -lamdhip64 -lstdc++ -lrt -pthread
|
||||
|
||||
ifeq ($(DEBUG), 0)
|
||||
HIPCUFLAGS += -O3
|
||||
else
|
||||
HIPCUFLAGS += -O0 -g -ggdb3
|
||||
endif
|
||||
|
||||
ifeq ($(VERBOSE), 0)
|
||||
.SILENT:
|
||||
endif
|
||||
|
||||
.PHONY: build clean
|
||||
|
||||
BUILDDIR ?= ../build
|
||||
HIPIFY_DIR ?= $(BUILDDIR)/hipify
|
||||
|
||||
.PRECIOUS: $(HIPIFY_DIR)/%.cpp $(HIPIFY_DIR)/%.h
|
||||
|
||||
ifeq ($(MPI), 1)
|
||||
HIPCUFLAGS += -DMPI_SUPPORT -I${MPI_HOME}/include -I${MPI_HOME}/include/openmpi -I${MPI_HOME}/openmpi/include -I${MPI_HOME}/openmpi/include/openmpi
|
||||
HIPLDFLAGS += -L${MPI_HOME}/lib -L${MPI_HOME}/openmpi/lib -lmpi
|
||||
else ifeq ($(MPICH), 1)
|
||||
HIPCUFLAGS += -DMPI_SUPPORT -I${MPI_HOME}/include -I${MPI_HOME}/mpich/include -I/usr/include/x86_64-linux-gnu/mpich
|
||||
HIPLDFLAGS += -L${MPI_HOME}/lib -L${MPI_HOME}/mpich/lib -lmpich
|
||||
endif
|
||||
|
||||
LIBRARIES += rccl
|
||||
HIPLDFLAGS += $(LIBRARIES:%=-l%)
|
||||
|
||||
DST_DIR := $(BUILDDIR)
|
||||
SRC_FILES := $(wildcard *.cpp)
|
||||
OBJ_FILES := $(SRC_FILES:%.cpp=${DST_DIR}/%.o)
|
||||
BIN_FILES_LIST := all_reduce all_gather broadcast reduce_scatter reduce alltoall scatter gather sendrecv alltoallv
|
||||
BIN_FILES := $(BIN_FILES_LIST:%=${DST_DIR}/%_perf)
|
||||
|
||||
GIT_VERSION_FILE := ${DST_DIR}/src/git_version.cpp
|
||||
GIT_REV := $(shell git log --pretty=format:'%h' -n 1)
|
||||
GIT_DIFF := $(shell git diff --quiet --exit-code || echo +)
|
||||
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
build: ${BIN_FILES}
|
||||
|
||||
clean:
|
||||
rm -rf ${DST_DIR}
|
||||
|
||||
TEST_VERIFIABLE_SRCDIR := ../verifiable
|
||||
TEST_VERIFIABLE_BUILDDIR := $(BUILDDIR)/verifiable
|
||||
include ../verifiable/verifiable.mk
|
||||
|
||||
# Rule to create git_version.cpp
|
||||
$(GIT_VERSION_FILE):
|
||||
@mkdir -p ${DST_DIR}/src
|
||||
@echo 'const char* rcclTestsGitHash = "$(GIT_BRANCH):$(GIT_REV)$(GIT_DIFF)";' > $@
|
||||
|
||||
${HIPIFY_DIR}/%.cpp: %.cpp
|
||||
@printf "Hipifying %-35s > %s\n" $< $@
|
||||
@mkdir -p ${HIPIFY_DIR}
|
||||
hipify-perl -quiet-warnings $< > $@
|
||||
|
||||
${HIPIFY_DIR}/%.h: %.h
|
||||
@printf "Hipifying %-35s > %s\n" $< $@
|
||||
@mkdir -p ${HIPIFY_DIR}
|
||||
hipify-perl -quiet-warnings $< > $@
|
||||
|
||||
${DST_DIR}/%.o: ${HIPIFY_DIR}/%.cpp ${HIPIFY_DIR}/common.h $(TEST_VERIFIABLE_HDRS) $(GIT_VERSION_FILE)
|
||||
@printf "Compiling %-35s > %s\n" $< $@
|
||||
@mkdir -p ${DST_DIR}
|
||||
echo "$(HIPCC) $(HIPCUFLAGS) -I. -c -o $@ $<"
|
||||
$(HIPCC) $(HIPCUFLAGS) -I. -c -o $@ $<
|
||||
|
||||
${DST_DIR}/timer.o: timer.cc timer.h
|
||||
@printf "Compiling %-35s > %s\n" $< $@
|
||||
@mkdir -p ${DST_DIR}
|
||||
$(CXX) $(CXXFLAGS) -o $@ -c timer.cc
|
||||
|
||||
${DST_DIR}/%_perf:${DST_DIR}/%.o ${DST_DIR}/common.o ${DST_DIR}/timer.o $(TEST_VERIFIABLE_OBJS) $(DST_DIR)/src/git_version.cpp
|
||||
@printf "Linking %-35s > %s\n" $< $@
|
||||
@mkdir -p ${DST_DIR}
|
||||
echo "$(HIPCC) -o $@ $^ $(HIPLDFLAGS)"
|
||||
$(HIPCC) -o $@ $^ $(HIPLDFLAGS)
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
AllGatherGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
size_t base = (count / nranks) & -(16 / eltSize);
|
||||
*sendcount = base;
|
||||
*recvcount = base * nranks;
|
||||
*sendInplaceOffset = base;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = base;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AllGatherInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? ((char*) args->recvbuffs[i]) + rank * args->sendBytes
|
||||
: args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, ncclSum, 33 * rep + rank, 1, 0));
|
||||
for(int j = 0; j < nranks; j++)
|
||||
{
|
||||
TESTCHECK(InitData((char*) args->expected[i] + args->sendBytes * j, sendcount,
|
||||
0, type, ncclSum, 33 * rep + j, 1, 0));
|
||||
}
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
AllGatherGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize * nranks) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (nranks - 1)) / ((double) nranks);
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AllGatherRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
NCCLCHECK(ncclAllGather(sendbuff, recvbuff, count, type, comm, stream));
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl allGatherTest = { "AllGather", AllGatherGetCollByteCount,
|
||||
AllGatherInitData, AllGatherGetBw, AllGatherRunColl };
|
||||
|
||||
void
|
||||
AllGatherGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
AllGatherGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AllGatherRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &allGatherTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
TESTCHECK(
|
||||
TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0, "none", -1));
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { AllGatherGetBuffSize, AllGatherRunTest };
|
||||
@@ -0,0 +1,126 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
AllReduceGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
*sendcount = count;
|
||||
*recvcount = count;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = *sendcount;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AllReduceInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, op, rep, nranks, rank));
|
||||
TESTCHECK(InitDataReduce(args->expected[i], recvcount, 0, type, op, rep, nranks));
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
AllReduceGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (2 * (nranks - 1))) / ((double) nranks);
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AllReduceRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
NCCLCHECK(ncclAllReduce(sendbuff, recvbuff, count, type, op, comm, stream));
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl allReduceTest = { "AllReduce", AllReduceGetCollByteCount,
|
||||
AllReduceInitData, AllReduceGetBw, AllReduceRunColl };
|
||||
|
||||
void
|
||||
AllReduceGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
AllReduceGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AllReduceRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &allReduceTest;
|
||||
ncclDataType_t* run_types;
|
||||
ncclRedOp_t* run_ops;
|
||||
const char ** run_typenames, **run_opnames;
|
||||
int type_count, op_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if((int) op != -1)
|
||||
{
|
||||
op_count = 1;
|
||||
run_ops = &op;
|
||||
run_opnames = &opName;
|
||||
}
|
||||
else
|
||||
{
|
||||
op_count = test_opnum;
|
||||
run_ops = test_ops;
|
||||
run_opnames = test_opnames;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = 0; j < op_count; j++)
|
||||
{
|
||||
#if defined(RCCL_FLOAT8)
|
||||
if((run_types[i] == ncclFp8E4M3 || run_types[i] == ncclFp8E5M2) &&
|
||||
run_ops[j] == ncclProd)
|
||||
continue;
|
||||
#endif
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], run_ops[j],
|
||||
run_opnames[j], -1));
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { AllReduceGetBuffSize, AllReduceRunTest };
|
||||
@@ -0,0 +1,112 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
AlltoAllGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
*paramcount = (count / nranks) & -(16 / eltSize);
|
||||
*sendcount = nranks * (*paramcount);
|
||||
*recvcount = *sendcount;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AlltoAllInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, ncclSum, 33 * rep + rank, 1, 0));
|
||||
for(int j = 0; j < nranks; j++)
|
||||
{
|
||||
size_t partcount = sendcount / nranks;
|
||||
TESTCHECK(InitData((char*) args->expected[i] + j * partcount * wordSize(type),
|
||||
partcount, rank * partcount, type, ncclSum, 33 * rep + j,
|
||||
1, 0));
|
||||
}
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
// We don't support in-place alltoall
|
||||
args->reportErrors = in_place ? 0 : 1;
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
AlltoAllGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * nranks * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (nranks - 1)) / ((double) (nranks));
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AlltoAllRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
NCCLCHECK(ncclAllToAll(sendbuff, recvbuff, count, type, comm, stream));
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl alltoAllTest = { "AlltoAll", AlltoAllGetCollByteCount, AlltoAllInitData,
|
||||
AlltoAllGetBw, AlltoAllRunColl };
|
||||
|
||||
void
|
||||
AlltoAllGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
AlltoAllGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AlltoAllRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &alltoAllTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
TESTCHECK(
|
||||
TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0, "none", -1));
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { AlltoAllGetBuffSize, AlltoAllRunTest };
|
||||
@@ -0,0 +1,218 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
#define USE_RCCL_GATHER_SCATTER
|
||||
|
||||
void
|
||||
AlltoAllvGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
if(count < nranks * nranks / 2)
|
||||
{
|
||||
*sendcount = 0;
|
||||
*recvcount = 0;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*paramcount = (count / nranks) & -(16 / eltSize);
|
||||
*sendcount = nranks * (*paramcount);
|
||||
*recvcount = *sendcount;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AlltoAllvInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, ncclSum, 33 * rep + rank, 1, 0));
|
||||
|
||||
#if 0
|
||||
int *dataHost = (int *)malloc(args->sendBytes);
|
||||
cudaMemcpy(dataHost, data, args->sendBytes, cudaMemcpyDeviceToHost);
|
||||
printf(" Rank [%d] Original: ", rank);
|
||||
for(int j=0; j<sendcount; j++) {
|
||||
printf("%d:%d ", j, dataHost[j]);
|
||||
}
|
||||
printf("\n");
|
||||
free(dataHost);
|
||||
#endif
|
||||
|
||||
size_t rdisp = 0;
|
||||
size_t data_count = sendcount * 2 / nranks;
|
||||
size_t chunksize = data_count / nranks;
|
||||
for(int j = 0; j < nranks; j++)
|
||||
{
|
||||
size_t scount = 0, rcount = ((j + rank) % nranks) * chunksize;
|
||||
if((j + rank) % nranks == 0)
|
||||
rcount += (sendcount - chunksize * (nranks - 1) * nranks / 2);
|
||||
size_t sdisp = 0;
|
||||
for(int k = 0; k < nranks; k++)
|
||||
{
|
||||
scount = ((k + j) % nranks) * chunksize;
|
||||
if((k + j) % nranks == 0)
|
||||
scount += (sendcount - chunksize * (nranks - 1) * nranks / 2);
|
||||
if(k == rank) break;
|
||||
sdisp += scount;
|
||||
}
|
||||
TESTCHECK(InitData(((char*) args->expected[i]) + rdisp * wordSize(type),
|
||||
rcount, sdisp, type, ncclSum, 33 * rep + j, 1, 0));
|
||||
rdisp += rcount;
|
||||
}
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
// We don't support in-place alltoall
|
||||
args->reportErrors = in_place ? 0 : 1;
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
AlltoAllvGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * nranks * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (nranks - 1)) / ((double) (nranks));
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AlltoAllvRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
int nranks;
|
||||
NCCLCHECK(ncclCommCount(comm, &nranks));
|
||||
int rank;
|
||||
NCCLCHECK(ncclCommUserRank(comm, &rank));
|
||||
|
||||
if(count == 0) return testSuccess;
|
||||
|
||||
size_t *sendcounts, *recvcounts, *sdispls, *rdispls;
|
||||
sendcounts = (size_t*) malloc(nranks * nranks * sizeof(size_t));
|
||||
recvcounts = (size_t*) malloc(nranks * nranks * sizeof(size_t));
|
||||
sdispls = (size_t*) malloc(nranks * nranks * sizeof(size_t));
|
||||
rdispls = (size_t*) malloc(nranks * nranks * sizeof(size_t));
|
||||
if(sendcounts == nullptr || recvcounts == nullptr || sdispls == nullptr ||
|
||||
rdispls == nullptr)
|
||||
{
|
||||
printf("failed to allocate buffers for alltoallv\n");
|
||||
return testNcclError;
|
||||
}
|
||||
|
||||
size_t disp = 0;
|
||||
size_t chunksize = count * 2 / nranks;
|
||||
for(int i = 0; i < nranks; i++)
|
||||
{
|
||||
size_t scount = ((i + rank) % nranks) * chunksize;
|
||||
if((i + rank) % nranks == 0)
|
||||
scount += (count * nranks - chunksize * (nranks - 1) * nranks / 2);
|
||||
sendcounts[i + rank * nranks] = recvcounts[i + rank * nranks] = scount;
|
||||
sdispls[i + rank * nranks] = rdispls[i + rank * nranks] = disp;
|
||||
disp += scount;
|
||||
// printf("%d->%d: sendcounts/recvcounts %lx sdispls/rdispls %lx\n", rank, i,
|
||||
// sendcounts[i+rank*nranks]*wordSize(type),
|
||||
// sdispls[i+rank*nranks]*wordSize(type));
|
||||
}
|
||||
|
||||
#if NCCL_MAJOR < 2 || NCCL_MINOR < 7
|
||||
printf(
|
||||
"NCCL 2.7 or later is needed for alltoallv. This test was compiled with %d.%d.\n",
|
||||
NCCL_MAJOR, NCCL_MINOR);
|
||||
return testNcclError;
|
||||
#else
|
||||
# if defined(RCCL_ALLTOALLV) && defined(USE_RCCL_GATHER_SCATTER)
|
||||
NCCLCHECK(ncclAllToAllv(sendbuff, sendcounts + rank * nranks, sdispls + rank * nranks,
|
||||
recvbuff, recvcounts + rank * nranks, rdispls + rank * nranks,
|
||||
type, comm, stream));
|
||||
# else
|
||||
NCCLCHECK(ncclGroupStart());
|
||||
for(int r = 0; r < nranks; r++)
|
||||
{
|
||||
if(sendcounts[r + rank * nranks] != 0)
|
||||
{
|
||||
NCCLCHECK(
|
||||
ncclSend(((char*) sendbuff) + sdispls[r + rank * nranks] * wordSize(type),
|
||||
sendcounts[r + rank * nranks], type, r, comm, stream));
|
||||
}
|
||||
if(recvcounts[r + rank * nranks] != 0)
|
||||
{
|
||||
NCCLCHECK(
|
||||
ncclRecv(((char*) recvbuff) + rdispls[r + rank * nranks] * wordSize(type),
|
||||
recvcounts[r + rank * nranks], type, r, comm, stream));
|
||||
}
|
||||
}
|
||||
NCCLCHECK(ncclGroupEnd());
|
||||
# endif
|
||||
#endif
|
||||
free(sendcounts);
|
||||
free(recvcounts);
|
||||
free(sdispls);
|
||||
free(rdispls);
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl alltoAllTest = { "AlltoAllv", AlltoAllvGetCollByteCount,
|
||||
AlltoAllvInitData, AlltoAllvGetBw, AlltoAllvRunColl };
|
||||
|
||||
void
|
||||
AlltoAllvGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
AlltoAllvGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
AlltoAllvRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &alltoAllTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = ncclNumTypes;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
TESTCHECK(
|
||||
TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0, "", -1));
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { AlltoAllvGetBuffSize, AlltoAllvRunTest };
|
||||
@@ -0,0 +1,131 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
BroadcastGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
*sendcount = count;
|
||||
*recvcount = count;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = *sendcount;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
BroadcastInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
if(rank == root)
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, ncclSum, rep, 1, 0));
|
||||
TESTCHECK(InitData(args->expected[i], recvcount, 0, type, ncclSum, rep, 1, 0));
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
BroadcastGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = 1;
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
BroadcastRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
int rank;
|
||||
NCCLCHECK(ncclCommUserRank(comm, &rank));
|
||||
#if NCCL_MAJOR >= 2 && NCCL_MINOR >= 2
|
||||
NCCLCHECK(ncclBroadcast(sendbuff, recvbuff, count, type, root, comm, stream));
|
||||
#else
|
||||
if(rank == root)
|
||||
{
|
||||
NCCLCHECK(ncclBcast(sendbuff, count, type, root, comm, stream));
|
||||
}
|
||||
else
|
||||
{
|
||||
NCCLCHECK(ncclBcast(recvbuff, count, type, root, comm, stream));
|
||||
}
|
||||
#endif
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl broadcastTest = { "Broadcast", BroadcastGetCollByteCount,
|
||||
BroadcastInitData, BroadcastGetBw, BroadcastRunColl };
|
||||
|
||||
void
|
||||
BroadcastGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
BroadcastGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
BroadcastRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &broadcastTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
int begin_root, end_root;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if(root != -1)
|
||||
{
|
||||
begin_root = end_root = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_root = 0;
|
||||
end_root = args->nProcs * args->nThreads * args->nGpus - 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = begin_root; j <= end_root; j++)
|
||||
{
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0,
|
||||
"none", j));
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { BroadcastGetBuffSize, BroadcastRunTest };
|
||||
文件差异内容过多而无法显示
加载差异
@@ -0,0 +1,431 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* Modifications Copyright (c) Microsoft Corporation. Licensed under the MIT License.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include "rccl/rccl.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <stdio.h>
|
||||
#ifdef MPI_SUPPORT
|
||||
# include "mpi.h"
|
||||
#endif
|
||||
#include "nccl1_compat.h"
|
||||
#include "timer.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
||||
// Ensures backward compatibility for FP8 types in RCCL 2.24.3 and later
|
||||
#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 24, 3)
|
||||
# define ncclFp8E4M3 ncclFloat8e4m3
|
||||
# define ncclFp8E5M2 ncclFloat8e5m2
|
||||
#endif
|
||||
|
||||
// For nccl.h < 2.13 since we define a weak fallback
|
||||
extern "C" char const*
|
||||
ncclGetLastError(ncclComm_t comm);
|
||||
|
||||
#define CUDACHECK(cmd) \
|
||||
do \
|
||||
{ \
|
||||
cudaError_t err = cmd; \
|
||||
if(err != cudaSuccess) \
|
||||
{ \
|
||||
char hostname[1024]; \
|
||||
getHostName(hostname, 1024); \
|
||||
printf("%s: Test CUDA failure %s:%d '%s'\n", hostname, __FILE__, __LINE__, \
|
||||
cudaGetErrorString(err)); \
|
||||
return testCudaError; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 13, 0)
|
||||
# define NCCLCHECK(cmd) \
|
||||
do \
|
||||
{ \
|
||||
ncclResult_t res = cmd; \
|
||||
if(res != ncclSuccess) \
|
||||
{ \
|
||||
char hostname[1024]; \
|
||||
getHostName(hostname, 1024); \
|
||||
printf("%s: Test NCCL failure %s:%d " \
|
||||
"'%s / %s'\n", \
|
||||
hostname, __FILE__, __LINE__, ncclGetErrorString(res), \
|
||||
ncclGetLastError(NULL)); \
|
||||
return testNcclError; \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
# define NCCLCHECK(cmd) \
|
||||
do \
|
||||
{ \
|
||||
ncclResult_t res = cmd; \
|
||||
if(res != ncclSuccess) \
|
||||
{ \
|
||||
char hostname[1024]; \
|
||||
getHostName(hostname, 1024); \
|
||||
printf("%s: Test NCCL failure %s:%d '%s'\n", hostname, __FILE__, \
|
||||
__LINE__, ncclGetErrorString(res)); \
|
||||
return testNcclError; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
testSuccess = 0,
|
||||
testInternalError = 1,
|
||||
testCudaError = 2,
|
||||
testNcclError = 3,
|
||||
testTimeout = 4,
|
||||
testNumResults = 5
|
||||
} testResult_t;
|
||||
|
||||
// Relay errors up and trace
|
||||
#define TESTCHECK(cmd) \
|
||||
do \
|
||||
{ \
|
||||
testResult_t r = cmd; \
|
||||
if(r != testSuccess) \
|
||||
{ \
|
||||
char hostname[1024]; \
|
||||
getHostName(hostname, 1024); \
|
||||
printf(" .. %s pid %d: Test failure %s:%d\n", hostname, getpid(), __FILE__, \
|
||||
__LINE__); \
|
||||
return r; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
struct testColl
|
||||
{
|
||||
const char name[20];
|
||||
void (*getCollByteCount)(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks);
|
||||
testResult_t (*initData)(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op,
|
||||
int root, int rep, int in_place);
|
||||
void (*getBw)(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks);
|
||||
testResult_t (*runColl)(void* sendbuff, void* recvbuff, size_t count,
|
||||
ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
ncclComm_t comm, cudaStream_t stream);
|
||||
};
|
||||
extern struct testColl allReduceTest;
|
||||
extern struct testColl allGatherTest;
|
||||
extern struct testColl reduceScatterTest;
|
||||
extern struct testColl broadcastTest;
|
||||
extern struct testColl reduceTest;
|
||||
extern struct testColl alltoAllTest;
|
||||
|
||||
class Reporter
|
||||
{
|
||||
public:
|
||||
Reporter(std::string fileName, std::string outputFormat);
|
||||
~Reporter()
|
||||
{
|
||||
if(_outputValid)
|
||||
{
|
||||
_out.close();
|
||||
}
|
||||
};
|
||||
void setParameters(const size_t numCycle, const char* name, const char* typeName,
|
||||
const char* opName);
|
||||
void addResult(int gpusPerRank, int ranksPerNode, int totalRanks, size_t numBytes,
|
||||
int inPlace, double timeUsec, double algBw, double busBw,
|
||||
int64_t wrongElts = -1);
|
||||
|
||||
private:
|
||||
bool isMainThread();
|
||||
template <typename T>
|
||||
std::pair<std::string, std::string> makeValueKeyPair(T v, std::string k)
|
||||
{
|
||||
return std::make_pair(std::to_string(v), k);
|
||||
};
|
||||
template <>
|
||||
std::pair<std::string, std::string> makeValueKeyPair<std::string>(std::string v,
|
||||
std::string k)
|
||||
{
|
||||
return std::make_pair("\"" + v + "\"", k);
|
||||
};
|
||||
|
||||
bool _outputValid = false;
|
||||
std::ofstream _out;
|
||||
std::string _outputFormat;
|
||||
size_t _numCycle = 0;
|
||||
std::string _collectiveName;
|
||||
std::string _typeName;
|
||||
std::string _opName;
|
||||
};
|
||||
|
||||
struct testEngine
|
||||
{
|
||||
void (*getBuffSize)(size_t* sendcount, size_t* recvcount, size_t count, int nranks);
|
||||
testResult_t (*runTest)(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName);
|
||||
};
|
||||
|
||||
extern struct testEngine ncclTestEngine;
|
||||
|
||||
struct threadArgs
|
||||
{
|
||||
size_t nbytes;
|
||||
size_t minbytes;
|
||||
size_t maxbytes;
|
||||
size_t stepbytes;
|
||||
size_t stepfactor;
|
||||
|
||||
int totalProcs;
|
||||
int nProcs;
|
||||
int proc;
|
||||
int nThreads;
|
||||
int thread;
|
||||
int nGpus;
|
||||
int* gpus;
|
||||
int localRank;
|
||||
int enable_out_of_place;
|
||||
int enable_in_place;
|
||||
int enable_cache_flush;
|
||||
int enable_rotating_tensor;
|
||||
void** sendbuffs;
|
||||
size_t sendBytes;
|
||||
size_t sendInplaceOffset;
|
||||
void** recvbuffs;
|
||||
size_t recvInplaceOffset;
|
||||
ncclUniqueId ncclId;
|
||||
ncclComm_t* comms;
|
||||
cudaStream_t* streams;
|
||||
|
||||
void** expected;
|
||||
size_t expectedBytes;
|
||||
int* errors;
|
||||
double* bw;
|
||||
int* bw_count;
|
||||
|
||||
int reportErrors;
|
||||
|
||||
struct testColl* collTest;
|
||||
|
||||
Reporter* reporter;
|
||||
};
|
||||
|
||||
typedef testResult_t (*threadFunc_t)(struct threadArgs* args);
|
||||
struct testThread
|
||||
{
|
||||
pthread_t thread;
|
||||
threadFunc_t func;
|
||||
struct threadArgs args;
|
||||
testResult_t ret;
|
||||
};
|
||||
|
||||
// Provided by common.cu
|
||||
extern void
|
||||
Barrier(struct threadArgs* args);
|
||||
extern testResult_t
|
||||
TimeTest(struct threadArgs* args, ncclDataType_t type, const char* typeName,
|
||||
ncclRedOp_t op, const char* opName, int root);
|
||||
extern testResult_t
|
||||
InitDataReduce(void* data, const size_t count, const size_t offset, ncclDataType_t type,
|
||||
ncclRedOp_t op, const uint64_t seed, const int nranks);
|
||||
extern testResult_t
|
||||
InitData(void* data, const size_t count, size_t offset, ncclDataType_t type,
|
||||
ncclRedOp_t op, const uint64_t seed, const int nranks, const int rank);
|
||||
extern void
|
||||
AllocateBuffs(void** sendbuff, void** recvbuff, void** expected, void** expectedHost,
|
||||
size_t nbytes, int nranks);
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
getHostName(char* hostname, int maxlen)
|
||||
{
|
||||
gethostname(hostname, maxlen);
|
||||
for(int i = 0; i < maxlen; i++)
|
||||
{
|
||||
if(hostname[i] == '.')
|
||||
{
|
||||
hostname[i] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static uint64_t
|
||||
getHash(const char* string, size_t n)
|
||||
{
|
||||
// Based on DJB2a, result = result * 33 ^ char
|
||||
uint64_t result = 5381;
|
||||
for(size_t c = 0; c < n; c++)
|
||||
{
|
||||
result = ((result << 5) + result) ^ string[c];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Generate a hash of the unique identifying string for this host
|
||||
* that will be unique for both bare-metal and container instances
|
||||
* Equivalent of a hash of;
|
||||
*
|
||||
* $(hostname)$(cat /proc/sys/kernel/random/boot_id)
|
||||
*
|
||||
*/
|
||||
#define HOSTID_FILE "/proc/sys/kernel/random/boot_id"
|
||||
static uint64_t
|
||||
getHostHash(const char* hostname)
|
||||
{
|
||||
char hostHash[1024];
|
||||
|
||||
// Fall back is the hostname if something fails
|
||||
(void) strncpy(hostHash, hostname, sizeof(hostHash));
|
||||
int offset = strlen(hostHash);
|
||||
|
||||
FILE* file = fopen(HOSTID_FILE, "r");
|
||||
if(file != NULL)
|
||||
{
|
||||
char* p;
|
||||
if(fscanf(file, "%ms", &p) == 1)
|
||||
{
|
||||
strncpy(hostHash + offset, p, sizeof(hostHash) - offset - 1);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Make sure the string is terminated
|
||||
hostHash[sizeof(hostHash) - 1] = '\0';
|
||||
|
||||
return getHash(hostHash, strlen(hostHash));
|
||||
}
|
||||
|
||||
static size_t
|
||||
wordSize(ncclDataType_t type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ncclChar:
|
||||
#if NCCL_MAJOR >= 2
|
||||
// case ncclInt8:
|
||||
case ncclUint8:
|
||||
# if NCCL_MAJOR >= 2 && RCCL_FLOAT8 == 1
|
||||
case ncclFp8E4M3:
|
||||
case ncclFp8E5M2:
|
||||
# endif
|
||||
#endif
|
||||
return 1;
|
||||
case ncclHalf:
|
||||
#if NCCL_MAJOR >= 2 && RCCL_BFLOAT16 == 1
|
||||
case ncclBfloat16:
|
||||
#endif
|
||||
// case ncclFloat16:
|
||||
return 2;
|
||||
case ncclInt:
|
||||
case ncclFloat:
|
||||
#if NCCL_MAJOR >= 2
|
||||
// case ncclInt32:
|
||||
case ncclUint32:
|
||||
// case ncclFloat32:
|
||||
#endif
|
||||
return 4;
|
||||
case ncclInt64:
|
||||
case ncclUint64:
|
||||
case ncclDouble:
|
||||
// case ncclFloat64:
|
||||
return 8;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern int test_ncclVersion; // init'd with ncclGetVersion()
|
||||
typedef enum
|
||||
{
|
||||
ncclCoarse = 0,
|
||||
ncclFine = 1,
|
||||
ncclHost = 2,
|
||||
ncclManaged = 3,
|
||||
nccl_NUM_MTYPES = 4
|
||||
} ncclMemoryType_t;
|
||||
extern const char* test_memorytypes[nccl_NUM_MTYPES];
|
||||
constexpr int test_opNumMax =
|
||||
(int) ncclNumOps + (NCCL_VERSION_CODE >= NCCL_VERSION(2, 11, 0) ? 1 : 0);
|
||||
extern int test_opnum;
|
||||
extern int test_typenum;
|
||||
extern ncclDataType_t test_types[ncclNumTypes];
|
||||
extern const char* test_typenames[ncclNumTypes];
|
||||
extern ncclRedOp_t test_ops[];
|
||||
extern const char* test_opnames[];
|
||||
|
||||
static int
|
||||
ncclstringtotype(char* str)
|
||||
{
|
||||
for(int t = 0; t < test_typenum; t++)
|
||||
{
|
||||
if(strcmp(str, test_typenames[t]) == 0)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
if(strcmp(str, "all") == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
printf("invalid type %s, defaulting to %s .. \n", str, test_typenames[ncclFloat]);
|
||||
return ncclFloat;
|
||||
}
|
||||
|
||||
static int
|
||||
ncclstringtoop(char* str)
|
||||
{
|
||||
for(int o = 0; o < test_opnum; o++)
|
||||
{
|
||||
if(strcmp(str, test_opnames[o]) == 0)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
}
|
||||
if(strcmp(str, "all") == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
printf("invalid op %s, defaulting to %s .. \n", str, test_opnames[ncclSum]);
|
||||
return ncclSum;
|
||||
}
|
||||
|
||||
static int
|
||||
ncclstringtoroot(char* str)
|
||||
{
|
||||
if(strcmp(str, "all") == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return strtol(str, NULL, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
ncclstringtomtype(char* str)
|
||||
{
|
||||
for(int o = 0; o < nccl_NUM_MTYPES; o++)
|
||||
{
|
||||
if(strcmp(str, test_memorytypes[o]) == 0)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
}
|
||||
printf("invalid memorytype %s, defaulting to %s .. \n", str,
|
||||
test_memorytypes[ncclCoarse]);
|
||||
return ncclCoarse;
|
||||
}
|
||||
|
||||
extern int is_main_proc;
|
||||
extern thread_local int is_main_thread;
|
||||
#define PRINT \
|
||||
if(is_main_thread) printf
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
GatherGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset, size_t count,
|
||||
size_t eltSize, int nranks)
|
||||
{
|
||||
*sendcount = (count / nranks) & -(16 / eltSize);
|
||||
*recvcount = (*sendcount) * nranks;
|
||||
*sendInplaceOffset = *sendcount;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = *sendcount;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
GatherInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? ((char*) args->recvbuffs[i]) + rank * args->sendBytes
|
||||
: args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, rank * sendcount, type, ncclSum, rep, 1, 0));
|
||||
CUDACHECK(cudaMemcpy(args->expected[i], args->recvbuffs[i], args->expectedBytes,
|
||||
cudaMemcpyDefault));
|
||||
if(rank == root)
|
||||
{
|
||||
TESTCHECK(InitData(args->expected[i], nranks * sendcount, 0, type, ncclSum,
|
||||
rep, 1, 0));
|
||||
}
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
GatherGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * nranks * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (nranks - 1)) / ((double) (nranks));
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
GatherRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
int nRanks;
|
||||
NCCLCHECK(ncclCommCount(comm, &nRanks));
|
||||
int rank;
|
||||
NCCLCHECK(ncclCommUserRank(comm, &rank));
|
||||
size_t rankOffset = count * wordSize(type);
|
||||
if(count == 0) return testSuccess;
|
||||
|
||||
NCCLCHECK(ncclGroupStart());
|
||||
NCCLCHECK(ncclSend(sendbuff, count, type, root, comm, stream));
|
||||
if(rank == root)
|
||||
{
|
||||
for(int r = 0; r < nRanks; r++)
|
||||
{
|
||||
NCCLCHECK(ncclRecv(((char*) recvbuff) + r * rankOffset, count, type, r, comm,
|
||||
stream));
|
||||
}
|
||||
}
|
||||
NCCLCHECK(ncclGroupEnd());
|
||||
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl gatherTest = { "Gather", GatherGetCollByteCount, GatherInitData,
|
||||
GatherGetBw, GatherRunColl };
|
||||
|
||||
void
|
||||
GatherGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
GatherGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
GatherRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &gatherTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
int begin_root, end_root;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if(root != -1)
|
||||
{
|
||||
begin_root = end_root = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_root = 0;
|
||||
end_root = args->nProcs * args->nThreads * args->nGpus - 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = begin_root; j <= end_root; j++)
|
||||
{
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0,
|
||||
"none", j));
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { GatherGetBuffSize, GatherRunTest };
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef RCCL_TESTS_GIT_VERSION_H_
|
||||
#define RCCL_TESTS_GIT_VERSION_H_
|
||||
|
||||
extern const char* rcclTestsGitHash;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,144 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
#define ALIGN 4
|
||||
|
||||
void
|
||||
HyperCubeGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
size_t base = (count / nranks) & -(16 / eltSize);
|
||||
*sendcount = base;
|
||||
*recvcount = base * nranks;
|
||||
*sendInplaceOffset = base;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = base;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
HyperCubeInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? ((char*) args->recvbuffs[i]) + rank * args->sendBytes
|
||||
: args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, ncclSum, 33 * rep + rank, 1, 0));
|
||||
for(int j = 0; j < nranks; j++)
|
||||
{
|
||||
TESTCHECK(InitData((char*) args->expected[i] + args->sendBytes * j, sendcount,
|
||||
0, type, ncclSum, 33 * rep + j, 1, 0));
|
||||
}
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
HyperCubeGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize * (nranks - 1)) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = 1;
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
HyperCubeRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
char* sbuff = (char*) sendbuff;
|
||||
char* rbuff = (char*) recvbuff;
|
||||
int nRanks;
|
||||
NCCLCHECK(ncclCommCount(comm, &nRanks));
|
||||
int rank;
|
||||
NCCLCHECK(ncclCommUserRank(comm, &rank));
|
||||
size_t rankSize = count * wordSize(type);
|
||||
if(rbuff + rank * rankSize != sbuff)
|
||||
CUDACHECK(cudaMemcpyAsync(rbuff + rank * rankSize, sbuff, rankSize,
|
||||
cudaMemcpyDeviceToDevice, stream));
|
||||
|
||||
// Hypercube AllGather
|
||||
for(int mask = 1; mask < nRanks; mask <<= 1)
|
||||
{
|
||||
NCCLCHECK(ncclGroupStart());
|
||||
int s = rank & ~(mask - 1);
|
||||
int r = s ^ mask;
|
||||
NCCLCHECK(ncclSend(rbuff + s * rankSize, count * mask, type, rank ^ mask, comm,
|
||||
stream));
|
||||
NCCLCHECK(ncclRecv(rbuff + r * rankSize, count * mask, type, rank ^ mask, comm,
|
||||
stream));
|
||||
NCCLCHECK(ncclGroupEnd());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl hyperCubeTest = { "HyperCube", HyperCubeGetCollByteCount,
|
||||
HyperCubeInitData, HyperCubeGetBw, HyperCubeRunColl };
|
||||
|
||||
void
|
||||
HyperCubeGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
HyperCubeGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
HyperCubeRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &hyperCubeTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
// Check if this is a power of 2
|
||||
int nRanks = args->nProcs * args->nThreads * args->nGpus;
|
||||
if(nRanks && !(nRanks & (nRanks - 1)))
|
||||
{
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
TESTCHECK(
|
||||
TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0, "", -1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("nRanks %d is not a power of 2, skipping\n", nRanks);
|
||||
}
|
||||
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { HyperCubeGetBuffSize, HyperCubeRunTest };
|
||||
@@ -0,0 +1,70 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#ifndef NCCL1_COMPAT_H
|
||||
#define NCCL1_COMPAT_H
|
||||
|
||||
#ifndef NCCL_MAJOR // NCCL 1.x
|
||||
# define NCCL_MAJOR 1
|
||||
# define NCCL_MINOR 0
|
||||
|
||||
# define ncclNumOps nccl_NUM_OPS
|
||||
# define ncclNumTypes nccl_NUM_TYPES
|
||||
|
||||
static ncclResult_t
|
||||
ncclGroupStart()
|
||||
{
|
||||
return ncclSuccess;
|
||||
}
|
||||
static ncclResult_t
|
||||
ncclGroupEnd()
|
||||
{
|
||||
return ncclSuccess;
|
||||
}
|
||||
|
||||
# define CHECKCOUNT(count) \
|
||||
if(count > INT_MAX) return ncclInvalidArgument;
|
||||
|
||||
static ncclResult_t
|
||||
ncclReduce(const void* sendbuff, void* recvbuff, size_t count, ncclDataType_t datatype,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
CHECKCOUNT(count);
|
||||
return ncclReduce(sendbuff, recvbuff, (int) count, datatype, op, root, comm, stream);
|
||||
}
|
||||
static ncclResult_t
|
||||
ncclAllReduce(const void* sendbuff, void* recvbuff, size_t count, ncclDataType_t datatype,
|
||||
ncclRedOp_t op, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
CHECKCOUNT(count);
|
||||
return ncclAllReduce(sendbuff, recvbuff, (int) count, datatype, op, comm, stream);
|
||||
}
|
||||
static ncclResult_t
|
||||
ncclBcast(void* buff, size_t count, ncclDataType_t datatype, int root, ncclComm_t comm,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
CHECKCOUNT(count);
|
||||
return ncclBcast(buff, (int) count, datatype, root, comm, stream);
|
||||
}
|
||||
static ncclResult_t
|
||||
ncclReduceScatter(const void* sendbuff, void* recvbuff, size_t recvcount,
|
||||
ncclDataType_t datatype, ncclRedOp_t op, ncclComm_t comm,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
CHECKCOUNT(recvcount);
|
||||
return ncclReduceScatter(sendbuff, recvbuff, (int) recvcount, datatype, op, comm,
|
||||
stream);
|
||||
}
|
||||
static ncclResult_t
|
||||
ncclAllGather(const void* sendbuff, void* recvbuff, size_t sendcount,
|
||||
ncclDataType_t datatype, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
CHECKCOUNT(sendcount);
|
||||
return ncclAllGather(sendbuff, (int) sendcount, datatype, recvbuff, comm, stream);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
文件差异内容过多而无法显示
加载差异
@@ -0,0 +1,142 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
ReduceGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset, size_t count,
|
||||
size_t eltSize, int nranks)
|
||||
{
|
||||
*sendcount = count;
|
||||
*recvcount = count;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = *sendcount;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ReduceInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, op, rep, nranks, rank));
|
||||
CUDACHECK(cudaMemcpy(args->expected[i], args->recvbuffs[i], args->expectedBytes,
|
||||
cudaMemcpyDefault));
|
||||
if(rank == root)
|
||||
TESTCHECK(
|
||||
InitDataReduce(args->expected[i], recvcount, 0, type, op, rep, nranks));
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
ReduceGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize) / 1.0E9 / sec;
|
||||
*algBw = baseBw;
|
||||
*busBw = baseBw;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ReduceRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
NCCLCHECK(ncclReduce(sendbuff, recvbuff, count, type, op, root, comm, stream));
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl reduceTest = { "Reduce", ReduceGetCollByteCount, ReduceInitData,
|
||||
ReduceGetBw, ReduceRunColl };
|
||||
|
||||
void
|
||||
ReduceGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
ReduceGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ReduceRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &reduceTest;
|
||||
ncclDataType_t* run_types;
|
||||
ncclRedOp_t* run_ops;
|
||||
const char ** run_typenames, **run_opnames;
|
||||
int type_count, op_count;
|
||||
int begin_root, end_root;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if((int) op != -1)
|
||||
{
|
||||
op_count = 1;
|
||||
run_ops = &op;
|
||||
run_opnames = &opName;
|
||||
}
|
||||
else
|
||||
{
|
||||
op_count = test_opnum;
|
||||
run_ops = test_ops;
|
||||
run_opnames = test_opnames;
|
||||
}
|
||||
|
||||
if(root != -1)
|
||||
{
|
||||
begin_root = end_root = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_root = 0;
|
||||
end_root = args->nProcs * args->nThreads * args->nGpus - 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = 0; j < op_count; j++)
|
||||
{
|
||||
#if defined(RCCL_FLOAT8)
|
||||
if((run_types[i] == ncclFp8E4M3 || run_types[i] == ncclFp8E5M2) &&
|
||||
run_ops[j] == ncclProd)
|
||||
continue;
|
||||
#endif
|
||||
for(int k = begin_root; k <= end_root; k++)
|
||||
{
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], run_ops[j],
|
||||
run_opnames[j], k));
|
||||
}
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { ReduceGetBuffSize, ReduceRunTest };
|
||||
@@ -0,0 +1,131 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
ReduceScatterGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
size_t base = (count / nranks) & -(16 / eltSize);
|
||||
*sendcount = base * nranks;
|
||||
*recvcount = base;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = base;
|
||||
*paramcount = base;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ReduceScatterInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op,
|
||||
int root, int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, op, rep, nranks, rank));
|
||||
CUDACHECK(cudaMemcpy(args->expected[i], args->recvbuffs[i], args->expectedBytes,
|
||||
cudaMemcpyDefault));
|
||||
TESTCHECK(InitDataReduce(args->expected[i], recvcount, rank * recvcount, type, op,
|
||||
rep, nranks));
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
ReduceScatterGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize * nranks) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (nranks - 1)) / ((double) nranks);
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ReduceScatterRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
NCCLCHECK(ncclReduceScatter(sendbuff, recvbuff, count, type, op, comm, stream));
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl reduceScatterTest = { "ReduceScatter", ReduceScatterGetCollByteCount,
|
||||
ReduceScatterInitData, ReduceScatterGetBw,
|
||||
ReduceScatterRunColl };
|
||||
|
||||
void
|
||||
ReduceScatterGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
ReduceScatterGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ReduceScatterRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &reduceScatterTest;
|
||||
ncclDataType_t* run_types;
|
||||
ncclRedOp_t* run_ops;
|
||||
const char ** run_typenames, **run_opnames;
|
||||
int type_count, op_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if((int) op != -1)
|
||||
{
|
||||
run_ops = &op;
|
||||
run_opnames = &opName;
|
||||
op_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
op_count = test_opnum;
|
||||
run_ops = test_ops;
|
||||
run_opnames = test_opnames;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = 0; j < op_count; j++)
|
||||
{
|
||||
#if defined(RCCL_FLOAT8)
|
||||
if((run_types[i] == ncclFp8E4M3 || run_types[i] == ncclFp8E5M2) &&
|
||||
run_ops[j] == ncclProd)
|
||||
continue;
|
||||
#endif
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], run_ops[j],
|
||||
run_opnames[j], -1));
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { ReduceScatterGetBuffSize, ReduceScatterRunTest };
|
||||
@@ -0,0 +1,137 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2020-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
ScatterGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
*recvcount = (count / nranks) & -(16 / eltSize);
|
||||
*sendcount = (*recvcount) * nranks;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = *recvcount;
|
||||
*paramcount = *recvcount;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ScatterInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
if(rank == root)
|
||||
TESTCHECK(InitData(data, sendcount, 0, type, ncclSum, rep, 1, 0));
|
||||
TESTCHECK(InitData(args->expected[i], recvcount, rank * recvcount, type, ncclSum,
|
||||
rep, 1, 0));
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
ScatterGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * nranks * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = ((double) (nranks - 1)) / ((double) (nranks));
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ScatterRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
int nRanks;
|
||||
NCCLCHECK(ncclCommCount(comm, &nRanks));
|
||||
int rank;
|
||||
NCCLCHECK(ncclCommUserRank(comm, &rank));
|
||||
size_t rankOffset = count * wordSize(type);
|
||||
if(count == 0) return testSuccess;
|
||||
|
||||
NCCLCHECK(ncclGroupStart());
|
||||
if(rank == root)
|
||||
{
|
||||
for(int r = 0; r < nRanks; r++)
|
||||
{
|
||||
NCCLCHECK(ncclSend(((char*) sendbuff) + r * rankOffset, count, type, r, comm,
|
||||
stream));
|
||||
}
|
||||
}
|
||||
NCCLCHECK(ncclRecv(recvbuff, count, type, root, comm, stream));
|
||||
NCCLCHECK(ncclGroupEnd());
|
||||
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl scatterTest = { "Scatter", ScatterGetCollByteCount, ScatterInitData,
|
||||
ScatterGetBw, ScatterRunColl };
|
||||
|
||||
void
|
||||
ScatterGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
ScatterGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
ScatterRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &scatterTest;
|
||||
ncclDataType_t* run_types;
|
||||
const char** run_typenames;
|
||||
int type_count;
|
||||
int begin_root, end_root;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if(root != -1)
|
||||
{
|
||||
begin_root = end_root = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_root = 0;
|
||||
end_root = args->nProcs * args->nThreads * args->nGpus - 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = begin_root; j <= end_root; j++)
|
||||
{
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], (ncclRedOp_t) 0,
|
||||
"none", j));
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { ScatterGetBuffSize, ScatterRunTest };
|
||||
@@ -0,0 +1,135 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Modifications Copyright (c) 2020-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "cuda_runtime.h"
|
||||
|
||||
void
|
||||
SendRecvGetCollByteCount(size_t* sendcount, size_t* recvcount, size_t* paramcount,
|
||||
size_t* sendInplaceOffset, size_t* recvInplaceOffset,
|
||||
size_t count, size_t eltSize, int nranks)
|
||||
{
|
||||
*sendcount = count;
|
||||
*recvcount = count;
|
||||
*sendInplaceOffset = 0;
|
||||
*recvInplaceOffset = 0;
|
||||
*paramcount = *sendcount;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
SendRecvInitData(struct threadArgs* args, ncclDataType_t type, ncclRedOp_t op, int root,
|
||||
int rep, int in_place)
|
||||
{
|
||||
size_t sendcount = args->sendBytes / wordSize(type);
|
||||
size_t recvcount = args->expectedBytes / wordSize(type);
|
||||
int nranks = args->nProcs * args->nThreads * args->nGpus;
|
||||
|
||||
for(int i = 0; i < args->nGpus; i++)
|
||||
{
|
||||
CUDACHECK(cudaSetDevice(args->gpus[i]));
|
||||
int rank = ((args->proc * args->nThreads + args->thread) * args->nGpus + i);
|
||||
CUDACHECK(cudaMemset(args->recvbuffs[i], 0, args->expectedBytes));
|
||||
void* data = in_place ? args->recvbuffs[i] : args->sendbuffs[i];
|
||||
TESTCHECK(InitData(data, sendcount, rank * sendcount, type, ncclSum, rep, 1, 0));
|
||||
int peer = (rank - 1 + nranks) % nranks;
|
||||
TESTCHECK(InitData(args->expected[i], recvcount, peer * recvcount, type, ncclSum,
|
||||
rep, 1, 0));
|
||||
CUDACHECK(cudaDeviceSynchronize());
|
||||
}
|
||||
// We don't support in-place sendrecv
|
||||
args->reportErrors = in_place ? 0 : 1;
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
SendRecvGetBw(size_t count, int typesize, double sec, double* algBw, double* busBw,
|
||||
int nranks)
|
||||
{
|
||||
double baseBw = (double) (count * typesize) / 1.0E9 / sec;
|
||||
|
||||
*algBw = baseBw;
|
||||
double factor = 1;
|
||||
*busBw = baseBw * factor;
|
||||
}
|
||||
|
||||
testResult_t
|
||||
SendRecvRunColl(void* sendbuff, void* recvbuff, size_t count, ncclDataType_t type,
|
||||
ncclRedOp_t op, int root, ncclComm_t comm, cudaStream_t stream)
|
||||
{
|
||||
int nRanks;
|
||||
NCCLCHECK(ncclCommCount(comm, &nRanks));
|
||||
int rank;
|
||||
NCCLCHECK(ncclCommUserRank(comm, &rank));
|
||||
int recvPeer = (rank - 1 + nRanks) % nRanks;
|
||||
int sendPeer = (rank + 1) % nRanks;
|
||||
|
||||
NCCLCHECK(ncclGroupStart());
|
||||
NCCLCHECK(ncclSend(sendbuff, count, type, sendPeer, comm, stream));
|
||||
NCCLCHECK(ncclRecv(recvbuff, count, type, recvPeer, comm, stream));
|
||||
NCCLCHECK(ncclGroupEnd());
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testColl sendRecvTest = { "SendRecv", SendRecvGetCollByteCount, SendRecvInitData,
|
||||
SendRecvGetBw, SendRecvRunColl };
|
||||
|
||||
void
|
||||
SendRecvGetBuffSize(size_t* sendcount, size_t* recvcount, size_t count, int nranks)
|
||||
{
|
||||
size_t paramcount, sendInplaceOffset, recvInplaceOffset;
|
||||
SendRecvGetCollByteCount(sendcount, recvcount, ¶mcount, &sendInplaceOffset,
|
||||
&recvInplaceOffset, count, /*eltSize=*/1, nranks);
|
||||
}
|
||||
|
||||
testResult_t
|
||||
SendRecvRunTest(struct threadArgs* args, int root, ncclDataType_t type,
|
||||
const char* typeName, ncclRedOp_t op, const char* opName)
|
||||
{
|
||||
args->collTest = &sendRecvTest;
|
||||
ncclDataType_t* run_types;
|
||||
ncclRedOp_t* run_ops;
|
||||
const char ** run_typenames, **run_opnames;
|
||||
int type_count, op_count;
|
||||
|
||||
if((int) type != -1)
|
||||
{
|
||||
type_count = 1;
|
||||
run_types = &type;
|
||||
run_typenames = &typeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_count = test_typenum;
|
||||
run_types = test_types;
|
||||
run_typenames = test_typenames;
|
||||
}
|
||||
|
||||
if((int) op != -1)
|
||||
{
|
||||
op_count = 1;
|
||||
run_ops = &op;
|
||||
run_opnames = &opName;
|
||||
}
|
||||
else
|
||||
{
|
||||
op_count = test_opnum;
|
||||
run_ops = test_ops;
|
||||
run_opnames = test_opnames;
|
||||
}
|
||||
|
||||
for(int i = 0; i < type_count; i++)
|
||||
{
|
||||
for(int j = 0; j < op_count; j++)
|
||||
{
|
||||
TESTCHECK(TimeTest(args, run_types[i], run_typenames[i], run_ops[j],
|
||||
run_opnames[j], -1));
|
||||
}
|
||||
}
|
||||
return testSuccess;
|
||||
}
|
||||
|
||||
struct testEngine ncclTestEngine = { SendRecvGetBuffSize, SendRecvRunTest };
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "timer.h"
|
||||
|
||||
// Make sure to compile this translation unit with the host compiler and not
|
||||
// nvcc, lest you hit an internal compiler error (ICE) with GCC 10.3.0
|
||||
#include <chrono>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::uint64_t
|
||||
now()
|
||||
{
|
||||
using clock = std::chrono::steady_clock;
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
timer::timer() { t0 = now(); }
|
||||
|
||||
double
|
||||
timer::elapsed() const
|
||||
{
|
||||
std::uint64_t t1 = now();
|
||||
return 1.e-9 * (t1 - t0);
|
||||
}
|
||||
|
||||
double
|
||||
timer::reset()
|
||||
{
|
||||
std::uint64_t t1 = now();
|
||||
double ans = 1.e-9 * (t1 - t0);
|
||||
t0 = t1;
|
||||
return ans;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef _408319ecdd5b47b28bf8f511c4fdf816
|
||||
#define _408319ecdd5b47b28bf8f511c4fdf816
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Can't include <chrono> because of bug with gcc 10.3.0
|
||||
class timer
|
||||
{
|
||||
std::uint64_t t0;
|
||||
|
||||
public:
|
||||
timer();
|
||||
double elapsed() const;
|
||||
double reset();
|
||||
};
|
||||
|
||||
#endif
|
||||
在新工单中引用
屏蔽一个用户