mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-23 21:28:17 +08:00
Add and update samples for cuda 11.0 support
This commit is contained in:
@@ -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)
|
||||
@@ -234,6 +255,12 @@ ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
|
||||
|
||||
SAMPLE_ENABLED := 1
|
||||
|
||||
# This sample is not supported on QNX
|
||||
ifeq ($(TARGET_OS),qnx)
|
||||
$(info >>> WARNING - reduction is not supported on QNX - waiving sample <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
|
||||
ALL_LDFLAGS :=
|
||||
ALL_LDFLAGS += $(ALL_CCFLAGS)
|
||||
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
|
||||
@@ -245,11 +272,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 ?= 30 35 37 50 52 60 61 70 72 75
|
||||
SMS ?= 35 37 50 52 60 61 70 72 75 80
|
||||
else
|
||||
SMS ?= 30 35 37 50 52 60 61 70 75
|
||||
SMS ?= 35 37 50 52 60 61 70 75 80
|
||||
endif
|
||||
|
||||
ifeq ($(SMS),)
|
||||
@@ -268,6 +322,8 @@ GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
|
||||
endif
|
||||
endif
|
||||
|
||||
ALL_CCFLAGS += --std=c++11
|
||||
|
||||
ifeq ($(SAMPLE_ENABLED),0)
|
||||
EXEC ?= @echo "[@]"
|
||||
endif
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
|
||||
<entry>
|
||||
<name>reduction</name>
|
||||
<description><![CDATA[A parallel sum reduction that computes the sum of a large arrays of values. This sample demonstrates several important optimization strategies for Data-Parallel Algorithms like reduction.]]></description>
|
||||
<cflags>
|
||||
<flag>--std=c++11</flag>
|
||||
</cflags>
|
||||
<description><![CDATA[A parallel sum reduction that computes the sum of a large arrays of values. This sample demonstrates several important optimization strategies for Data-Parallel Algorithms like reduction using shared memory, __shfl_down_sync, __reduce_add_sync and cooperative_groups reduce.]]></description>
|
||||
<devicecompilation>whole</devicecompilation>
|
||||
<includepaths>
|
||||
<path>./</path>
|
||||
@@ -17,6 +20,7 @@
|
||||
<keyword>CUDA</keyword>
|
||||
<keyword>GPGPU</keyword>
|
||||
<keyword>Parallel Reduction</keyword>
|
||||
<keyword>CPP11</keyword>
|
||||
</keywords>
|
||||
<libraries>
|
||||
</libraries>
|
||||
@@ -24,12 +28,23 @@
|
||||
</librarypaths>
|
||||
<nsight_eclipse>true</nsight_eclipse>
|
||||
<primary_file>reduction.cpp</primary_file>
|
||||
<qatests>
|
||||
<qatest>-kernel 0</qatest>
|
||||
<qatest>-kernel 1</qatest>
|
||||
<qatest>-kernel 2</qatest>
|
||||
<qatest>-kernel 3</qatest>
|
||||
<qatest>-kernel 4</qatest>
|
||||
<qatest>-kernel 5</qatest>
|
||||
<qatest>-kernel 6</qatest>
|
||||
</qatests>
|
||||
<required_dependencies>
|
||||
<dependency>CPP11</dependency>
|
||||
</required_dependencies>
|
||||
<scopes>
|
||||
<scope>1:CUDA Advanced Topics</scope>
|
||||
<scope>1:Data-Parallel Algorithms</scope>
|
||||
<scope>1:Performance Strategies</scope>
|
||||
</scopes>
|
||||
<sm-arch>sm30</sm-arch>
|
||||
<sm-arch>sm35</sm-arch>
|
||||
<sm-arch>sm37</sm-arch>
|
||||
<sm-arch>sm50</sm-arch>
|
||||
@@ -39,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>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Description
|
||||
|
||||
A parallel sum reduction that computes the sum of a large arrays of values. This sample demonstrates several important optimization strategies for Data-Parallel Algorithms like reduction.
|
||||
A parallel sum reduction that computes the sum of a large arrays of values. This sample demonstrates several important optimization strategies for Data-Parallel Algorithms like reduction using shared memory, __shfl_down_sync, __reduce_add_sync and cooperative_groups reduce.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
@@ -10,11 +10,11 @@ Data-Parallel Algorithms, Performance Strategies
|
||||
|
||||
## Supported SM Architectures
|
||||
|
||||
[SM 3.0 ](https://developer.nvidia.com/cuda-gpus) [SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [SM 5.0 ](https://developer.nvidia.com/cuda-gpus) [SM 5.2 ](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 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [SM 5.0 ](https://developer.nvidia.com/cuda-gpus) [SM 5.2 ](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
|
||||
|
||||
Linux, Windows, MacOSX
|
||||
Linux, Windows
|
||||
|
||||
## Supported CPU Architecture
|
||||
|
||||
@@ -22,9 +22,13 @@ x86_64, ppc64le, armv7l
|
||||
|
||||
## CUDA APIs involved
|
||||
|
||||
## Dependencies needed to build/run
|
||||
[CPP11](../../README.md#cpp11)
|
||||
|
||||
## 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
|
||||
|
||||
@@ -63,29 +67,5 @@ The samples makefiles can take advantage of certain options:
|
||||
$ make HOST_COMPILER=g++
|
||||
```
|
||||
|
||||
### Mac
|
||||
The Mac samples are built using makefiles. To use the makefiles, change directory into the sample directory you wish to build, and run make:
|
||||
```
|
||||
$ cd <sample_dir>
|
||||
$ make
|
||||
```
|
||||
|
||||
The samples makefiles can take advantage of certain options:
|
||||
|
||||
* **dbg=1** - build with debug symbols
|
||||
```
|
||||
$ make dbg=1
|
||||
```
|
||||
|
||||
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where "A B ..." is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use SMS="50 60".
|
||||
```
|
||||
$ make SMS="A B ..."
|
||||
```
|
||||
|
||||
* **HOST_COMPILER=<host_compiler>** - override the default clang host compiler. See the [Mac Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#system-requirements) for a list of supported host compilers.
|
||||
```
|
||||
$ make HOST_COMPILER=clang
|
||||
```
|
||||
|
||||
## References (for more details)
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ void getNumBlocksAndThreads(int whichKernel, int n, int maxBlocks,
|
||||
threads *= 2;
|
||||
}
|
||||
|
||||
if (whichKernel == 6) {
|
||||
if (whichKernel >= 6) {
|
||||
blocks = MIN(maxBlocks, blocks);
|
||||
}
|
||||
}
|
||||
@@ -361,7 +361,7 @@ void shmoo(int minN, int maxN, int maxThreads, int maxBlocks,
|
||||
cudaMemcpyHostToDevice));
|
||||
|
||||
// warm-up
|
||||
for (int kernel = 0; kernel < 7; kernel++) {
|
||||
for (int kernel = 0; kernel < 8; kernel++) {
|
||||
reduce<T>(maxN, maxThreads, maxNumBlocks, kernel, d_idata, d_odata);
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ void shmoo(int minN, int maxN, int maxThreads, int maxBlocks,
|
||||
printf(", %d", i);
|
||||
}
|
||||
|
||||
for (int kernel = 0; kernel < 7; kernel++) {
|
||||
for (int kernel = 0; kernel < 8; kernel++) {
|
||||
printf("\n%d", kernel);
|
||||
|
||||
for (int i = minN; i <= maxN; i *= 2) {
|
||||
@@ -421,7 +421,7 @@ template <class T>
|
||||
bool runTest(int argc, char **argv, ReduceType datatype) {
|
||||
int size = 1 << 24; // number of elements to reduce
|
||||
int maxThreads = 256; // number of threads per block
|
||||
int whichKernel = 6;
|
||||
int whichKernel = 7;
|
||||
int maxBlocks = 64;
|
||||
bool cpuFinalReduction = false;
|
||||
int cpuFinalThreshold = 1;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define _REDUCE_KERNEL_H_
|
||||
|
||||
#include <cooperative_groups.h>
|
||||
#include <cooperative_groups/reduce.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace cg = cooperative_groups;
|
||||
@@ -67,6 +68,25 @@ struct SharedMemory<double> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
__device__ __forceinline__ T warpReduceSum(unsigned int mask, T mySum) {
|
||||
for (int offset = warpSize / 2; offset > 0; offset /= 2) {
|
||||
mySum += __shfl_down_sync(mask, mySum, offset);
|
||||
}
|
||||
return mySum;
|
||||
}
|
||||
|
||||
#if __CUDA_ARCH__ >= 800
|
||||
// Specialize warpReduceFunc for int inputs to use __reduce_add_sync intrinsic
|
||||
// when on SM 8.0 or higher
|
||||
template <>
|
||||
__device__ __forceinline__ int warpReduceSum<int>(unsigned int mask,
|
||||
int mySum) {
|
||||
mySum = __reduce_add_sync(mask, mySum);
|
||||
return mySum;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Parallel sum reduction using shared memory
|
||||
- takes log(n) steps for n input elements
|
||||
@@ -341,22 +361,32 @@ __global__ void reduce6(T *g_idata, T *g_odata, unsigned int n) {
|
||||
// perform first level of reduction,
|
||||
// reading from global memory, writing to shared memory
|
||||
unsigned int tid = threadIdx.x;
|
||||
unsigned int i = blockIdx.x * blockSize * 2 + threadIdx.x;
|
||||
unsigned int gridSize = blockSize * 2 * gridDim.x;
|
||||
unsigned int gridSize = blockSize * gridDim.x;
|
||||
|
||||
T mySum = 0;
|
||||
|
||||
// we reduce multiple elements per thread. The number is determined by the
|
||||
// number of active thread blocks (via gridDim). More blocks will result
|
||||
// in a larger gridSize and therefore fewer elements per thread
|
||||
while (i < n) {
|
||||
mySum += g_idata[i];
|
||||
if (nIsPow2) {
|
||||
unsigned int i = blockIdx.x * blockSize * 2 + threadIdx.x;
|
||||
gridSize = gridSize << 1;
|
||||
|
||||
// ensure we don't read out of bounds -- this is optimized away for powerOf2
|
||||
// sized arrays
|
||||
if (nIsPow2 || i + blockSize < n) mySum += g_idata[i + blockSize];
|
||||
|
||||
i += gridSize;
|
||||
while (i < n) {
|
||||
mySum += g_idata[i];
|
||||
// ensure we don't read out of bounds -- this is optimized away for
|
||||
// powerOf2 sized arrays
|
||||
if ((i + blockSize) < n) {
|
||||
mySum += g_idata[i + blockSize];
|
||||
}
|
||||
i += gridSize;
|
||||
}
|
||||
} else {
|
||||
unsigned int i = blockIdx.x * blockSize + threadIdx.x;
|
||||
while (i < n) {
|
||||
mySum += g_idata[i];
|
||||
i += gridSize;
|
||||
}
|
||||
}
|
||||
|
||||
// each thread puts its local sum into shared memory
|
||||
@@ -397,6 +427,129 @@ __global__ void reduce6(T *g_idata, T *g_odata, unsigned int n) {
|
||||
if (cta.thread_rank() == 0) g_odata[blockIdx.x] = mySum;
|
||||
}
|
||||
|
||||
template <typename T, unsigned int blockSize, bool nIsPow2>
|
||||
__global__ void reduce7(const T *__restrict__ g_idata, T *__restrict__ g_odata,
|
||||
unsigned int n) {
|
||||
T *sdata = SharedMemory<T>();
|
||||
|
||||
// perform first level of reduction,
|
||||
// reading from global memory, writing to shared memory
|
||||
unsigned int tid = threadIdx.x;
|
||||
unsigned int gridSize = blockSize * gridDim.x;
|
||||
unsigned int maskLength = (blockSize & 31); // 31 = warpSize-1
|
||||
maskLength = (maskLength > 0) ? (32 - maskLength) : maskLength;
|
||||
const unsigned int mask = (0xffffffff) >> maskLength;
|
||||
|
||||
T mySum = 0;
|
||||
|
||||
// we reduce multiple elements per thread. The number is determined by the
|
||||
// number of active thread blocks (via gridDim). More blocks will result
|
||||
// in a larger gridSize and therefore fewer elements per thread
|
||||
if (nIsPow2) {
|
||||
unsigned int i = blockIdx.x * blockSize * 2 + threadIdx.x;
|
||||
gridSize = gridSize << 1;
|
||||
|
||||
while (i < n) {
|
||||
mySum += g_idata[i];
|
||||
// ensure we don't read out of bounds -- this is optimized away for
|
||||
// powerOf2 sized arrays
|
||||
if ((i + blockSize) < n) {
|
||||
mySum += g_idata[i + blockSize];
|
||||
}
|
||||
i += gridSize;
|
||||
}
|
||||
} else {
|
||||
unsigned int i = blockIdx.x * blockSize + threadIdx.x;
|
||||
while (i < n) {
|
||||
mySum += g_idata[i];
|
||||
i += gridSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce within warp using shuffle or reduce_add if T==int & CUDA_ARCH ==
|
||||
// SM 8.0
|
||||
mySum = warpReduceSum<T>(mask, mySum);
|
||||
|
||||
// each thread puts its local sum into shared memory
|
||||
if ((tid % warpSize) == 0) {
|
||||
sdata[tid / warpSize] = mySum;
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
const unsigned int shmem_extent =
|
||||
(blockSize / warpSize) > 0 ? (blockSize / warpSize) : 1;
|
||||
const unsigned int ballot_result = __ballot_sync(mask, tid < shmem_extent);
|
||||
if (tid < shmem_extent) {
|
||||
mySum = sdata[tid];
|
||||
// Reduce final warp using shuffle or reduce_add if T==int & CUDA_ARCH ==
|
||||
// SM 8.0
|
||||
mySum = warpReduceSum<T>(ballot_result, mySum);
|
||||
}
|
||||
|
||||
// write result for this block to global mem
|
||||
if (tid == 0) {
|
||||
g_odata[blockIdx.x] = mySum;
|
||||
}
|
||||
}
|
||||
|
||||
// Performs a reduction step and updates numTotal with how many are remaining
|
||||
template <typename T, typename Group>
|
||||
__device__ T cg_reduce_n(T in, Group &threads) {
|
||||
return cg::reduce(threads, in, cg::plus<T>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void cg_reduce(T *g_idata, T *g_odata, unsigned int n) {
|
||||
// Shared memory for intermediate steps
|
||||
T *sdata = SharedMemory<T>();
|
||||
// Handle to thread block group
|
||||
cg::thread_block cta = cg::this_thread_block();
|
||||
// Handle to tile in thread block
|
||||
cg::thread_block_tile<32> tile = cg::tiled_partition<32>(cta);
|
||||
|
||||
unsigned int ctaSize = cta.size();
|
||||
unsigned int numCtas = gridDim.x;
|
||||
unsigned int threadRank = cta.thread_rank();
|
||||
unsigned int threadIndex = (blockIdx.x * ctaSize) + threadRank;
|
||||
|
||||
T threadVal = 0;
|
||||
{
|
||||
unsigned int i = threadIndex;
|
||||
unsigned int indexStride = (numCtas * ctaSize);
|
||||
while (i < n) {
|
||||
threadVal += g_idata[i];
|
||||
i += indexStride;
|
||||
}
|
||||
sdata[threadRank] = threadVal;
|
||||
}
|
||||
|
||||
// Wait for all tiles to finish and reduce within CTA
|
||||
{
|
||||
unsigned int ctaSteps = tile.meta_group_size();
|
||||
unsigned int ctaIndex = ctaSize >> 1;
|
||||
while (ctaIndex >= 32) {
|
||||
cta.sync();
|
||||
if (threadRank < ctaIndex) {
|
||||
threadVal += sdata[threadRank + ctaIndex];
|
||||
sdata[threadRank] = threadVal;
|
||||
}
|
||||
ctaSteps >>= 1;
|
||||
ctaIndex >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Shuffle redux instead of smem redux
|
||||
{
|
||||
cta.sync();
|
||||
if (tile.meta_group_rank() == 0) {
|
||||
threadVal = cg_reduce_n(threadVal, tile);
|
||||
}
|
||||
}
|
||||
|
||||
if (threadRank == 0) g_odata[blockIdx.x] = threadVal;
|
||||
}
|
||||
|
||||
extern "C" bool isPow2(unsigned int x);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -542,7 +695,6 @@ void reduce(int size, int threads, int blocks, int whichKernel, T *d_idata,
|
||||
break;
|
||||
|
||||
case 6:
|
||||
default:
|
||||
if (isPow2(size)) {
|
||||
switch (threads) {
|
||||
case 512:
|
||||
@@ -650,6 +802,122 @@ void reduce(int size, int threads, int blocks, int whichKernel, T *d_idata,
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
// For reduce7 kernel we require only blockSize/warpSize
|
||||
// number of elements in shared memory
|
||||
smemSize = ((threads / 32) + 1) * sizeof(T);
|
||||
if (isPow2(size)) {
|
||||
switch (threads) {
|
||||
case 512:
|
||||
reduce7<T, 512, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 256:
|
||||
reduce7<T, 256, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 128:
|
||||
reduce7<T, 128, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
reduce7<T, 64, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
reduce7<T, 32, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
reduce7<T, 16, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
reduce7<T, 8, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
reduce7<T, 4, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
reduce7<T, 2, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
reduce7<T, 1, true>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (threads) {
|
||||
case 512:
|
||||
reduce7<T, 512, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 256:
|
||||
reduce7<T, 256, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 128:
|
||||
reduce7<T, 128, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
reduce7<T, 64, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
reduce7<T, 32, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
reduce7<T, 16, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
reduce7<T, 8, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
reduce7<T, 4, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
reduce7<T, 2, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
reduce7<T, 1, false>
|
||||
<<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
cg_reduce<T><<<dimGrid, dimBlock, smemSize>>>(d_idata, d_odata, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<OutputFile>$(OutDir)/reduction.exe</OutputFile>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<CodeGeneration>compute_30,sm_30;compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;</CodeGeneration>
|
||||
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;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>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<OutputFile>$(OutDir)/reduction.exe</OutputFile>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<CodeGeneration>compute_30,sm_30;compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;</CodeGeneration>
|
||||
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;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>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<OutputFile>$(OutDir)/reduction.exe</OutputFile>
|
||||
</Link>
|
||||
<CudaCompile>
|
||||
<CodeGeneration>compute_30,sm_30;compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;</CodeGeneration>
|
||||
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;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>
|
||||
|
||||
Reference in New Issue
Block a user