Add and update samples for cuda 11.0 support

This commit is contained in:
Mahesh Doijade
2020-05-18 22:22:06 +05:30
parent 6be514679b
commit 4f6e02970b
410 changed files with 21920 additions and 3864 deletions

View File

@@ -72,9 +72,9 @@ endif
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 ppc64le armv7l))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 ppc64le))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
@@ -85,8 +85,17 @@ ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 ppc64le armv7l))
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-ppc64le))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
@@ -141,6 +150,8 @@ else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
@@ -185,19 +196,27 @@ ifneq ($(TARGET_ARCH),$(HOST_ARCH))
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L $(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L $(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L $(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -rpath=/usr/lib/aarch64-qnx-gnu -L/usr/lib/aarch64-qnx-gnu
ifneq ($(TARGET_FS),)
LDFLAGS += -rpath=$(TARGET_FS)/usr/lib -L $(TARGET_FS)/usr/lib
LDFLAGS += -rpath=$(TARGET_FS)/usr/libnvidia -L $(TARGET_FS)/usr/libnvidia
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
endif
endif
ifeq ($(TARGET_OS),qnx)
CCFLAGS += -DWIN_INTERFACE_CUSTOM
LDFLAGS += -lsocket
endif
# Install directory of different arch
@@ -206,6 +225,8 @@ ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
@@ -252,6 +273,12 @@ ifeq ($(TARGET_ARCH),aarch64)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on sbsa
ifeq ($(TARGET_ARCH),sbsa)
$(info >>> WARNING - conjugateGradientMultiDeviceCG is not supported on sbsa - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
@@ -263,11 +290,38 @@ LIBRARIES :=
################################################################################
#Detect if installed version of GCC supports required C++11
ifeq ($(TARGET_OS),linux)
empty :=
space := $(empty) $(empty)
GCCVERSIONSTRING := $(shell expr `$(HOST_COMPILER) -dumpversion`)
#Create version number without "."
GCCVERSION := $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f1 -d.)
GCCVERSION += $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f2 -d.)
GCCVERSION += $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f3 -d.)
# Make sure the version number has at least 3 decimals
GCCVERSION += 00
# Remove spaces from the version number
GCCVERSION := $(subst $(space),$(empty),$(GCCVERSION))
# Crop the version number to 3 decimals.
GCCVERSION := $(shell expr `echo $(GCCVERSION)` | cut -b1-3)
#$(warning $(GCCVERSION))
IS_MIN_VERSION := $(shell expr `echo $(GCCVERSION)` \>= 470)
ifeq ($(IS_MIN_VERSION), 1)
$(info >>> GCC Version is greater or equal to 4.7.0 <<<)
else
$(info >>> Waiving build. Minimum GCC version required is 4.7.0<<<)
SAMPLE_ENABLED := 0
endif
endif
# Gencode arguments
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64))
SMS ?= 60 61 70 72 75
SMS ?= 60 61 70 72 75 80
else
SMS ?= 60 61 70 75
SMS ?= 60 61 70 75 80
endif
ifeq ($(SMS),)
@@ -286,7 +340,7 @@ GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
endif
endif
ALL_CCFLAGS += -dc -maxrregcount=64
ALL_CCFLAGS += -dc -maxrregcount=64 --std=c++11
LIBRARIES += -lcudadevrt

View File

@@ -5,6 +5,7 @@
<cflags>
<flag>-dc</flag>
<flag>-maxrregcount=64</flag>
<flag>--std=c++11</flag>
</cflags>
<cuda_api_list>
<toolkit>cudaMemAdvise</toolkit>
@@ -31,6 +32,7 @@
<keyword>Sparse Matrix</keyword>
<keyword>Unified Memory</keyword>
<keyword>Multi-GPU</keyword>
<keyword>CPP11</keyword>
</keywords>
<libraries>
<library>cudadevrt</library>
@@ -52,6 +54,7 @@
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<supported_envs>
<env>
<arch>x86_64</arch>

View File

@@ -10,7 +10,7 @@ Unified Memory, Linear Algebra, Cooperative Groups, MultiDevice Cooperative Grou
## Supported SM Architectures
[SM 6.0 ](https://developer.nvidia.com/cuda-gpus) [SM 6.1 ](https://developer.nvidia.com/cuda-gpus) [SM 7.0 ](https://developer.nvidia.com/cuda-gpus) [SM 7.2 ](https://developer.nvidia.com/cuda-gpus) [SM 7.5 ](https://developer.nvidia.com/cuda-gpus)
[SM 6.0 ](https://developer.nvidia.com/cuda-gpus) [SM 6.1 ](https://developer.nvidia.com/cuda-gpus) [SM 7.0 ](https://developer.nvidia.com/cuda-gpus) [SM 7.2 ](https://developer.nvidia.com/cuda-gpus) [SM 7.5 ](https://developer.nvidia.com/cuda-gpus) [SM 8.0 ](https://developer.nvidia.com/cuda-gpus)
## Supported OSes
@@ -30,7 +30,7 @@ cudaMemAdvise, cudaMemPrefetchAsync, cudaLaunchCooperativeKernelMultiDevice, cud
## Prerequisites
Download and install the [CUDA Toolkit 10.2](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Download and install the [CUDA Toolkit 11.0](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run

View File

@@ -36,8 +36,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <map>
#include <iostream>
#include <set>
#include <utility>
#include <cuda_runtime.h>
@@ -46,6 +48,7 @@
#include <helper_functions.h> // helper for shared functions common to CUDA Samples
#include <cooperative_groups.h>
#include <cooperative_groups/reduce.h>
namespace cg = cooperative_groups;
@@ -201,37 +204,31 @@ __device__ void gpuSaxpy(float *x, float *y, float a, int size,
__device__ void gpuDotProduct(float *vecA, float *vecB, int size,
const cg::thread_block &cta,
const cg::multi_grid_group &multi_grid) {
__shared__ double tmp[THREADS_PER_BLOCK];
extern __shared__ double tmp[];
double temp_sum = 0.0;
for (int i = multi_grid.thread_rank(); i < size; i += multi_grid.size()) {
temp_sum += static_cast<double>(vecA[i] * vecB[i]);
}
tmp[cta.thread_rank()] = temp_sum;
cg::sync(cta);
cg::thread_block_tile<32> tile32 = cg::tiled_partition<32>(cta);
double beta = temp_sum;
double temp;
temp_sum = cg::reduce(tile32, temp_sum, cg::plus<double>());
for (int i = tile32.size() / 2; i > 0; i >>= 1) {
if (tile32.thread_rank() < i) {
temp = tmp[cta.thread_rank() + i];
beta += temp;
tmp[cta.thread_rank()] = beta;
}
cg::sync(tile32);
if (tile32.thread_rank() == 0) {
tmp[tile32.meta_group_rank()] = temp_sum;
}
cg::sync(cta);
if (cta.thread_rank() == 0) {
beta = 0.0;
for (int i = 0; i < cta.size(); i += tile32.size()) {
beta += tmp[i];
if (tile32.meta_group_rank() == 0) {
temp_sum = tile32.thread_rank() < tile32.meta_group_size() ? tmp[tile32.thread_rank()] : 0.0;
temp_sum = cg::reduce(tile32, temp_sum, cg::plus<double>());
if (tile32.thread_rank() == 0) {
atomicAdd(&grid_dot_result, temp_sum);
}
atomicAdd(&grid_dot_result, beta);
}
}
@@ -242,24 +239,13 @@ __device__ void gpuCopyVector(float *srcA, float *destB, int size,
}
}
__device__ void gpuScaleVector(float *vec, float alpha, int size,
const cg::multi_grid_group &multi_grid) {
__device__ void gpuScaleVectorAndSaxpy(float *x, float *y, float a, float scale, int size,
const cg::multi_grid_group &multi_grid) {
for (int i = multi_grid.thread_rank(); i < size; i += multi_grid.size()) {
vec[i] = alpha * vec[i];
y[i] = a * x[i] + scale * y[i];
}
}
__device__ void setDotResultToZero(double *dot_result) {
unsigned long long int *address_as_ull = (unsigned long long int *)dot_result;
unsigned long long int old = *address_as_ull, assumed;
do {
assumed = old;
old = atomicCAS_system(address_as_ull, assumed, 0);
} while (assumed != old);
}
extern "C" __global__ void multiGpuConjugateGradient(
int *I, int *J, float *val, float *x, float *Ax, float *p, float *r,
double *dot_result, int nnz, int N, float tol) {
@@ -304,10 +290,7 @@ extern "C" __global__ void multiGpuConjugateGradient(
while (r1 > tol * tol && k <= max_iter) {
if (k > 1) {
b = r1 / r0;
gpuScaleVector(p, b, N, multi_grid);
cg::sync(grid);
gpuSaxpy(r, p, alpha, N, multi_grid);
gpuScaleVectorAndSaxpy(r, p, alpha, b, N, multi_grid);
} else {
gpuCopyVector(r, p, N, multi_grid);
}
@@ -317,7 +300,7 @@ extern "C" __global__ void multiGpuConjugateGradient(
gpuSpMV(I, J, val, nnz, N, alpha, p, Ax, cta, multi_grid);
if (multi_grid.thread_rank() == 0) {
setDotResultToZero(dot_result);
*dot_result = 0.0;
}
cg::sync(multi_grid);
@@ -343,7 +326,7 @@ extern "C" __global__ void multiGpuConjugateGradient(
cg::sync(multi_grid);
if (multi_grid.thread_rank() == 0) {
setDotResultToZero(dot_result);
*dot_result = 0.0;
}
cg::sync(multi_grid);
@@ -363,68 +346,31 @@ extern "C" __global__ void multiGpuConjugateGradient(
}
}
void getIdenticalGPUs(int num_of_gpus, std::set<int> &identicalGPUs) {
int *major_minor =
reinterpret_cast<int *>(malloc(sizeof(int) * num_of_gpus * 2));
int foundIdenticalGPUs = 0;
// Map of device version to device number
std::multimap<std::pair<int, int>, int> getIdenticalGPUs() {
int numGpus = 0;
checkCudaErrors(cudaGetDeviceCount(&numGpus));
for (int i = 0; i < num_of_gpus; i++) {
std::multimap<std::pair<int, int>, int> identicalGpus;
for (int i = 0; i < numGpus; i++) {
cudaDeviceProp deviceProp;
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, i));
major_minor[i * 2] = deviceProp.major;
major_minor[i * 2 + 1] = deviceProp.minor;
// Filter unsupported devices
if (deviceProp.cooperativeMultiDeviceLaunch &&
deviceProp.concurrentManagedAccess) {
identicalGpus.emplace(std::make_pair(deviceProp.major, deviceProp.minor), i);
}
printf("GPU Device %d: \"%s\" with compute capability %d.%d\n", i,
deviceProp.name, deviceProp.major, deviceProp.minor);
deviceProp.name, deviceProp.major, deviceProp.minor);
}
int maxMajorMinor[2] = {0, 0};
for (int i = 0; i < num_of_gpus; i++) {
for (int j = i + 1; j < num_of_gpus; j++) {
if ((major_minor[i * 2] == major_minor[j * 2]) &&
(major_minor[i * 2 + 1] == major_minor[j * 2 + 1])) {
identicalGPUs.insert(i);
identicalGPUs.insert(j);
foundIdenticalGPUs = 1;
if (maxMajorMinor[0] < major_minor[i * 2] &&
maxMajorMinor[1] < major_minor[i * 2 + 1]) {
maxMajorMinor[0] = major_minor[i * 2];
maxMajorMinor[1] = major_minor[i * 2 + 1];
}
}
}
}
free(major_minor);
if (!foundIdenticalGPUs) {
printf(
"No Two or more GPUs with same architecture found\nWaiving the "
"sample\n");
exit(EXIT_WAIVED);
}
std::set<int>::iterator it = identicalGPUs.begin();
// Iterate over all the identical GPUs found
while (it != identicalGPUs.end()) {
cudaDeviceProp deviceProp;
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, *it));
// Remove all the GPUs which are less than the best arch available
if (deviceProp.major != maxMajorMinor[0] &&
deviceProp.minor != maxMajorMinor[1]) {
identicalGPUs.erase(it);
}
if (!deviceProp.cooperativeMultiDeviceLaunch ||
!deviceProp.concurrentManagedAccess) {
identicalGPUs.erase(it);
}
it++;
}
return;
return identicalGpus;
}
int main(int argc, char **argv) {
constexpr size_t kNumGpusRequired = 2;
int N = 0, nz = 0, *I = NULL, *J = NULL;
float *val = NULL;
const float tol = 1e-5f;
@@ -434,33 +380,101 @@ int main(int argc, char **argv) {
float *r, *p, *Ax;
printf("Starting [%s]...\n", sSDKname);
auto gpusByArch = getIdenticalGPUs();
int num_of_gpus = 0;
checkCudaErrors(cudaGetDeviceCount(&num_of_gpus));
auto it = gpusByArch.begin();
auto end = gpusByArch.end();
if (num_of_gpus <= 1) {
printf("No. of GPU on node %d\n", num_of_gpus);
printf("Minimum Two or more GPUs are required to run this sample code\n");
exit(EXIT_WAIVED);
auto bestFit = std::make_pair(it, it);
// use std::distance to find the largest number of GPUs amongst architectures
auto distance = [](decltype(bestFit) p){return std::distance(p.first, p.second);};
// Read each unique key/pair element in order
for (; it != end; it = gpusByArch.upper_bound(it->first)) {
// first and second are iterators bounded within the architecture group
auto testFit = gpusByArch.equal_range(it->first);
// Always use devices with highest architecture version or whichever has the most devices available
if (distance(bestFit) <= distance(testFit))
bestFit = testFit;
}
std::set<int> identicalGPUs;
getIdenticalGPUs(num_of_gpus, identicalGPUs);
if (identicalGPUs.size() <= 1) {
if (distance(bestFit) < kNumGpusRequired) {
printf(
"No Two or more GPUs with same architecture capable of "
"cooperativeMultiDeviceLaunch & concurrentManagedAccess found. \nWaiving the sample\n");
"cooperativeMultiDeviceLaunch & concurrentManagedAccess found. "
"\nWaiving the sample\n");
exit(EXIT_WAIVED);
}
std::set<int>::iterator deviceId = identicalGPUs.begin();
std::set<int> bestFitDeviceIds;
// We use only 2 GPUs as for input size of N = 10485760*2 two GPUs are enough.
while (identicalGPUs.size() > 2) {
identicalGPUs.erase(deviceId);
deviceId++;
// check & select peer-to-peer access capable GPU devices as enabling p2p access between participating
// GPUs gives better performance for multi_grid sync.
for (auto itr = bestFit.first; itr != bestFit.second; itr++) {
int deviceId = itr->second;
checkCudaErrors(cudaSetDevice(deviceId));
std::for_each(itr, bestFit.second, [&deviceId, &bestFitDeviceIds](decltype(*itr) mapPair) {
if (deviceId != mapPair.second)
{
int access = 0;
checkCudaErrors(cudaDeviceCanAccessPeer(&access, deviceId, mapPair.second));
printf("Device=%d %s Access Peer Device=%d\n", deviceId, access ? "CAN" : "CANNOT", mapPair.second);
if (access && bestFitDeviceIds.size() < kNumGpusRequired) {
bestFitDeviceIds.emplace(deviceId);
bestFitDeviceIds.emplace(mapPair.second);
}
else {
printf("Ignoring device %i (max devices exceeded)\n", mapPair.second);
}
}
});
if (bestFitDeviceIds.size() >= kNumGpusRequired)
{
printf("Selected p2p capable devices - ");
for (auto devicesItr = bestFitDeviceIds.begin(); devicesItr != bestFitDeviceIds.end(); devicesItr++)
{
printf("deviceId = %d ", *devicesItr);
}
printf("\n");
break;
}
}
// if bestFitDeviceIds.size() == 0 it means the GPUs in system are not p2p capable,
// hence we add it without p2p capability check.
if (!bestFitDeviceIds.size())
{
printf("Devices involved are not p2p capable.. selecting %zu of them\n", kNumGpusRequired);
std::for_each(bestFit.first, bestFit.second, [&bestFitDeviceIds](decltype(*bestFit.first) mapPair) {
if (bestFitDeviceIds.size() < kNumGpusRequired) {
bestFitDeviceIds.emplace(mapPair.second);
}
else {
printf("Ignoring device %i (max devices exceeded)\n", mapPair.second);
}
// Insert the sequence into the deviceIds set
});
}
else
{
// perform cudaDeviceEnablePeerAccess in both directions for all participating devices
// of a cudaLaunchCooperativeKernelMultiDevice call this gives better performance for multi_grid sync.
for (auto p1_itr = bestFitDeviceIds.begin(); p1_itr != bestFitDeviceIds.end(); p1_itr++)
{
checkCudaErrors(cudaSetDevice(*p1_itr));
for (auto p2_itr = bestFitDeviceIds.begin(); p2_itr != bestFitDeviceIds.end(); p2_itr++)
{
if (*p1_itr != *p2_itr)
{
checkCudaErrors(cudaDeviceEnablePeerAccess(*p2_itr, 0 ));
checkCudaErrors(cudaSetDevice(*p1_itr));
}
}
}
}
/* Generate a random tridiagonal symmetric matrix in CSR format */
N = 10485760 * 2;
nz = (N - 2) * 3 + 4;
@@ -501,87 +515,94 @@ int main(int argc, char **argv) {
checkCudaErrors(
cudaMallocManaged(reinterpret_cast<void **>(&Ax), N * sizeof(float)));
std::cout << "\nRunning on GPUs = " << identicalGPUs.size() << std::endl;
cudaStream_t *nStreams = reinterpret_cast<cudaStream_t *>(
malloc(sizeof(cudaStream_t) * identicalGPUs.size()));
std::cout << "\nRunning on GPUs = " << kNumGpusRequired << std::endl;
cudaStream_t nStreams[kNumGpusRequired];
void *kernelArgs[] = {
(void *)&I, (void *)&J, (void *)&val, (void *)&x,
(void *)&Ax, (void *)&p, (void *)&r, (void *)&dot_result,
(void *)&nz, (void *)&N, (void *)&tol,
};
int sMemSize = sizeof(double) * THREADS_PER_BLOCK;
int numBlocksPerSm = 0;
int sMemSize = sizeof(double) * ((THREADS_PER_BLOCK/32) + 1);
int numBlocksPerSm = INT_MAX;
int numThreads = THREADS_PER_BLOCK;
int numSms = INT_MAX;
auto deviceId = bestFitDeviceIds.begin();
deviceId = identicalGPUs.begin();
cudaDeviceProp deviceProp;
checkCudaErrors(cudaSetDevice(*deviceId));
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, *deviceId));
checkCudaErrors(cudaOccupancyMaxActiveBlocksPerMultiprocessor(
&numBlocksPerSm, multiGpuConjugateGradient, numThreads, sMemSize));
int numSms = deviceProp.multiProcessorCount;
dim3 dimGrid(numSms * numBlocksPerSm, 1, 1),
dimBlock(THREADS_PER_BLOCK, 1, 1);
int device_count = 0;
int totalThreadsPerGPU = numSms * numBlocksPerSm * THREADS_PER_BLOCK;
while (deviceId != identicalGPUs.end()) {
// set numSms & numBlocksPerSm to be lowest of 2 devices
while (deviceId != bestFitDeviceIds.end()) {
cudaDeviceProp deviceProp;
checkCudaErrors(cudaSetDevice(*deviceId));
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, *deviceId));
int numBlocksPerSm_current=0;
checkCudaErrors(cudaOccupancyMaxActiveBlocksPerMultiprocessor(
&numBlocksPerSm_current, multiGpuConjugateGradient, numThreads, sMemSize));
if (numBlocksPerSm > numBlocksPerSm_current)
{
numBlocksPerSm = numBlocksPerSm_current;
}
if (numSms > deviceProp.multiProcessorCount)
{
numSms = deviceProp.multiProcessorCount;
}
deviceId++;
}
if (!numBlocksPerSm) {
printf(
"Max active blocks per SM is returned as 0.\n Hence, Waiving the "
"sample\n");
exit(EXIT_WAIVED);
}
int device_count = 0;
int totalThreadsPerGPU = numSms * numBlocksPerSm * THREADS_PER_BLOCK;
deviceId = bestFitDeviceIds.begin();;
while (deviceId != bestFitDeviceIds.end()) {
checkCudaErrors(cudaSetDevice(*deviceId));
checkCudaErrors(cudaStreamCreate(&nStreams[device_count]));
if (deviceProp.concurrentManagedAccess) {
int perGPUIter = N / (totalThreadsPerGPU * identicalGPUs.size());
int offset_Ax = device_count * totalThreadsPerGPU;
int offset_r = device_count * totalThreadsPerGPU;
int offset_p = device_count * totalThreadsPerGPU;
int offset_x = device_count * totalThreadsPerGPU;
int perGPUIter = N / (totalThreadsPerGPU * kNumGpusRequired);
int offset_Ax = device_count * totalThreadsPerGPU;
int offset_r = device_count * totalThreadsPerGPU;
int offset_p = device_count * totalThreadsPerGPU;
int offset_x = device_count * totalThreadsPerGPU;
checkCudaErrors(cudaMemPrefetchAsync(I, sizeof(int) * N, *deviceId,
nStreams[device_count]));
checkCudaErrors(cudaMemPrefetchAsync(val, sizeof(float) * nz, *deviceId,
nStreams[device_count]));
checkCudaErrors(cudaMemPrefetchAsync(J, sizeof(float) * nz, *deviceId,
nStreams[device_count]));
checkCudaErrors(cudaMemPrefetchAsync(I, sizeof(int) * N, *deviceId,
nStreams[device_count]));
checkCudaErrors(cudaMemPrefetchAsync(val, sizeof(float) * nz, *deviceId,
nStreams[device_count]));
checkCudaErrors(cudaMemPrefetchAsync(J, sizeof(float) * nz, *deviceId,
nStreams[device_count]));
if (offset_Ax <= N) {
for (int i = 0; i < perGPUIter; i++) {
cudaMemAdvise(Ax + offset_Ax, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(r + offset_r, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(x + offset_x, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(p + offset_p, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
if (offset_Ax <= N) {
for (int i = 0; i < perGPUIter; i++) {
cudaMemAdvise(Ax + offset_Ax, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(r + offset_r, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(x + offset_x, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(p + offset_p, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetPreferredLocation, *deviceId);
cudaMemAdvise(Ax + offset_Ax, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(r + offset_r, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(p + offset_p, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(x + offset_x, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(Ax + offset_Ax, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(r + offset_r, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(p + offset_p, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
cudaMemAdvise(x + offset_x, sizeof(float) * totalThreadsPerGPU,
cudaMemAdviseSetAccessedBy, *deviceId);
offset_Ax += totalThreadsPerGPU * identicalGPUs.size();
offset_r += totalThreadsPerGPU * identicalGPUs.size();
offset_p += totalThreadsPerGPU * identicalGPUs.size();
offset_x += totalThreadsPerGPU * identicalGPUs.size();
offset_Ax += totalThreadsPerGPU * kNumGpusRequired;
offset_r += totalThreadsPerGPU * kNumGpusRequired;
offset_p += totalThreadsPerGPU * kNumGpusRequired;
offset_x += totalThreadsPerGPU * kNumGpusRequired;
if (offset_Ax >= N) {
break;
}
if (offset_Ax >= N) {
break;
}
}
}
device_count++;
deviceId++;
}
@@ -600,11 +621,16 @@ int main(int argc, char **argv) {
printf("Total threads per GPU = %d numBlocksPerSm = %d\n",
numSms * numBlocksPerSm * THREADS_PER_BLOCK, numBlocksPerSm);
cudaLaunchParams *launchParamsList = reinterpret_cast<cudaLaunchParams *>(
malloc(sizeof(cudaLaunchParams) * identicalGPUs.size()));
for (int i = 0; i < identicalGPUs.size(); i++) {
launchParamsList[i].func =
reinterpret_cast<void *>(multiGpuConjugateGradient);
dim3 dimGrid(numSms * numBlocksPerSm, 1, 1), dimBlock(THREADS_PER_BLOCK, 1, 1);
void *kernelArgs[] = {
(void *)&I, (void *)&J, (void *)&val, (void *)&x,
(void *)&Ax, (void *)&p, (void *)&r, (void *)&dot_result,
(void *)&nz, (void *)&N, (void *)&tol,
};
cudaLaunchParams *launchParamsList = (cudaLaunchParams *)malloc(
sizeof(cudaLaunchParams) * kNumGpusRequired);
for (int i = 0; i < kNumGpusRequired; i++) {
launchParamsList[i].func = (void *)multiGpuConjugateGradient;
launchParamsList[i].gridDim = dimGrid;
launchParamsList[i].blockDim = dimBlock;
launchParamsList[i].sharedMem = sMemSize;
@@ -613,21 +639,20 @@ int main(int argc, char **argv) {
}
printf("Launching kernel\n");
checkCudaErrors(cudaLaunchCooperativeKernelMultiDevice(
launchParamsList, identicalGPUs.size(),
launchParamsList, kNumGpusRequired,
cudaCooperativeLaunchMultiDeviceNoPreSync |
cudaCooperativeLaunchMultiDeviceNoPostSync));
if (deviceProp.concurrentManagedAccess) {
checkCudaErrors(
cudaMemPrefetchAsync(x, sizeof(float) * N, cudaCpuDeviceId));
checkCudaErrors(
checkCudaErrors(
cudaMemPrefetchAsync(x, sizeof(float) * N, cudaCpuDeviceId));
checkCudaErrors(
cudaMemPrefetchAsync(dot_result, sizeof(double), cudaCpuDeviceId));
}
deviceId = identicalGPUs.begin();
deviceId = bestFitDeviceIds.begin();;
device_count = 0;
while (deviceId != identicalGPUs.end()) {
while (deviceId != bestFitDeviceIds.end()) {
checkCudaErrors(cudaSetDevice(*deviceId));
checkCudaErrors(cudaStreamSynchronize(nStreams[device_count++]));
deviceId++;

View File

@@ -62,7 +62,7 @@
<OutputFile>$(OutDir)/conjugateGradientMultiDeviceCG.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;</CodeGeneration>
<CodeGeneration>compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" %(AdditionalOptions)</AdditionalOptions>
<Include>./;../../Common</Include>
<Defines>WIN32</Defines>

View File

@@ -67,7 +67,7 @@
<OutputFile>$(OutDir)/conjugateGradientMultiDeviceCG.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;</CodeGeneration>
<CodeGeneration>compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" %(AdditionalOptions)</AdditionalOptions>
<Include>./;../../Common</Include>
<Defines>WIN32</Defines>

View File

@@ -63,7 +63,7 @@
<OutputFile>$(OutDir)/conjugateGradientMultiDeviceCG.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;</CodeGeneration>
<CodeGeneration>compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" %(AdditionalOptions)</AdditionalOptions>
<Include>./;../../Common</Include>
<Defines>WIN32</Defines>