From 53b6d3aae9221f170aa3f06eb607190f06d66f9c Mon Sep 17 00:00:00 2001 From: Ryan Tong Date: Sun, 18 Sep 2022 12:27:51 -0400 Subject: [PATCH 1/5] finished non-extra credit parts --- src/main.cpp | 2 +- stream_compaction/common.cu | 14 +++- stream_compaction/common.h | 3 + stream_compaction/cpu.cu | 42 +++++++++-- stream_compaction/efficient.cu | 132 ++++++++++++++++++++++++++++++++- stream_compaction/naive.cu | 63 +++++++++++++++- stream_compaction/thrust.cu | 10 +++ 7 files changed, 251 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 896ac2b..74bef51 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 8; // feel free to change the size of array +const int SIZE = 1 << 19; // feel free to change the size of array const int NPOT = SIZE - 3; // Non-Power-Of-Two int *a = new int[SIZE]; int *b = new int[SIZE]; diff --git a/stream_compaction/common.cu b/stream_compaction/common.cu index 2ed6d63..ea8a869 100644 --- a/stream_compaction/common.cu +++ b/stream_compaction/common.cu @@ -23,7 +23,12 @@ namespace StreamCompaction { * which map to 0 will be removed, and elements which map to 1 will be kept. */ __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { - // TODO + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + + bools[index] = idata[index] == 0 ? 0 : 1; } /** @@ -32,7 +37,12 @@ namespace StreamCompaction { */ __global__ void kernScatter(int n, int *odata, const int *idata, const int *bools, const int *indices) { - // TODO + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n || bools[index] == 0) { + return; + } + + odata[indices[index]] = idata[index]; } } diff --git a/stream_compaction/common.h b/stream_compaction/common.h index d2c1fed..fd3f159 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -9,6 +9,9 @@ #include #include #include +#include "device_launch_parameters.h" + +#define blockSize 256 #define FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #define checkCUDAError(msg) checkCUDAErrorFn(msg, FILENAME, __LINE__) diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 719fa11..37aa00c 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -19,7 +19,11 @@ namespace StreamCompaction { */ void scan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + int prev = 0; + for (int i = 0; i < n; ++i) { + odata[i] = prev; + prev += idata[i]; + } timer().endCpuTimer(); } @@ -30,9 +34,15 @@ namespace StreamCompaction { */ int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + int out_ptr = 0; + for (int i = 0; i < n; ++i) { + if (idata[i] != 0) { + odata[out_ptr] = idata[i]; + ++out_ptr; + } + } timer().endCpuTimer(); - return -1; + return out_ptr; } /** @@ -42,9 +52,31 @@ namespace StreamCompaction { */ int compactWithScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + int* binary = new int[n]; + int* scanOut = new int[n]; + for (int i = 0; i < n; ++i) { + if (idata[i] != 0) { + binary[i] = 1; + } + else { + binary[i] = 0; + } + } + //Scan code copied + int prev = 0; + for (int i = 0; i < n; ++i) { + scanOut[i] = prev; + prev += binary[i]; + } + int count = 0; + for (int i = 0; i < n; ++i) { + if (idata[i] != 0) { + odata[scanOut[i]] = idata[i]; + ++count; + } + } timer().endCpuTimer(); - return -1; + return count; } } } diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 2db346e..9706965 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -11,16 +11,75 @@ namespace StreamCompaction { static PerformanceTimer timer; return timer; } + __global__ void kernUpSweep(int n, int d, int* idata) { + // Parallel Reduction + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + + int k = index * (1 << (d + 1)); + idata[k + (1 << (d + 1)) - 1] += idata[k + (1 << d) - 1]; + } + + __global__ void kernDownSweep(int n, int d, int* idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + + int k = index * (1 << (d + 1)); + int t = idata[k + (1 << d) - 1]; + idata[k + (1 << d) - 1] = idata[k + (1 << (d + 1)) - 1]; + idata[k + (1 << (d + 1)) - 1] += t; + } + + __global__ void kernZeroRoot(int n, int* idata) { + // Root is last element + idata[n - 1] = 0; + } /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + // Account for non-powers of 2 by padding by 0 + int paddedN = (1 << ilog2ceil(n)); + int* dev_idata; + cudaMalloc((void**)&dev_idata, paddedN * sizeof(int)); + checkCUDAError("cudaMalloc dev_idata failed!"); + cudaMemcpy(dev_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + cudaMemset(dev_idata + n, 0, (paddedN - n) * sizeof(int)); + cudaDeviceSynchronize(); + timer().startGpuTimer(); - // TODO + // Upsweep + for (int i = 0; i < ilog2ceil(n); ++i) { + int numThreads = paddedN / (1 << (i + 1)); + dim3 upSweepGridSize((numThreads + blockSize - 1) / blockSize); + kernUpSweep << > > + (numThreads, i, dev_idata); + checkCUDAError("kernUpSweep failed!"); + cudaDeviceSynchronize(); + } + + // Downsweep + kernZeroRoot << <1, 1 >> > (paddedN, dev_idata); + for (int i = ilog2ceil(n) - 1; i >= 0; --i) { + int numThreads = paddedN / (1 << (i + 1)); + dim3 downSweepGridSize((numThreads + blockSize - 1) / blockSize); + kernDownSweep << > > + (numThreads, i, dev_idata); + checkCUDAError("kernDownSweep failed!"); + cudaDeviceSynchronize(); + } timer().endGpuTimer(); + cudaMemcpy(odata, dev_idata, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaFree(dev_idata); } + + /** * Performs stream compaction on idata, storing the result into odata. * All zeroes are discarded. @@ -31,10 +90,77 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { + // Account for non-powers of 2 by padding by 0 + int paddedN = (1 << ilog2ceil(n)); + int* dev_idata; + int* dev_odata; + int* dev_bool; + int* dev_indices; + + cudaMalloc((void**)&dev_idata, n * sizeof(int)); + checkCUDAError("cudaMalloc dev_idata failed!"); + cudaMemcpy(dev_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + + // Pad bool array instead of idata to save operations in kernMapToBoolean + cudaMalloc((void**)&dev_bool, paddedN * sizeof(int)); + checkCUDAError("cudaMalloc dev_bool failed!"); + cudaMemset(dev_bool + n, 0, (paddedN - n) * sizeof(int)); + + cudaMalloc((void**)&dev_indices, paddedN * sizeof(int)); + checkCUDAError("cudaMalloc dev_indices failed!"); + cudaMalloc((void**)&dev_odata, n * sizeof(int)); + checkCUDAError("cudaMalloc dev_indices failed!"); + cudaDeviceSynchronize(); + timer().startGpuTimer(); - // TODO + // Binarize + dim3 nGridSize((n + blockSize - 1) / blockSize); + StreamCompaction::Common::kernMapToBoolean << < nGridSize, blockSize >> > + (n, dev_bool, dev_idata); + checkCUDAError("kernMapToBoolean failed!"); + cudaDeviceSynchronize(); + // We need bool array for scatter so copy bool result to indices to be modified in place + cudaMemcpy(dev_indices, dev_bool, paddedN * sizeof(int), cudaMemcpyDeviceToDevice); + checkCUDAError("cudaMemcpy failed!"); + cudaDeviceSynchronize(); + + // Copied Scan code from above + // Upsweep + for (int i = 0; i < ilog2ceil(n); ++i) { + int numThreads = paddedN / (1 << (i + 1)); + dim3 upSweepGridSize((numThreads + blockSize - 1) / blockSize); + kernUpSweep << > > + (numThreads, i, dev_indices); + checkCUDAError("kernUpSweep failed!"); + cudaDeviceSynchronize(); + } + + // Downsweep + kernZeroRoot << <1, 1 >> > (paddedN, dev_indices); + for (int i = ilog2ceil(n) - 1; i >= 0; --i) { + int numThreads = paddedN / (1 << (i + 1)); + dim3 downSweepGridSize((numThreads + blockSize - 1) / blockSize); + kernDownSweep << > > + (numThreads, i, dev_indices); + checkCUDAError("kernDownSweep failed!"); + cudaDeviceSynchronize(); + } + + // Scatter + StreamCompaction::Common::kernScatter << > > + (n, dev_odata, dev_idata, dev_bool, dev_indices); + checkCUDAError("kernScatter failed!"); + cudaDeviceSynchronize(); timer().endGpuTimer(); - return -1; + + cudaMemcpy(odata, dev_indices, paddedN * sizeof(int), cudaMemcpyDeviceToHost); + int finalNum = odata[paddedN - 1]; + cudaMemcpy(odata, dev_odata, finalNum * sizeof(int), cudaMemcpyDeviceToHost); + cudaFree(dev_idata); + cudaFree(dev_bool); + cudaFree(dev_indices); + cudaFree(dev_odata); + return finalNum; } } } diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 4308876..e49a86a 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -12,14 +12,69 @@ namespace StreamCompaction { return timer; } // TODO: __global__ + __global__ void kernScan(int n, int d, int* odata, const int* idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + if (index >= (1 << (d - 1))) { + odata[index] = idata[index - (1 << (d - 1))] + idata[index]; + } + else { + odata[index] = idata[index]; + } + } + + __global__ void kernInclusiveToExclusive(int n, int* odata, const int* idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + + if (index == 0) { + odata[index] = 0; + return; + } + odata[index] = idata[index - 1]; + } - /** - * Performs prefix-sum (aka scan) on idata, storing the result into odata. - */ + + ///** + // * Performs prefix-sum (aka scan) on idata, storing the result into odata. + // */ void scan(int n, int *odata, const int *idata) { + dim3 fullBlocksPerGrid((n + blockSize - 1) / blockSize); + + // Put host arrays onto device + int* dev_odata; + int* dev_idata; + cudaMalloc((void**)&dev_odata, n * sizeof(int)); + checkCUDAError("cudaMalloc dev_odata failed!"); + cudaMalloc((void**)&dev_idata, n * sizeof(int)); + checkCUDAError("cudaMalloc dev_idata failed!"); + cudaMemcpy(dev_odata, odata, n * sizeof(int), cudaMemcpyHostToDevice); + cudaMemcpy(dev_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + cudaDeviceSynchronize(); + timer().startGpuTimer(); - // TODO + for (int i = 1; i <= ilog2ceil(n); ++i) { + kernScan << > > + (n, i, dev_odata, dev_idata); + checkCUDAError("kernScan failed!"); + cudaDeviceSynchronize(); + int* temp = dev_idata; + dev_idata = dev_odata; + dev_odata = temp; + } + cudaMemcpy(odata, dev_odata, n * sizeof(int), cudaMemcpyDeviceToHost); + kernInclusiveToExclusive << > > (n, dev_odata, dev_idata); + checkCUDAError("kernInclusiveToExclusive failed!"); + cudaDeviceSynchronize(); timer().endGpuTimer(); + + cudaMemcpy(odata, dev_odata, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaFree(dev_odata); + cudaFree(dev_idata); } } } diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index 1def45e..a4f3c39 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -18,11 +18,21 @@ namespace StreamCompaction { * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + + thrust::host_vector thrust_idata(idata, idata + n); + thrust::host_vector thrust_odata(odata, odata + n); + + thrust::device_vector dev_thrust_idata = thrust_idata; + thrust::device_vector dev_thrust_odata = thrust_odata; + cudaDeviceSynchronize(); timer().startGpuTimer(); // TODO use `thrust::exclusive_scan` // example: for device_vectors dv_in and dv_out: // thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); + thrust::exclusive_scan(dev_thrust_idata.begin(), dev_thrust_idata.end(), dev_thrust_odata.begin()); timer().endGpuTimer(); + + thrust::copy(dev_thrust_odata.begin(), dev_thrust_odata.end(), odata); } } } From 3e08669c1953cc6327465a22249eafb978c429c7 Mon Sep 17 00:00:00 2001 From: Ryan Tong Date: Sun, 18 Sep 2022 13:32:00 -0400 Subject: [PATCH 2/5] Images --- img/compaction.png | Bin 0 -> 25386 bytes img/compaction_small.png | Bin 0 -> 25098 bytes img/scan.png | Bin 0 -> 25938 bytes img/scan_small.png | Bin 0 -> 23526 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/compaction.png create mode 100644 img/compaction_small.png create mode 100644 img/scan.png create mode 100644 img/scan_small.png diff --git a/img/compaction.png b/img/compaction.png new file mode 100644 index 0000000000000000000000000000000000000000..248b0955ffdc3c6e565d951b069b1cb648ebcb0b GIT binary patch literal 25386 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%0Di_{efB)2M<3 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 F=RZaLQ@Q{E literal 0 HcmV?d00001 diff --git a/img/scan.png b/img/scan.png new file mode 100644 index 0000000000000000000000000000000000000000..cafbad8513263c8f577402cb398793dc0f95061f GIT binary patch literal 25938 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 literal 0 HcmV?d00001 diff --git a/img/scan_small.png b/img/scan_small.png new file mode 100644 index 0000000000000000000000000000000000000000..a83aea86676f4f8e9e0dc9262e4e99acfcc0ad82 GIT binary patch literal 23526 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 JsfI)Ne*iWN>pK7d literal 0 HcmV?d00001 From 4dc2e812bbed765ed001eef4cddb7ba27398fffa Mon Sep 17 00:00:00 2001 From: ryanryantong <71223488+ryanryantong@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:57:51 -0400 Subject: [PATCH 3/5] Update README.md --- README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0e38ddb..e759399 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,84 @@ CUDA Stream Compaction **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** -* (TODO) YOUR NAME HERE - * (TODO) [LinkedIn](), [personal website](), [twitter](), etc. -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) - -### (TODO: Your README) +* Ryan Tong + * [LinkedIn](https://www.linkedin.com/in/ryanctong/), [personal website](), [twitter](), etc. +* Tested on: Windows 10, i7-8750H @ 2.20GHz 16GB, GeForce GTX 1060 6144MB (Personal Laptop) Include analysis, etc. (Remember, this is public, so don't put anything here that you don't want to share with the world.) +### Features +This project implements the required features of CPU based scan and stream compaction; GPU based naive scan, work-efficient scan, stream compaction (using work-efficient scan); and Thrust based scan. I roughly optimized the block size to be 256 after doing some testing and reading this article: https://oneflow2020.medium.com/how-to-choose-the-grid-size-and-block-size-for-a-cuda-kernel-d1ff1f0a7f92. + +### Performance Analysis +Here are the graphs comapring the runtimes of scan implemented on the CPU, GPU, and with Thrust. Note that Thrust is removed and the range of array sizes is shrunk for the second graph for visualization purposes. + +![Scan](images/scan.png) +![Scan (Better Visualization)](images/scan_small.png) + +From the graphs, we can see that CPU is faster than the work-efficent GPU implementation until the array size reaches about ~1,000,000 elements. This is suprising because the theortical complexities of these algorithms are O(n), O(nlogn), O(n) for CPU, naive, and work efficent respectively. Since the GPU implementations are paralleized we would expect that they are faster than the CPU implementation. The cause of this is likely the lack of optimizations in my GPU code and frequent reads and writes to global memory which is slow. An implementation using shared memory would improve the memory access speeds. Further more, the indexing of scan is inefficent since there are many inactive threads that could be retired in a warp if they were consecutive. + +The Thrust implementations are significantly slower than both GPU and CPU implementation which is likely due to some implementation error that I was unable to solve. + +We can see these inefficenies reflected again in the stream compaction run times: + +![Stream Compaction](images/scan.png) +![Stream Compaction (Better Visualization)](images/scan_small.png) + +### Program Output +``` + +**************** +** SCAN TESTS ** +**************** + [ 29 48 7 23 28 16 45 34 2 47 35 3 16 ... 48 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 2.702ms (std::chrono Measured) + [ 0 29 77 84 107 135 151 196 230 232 279 314 317 ... 12845931 12845979 ] +==== cpu scan, non-power-of-two ==== + elapsed time: 2.7096ms (std::chrono Measured) + [ 0 29 77 84 107 135 151 196 230 232 279 314 317 ... 12845838 12845880 ] + passed +==== naive scan, power-of-two ==== + elapsed time: 4.85891ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 4.5247ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 2.23603ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 2.10493ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 35.5277ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 27.5845ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 3 2 3 1 2 0 3 0 2 3 1 3 2 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 6.4836ms (std::chrono Measured) + [ 3 2 3 1 2 3 2 3 1 3 2 3 1 ... 1 2 ] + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 5.3097ms (std::chrono Measured) + [ 3 2 3 1 2 3 2 3 1 3 2 3 1 ... 2 1 ] + passed +==== cpu compact with scan ==== + elapsed time: 14.7061ms (std::chrono Measured) + [ 3 2 3 1 2 3 2 3 1 3 2 3 1 ... 1 2 ] + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 2.84058ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 2.50528ms (CUDA Measured) + passed +``` From 885499e5d5f06357e0316e0f0b77e2be07b2b523 Mon Sep 17 00:00:00 2001 From: ryanryantong <71223488+ryanryantong@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:59:05 -0400 Subject: [PATCH 4/5] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e759399..b26ef7c 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ This project implements the required features of CPU based scan and stream compa ### Performance Analysis Here are the graphs comapring the runtimes of scan implemented on the CPU, GPU, and with Thrust. Note that Thrust is removed and the range of array sizes is shrunk for the second graph for visualization purposes. -![Scan](images/scan.png) -![Scan (Better Visualization)](images/scan_small.png) +![Scan](img/scan.png) +![Scan (Better Visualization)](img/scan_small.png) From the graphs, we can see that CPU is faster than the work-efficent GPU implementation until the array size reaches about ~1,000,000 elements. This is suprising because the theortical complexities of these algorithms are O(n), O(nlogn), O(n) for CPU, naive, and work efficent respectively. Since the GPU implementations are paralleized we would expect that they are faster than the CPU implementation. The cause of this is likely the lack of optimizations in my GPU code and frequent reads and writes to global memory which is slow. An implementation using shared memory would improve the memory access speeds. Further more, the indexing of scan is inefficent since there are many inactive threads that could be retired in a warp if they were consecutive. @@ -25,8 +25,8 @@ The Thrust implementations are significantly slower than both GPU and CPU implem We can see these inefficenies reflected again in the stream compaction run times: -![Stream Compaction](images/scan.png) -![Stream Compaction (Better Visualization)](images/scan_small.png) +![Stream Compaction](img/compaction.png) +![Stream Compaction (Better Visualization)](img/compaction_small.png) ### Program Output ``` From 8f1982bf396ee24cf1d9f6fb6b592a0d9528f877 Mon Sep 17 00:00:00 2001 From: Ryan Tong Date: Sat, 8 Oct 2022 00:10:38 -0400 Subject: [PATCH 5/5] Added shared mem --- src/main.cpp | 2 +- stream_compaction/CMakeLists.txt | 1 + stream_compaction/common.h | 2 +- stream_compaction/efficient.cu | 190 +++++++++++++++++++++++++++---- 4 files changed, 170 insertions(+), 25 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 74bef51..ac0ccc8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 19; // feel free to change the size of array +const int SIZE = 1 << 5; // feel free to change the size of array const int NPOT = SIZE - 3; // Non-Power-Of-Two int *a = new int[SIZE]; int *b = new int[SIZE]; diff --git a/stream_compaction/CMakeLists.txt b/stream_compaction/CMakeLists.txt index 567795b..18cc27e 100644 --- a/stream_compaction/CMakeLists.txt +++ b/stream_compaction/CMakeLists.txt @@ -1,3 +1,4 @@ +cmake_minimum_required(VERSION 3.1) set(headers "common.h" "cpu.h" diff --git a/stream_compaction/common.h b/stream_compaction/common.h index fd3f159..5f88cfd 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -11,7 +11,7 @@ #include #include "device_launch_parameters.h" -#define blockSize 256 +#define blockSize 4 #define FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #define checkCUDAError(msg) checkCUDAErrorFn(msg, FILENAME, __LINE__) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 9706965..36b47dc 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -33,6 +33,125 @@ namespace StreamCompaction { idata[k + (1 << d) - 1] = idata[k + (1 << (d + 1)) - 1]; idata[k + (1 << (d + 1)) - 1] += t; } + + __host__ __device__ int copyIlog2(int x) { //copied the given functions bc i am lazy + int lg = 0; + while (x >>= 1) { + ++lg; + } + return lg; + } + + __host__ __device__ int copyIlog2ceil(int x) { + return x == 1 ? 0 : copyIlog2(x - 1) + 1; + } + + + // Steps for shared scan + // 1. Launch kernel with N / (blockSize * 2) blocks, blockSize threads per blockSize + // 2. For each block generate a shared mem size 2 * blockSize + // 3. Load values from input array in pairs to shared mem + // 4. Do same indexing upsweep scheme as before on individual blocks + // 5. Get INCLUSIVE element for each block endand add to temp array + // 6. Zero out last element of each block, like with root zeroing + // 7. Down sweep on individual blocks + // OR DO REST ON CPU :) + // 8. Pass the temp array as the new input array and recurse steps 1 - 7 + // 9. Recursively add the output of the temp array as an offset to each block + __global__ void kernSharedScan(int n, int* idata, int* temp) { + // Parallel Reduction w/ shared memory + // Shared memory should be 2 * blockSize + __shared__ int partialSum[2 * blockSize]; + // Load input memory into shared memory in pairs + int index = threadIdx.x + (blockIdx.x * blockDim.x); //index of all launched threads (N / 2) + int sharedIdx = threadIdx.x; // per block index + partialSum[sharedIdx * 2] = idata[index * 2]; + partialSum[sharedIdx * 2 + 1] = idata[index * 2 + 1]; + // Per block upsweep + int logBlock = copyIlog2ceil(blockDim.x * 2); //blockSize * 2 since we are doing blockSize*2 elements per block + for (int d = 0; d < logBlock; ++d) { // Runs log2(blockSize) times + __syncthreads(); + if (sharedIdx < (blockDim.x / (1 << d))) { + int k = sharedIdx * (1 << (d + 1)); + partialSum[k + (1 << (d + 1)) - 1] += partialSum[k + (1 << d) - 1]; + } + } + __syncthreads(); + // Save last INCLUSIVE VALUE of block (for recursion and offset) + // Zero out root + if (sharedIdx == blockDim.x - 1) { // Last thread in block + temp[blockIdx.x] = partialSum[2 * blockDim.x - 1]; //+ idata[(2 * blockDim.x - 1) + blockIdx.x * blockDim.x * 2]; // Last element in shared mem + last element of block in idata (last inclusive element) + partialSum[2 * blockDim.x - 1] = 0; + } + __syncthreads(); + // Per block downsweep + for (int d = logBlock - 1; d >= 0; --d) { + if (sharedIdx < (blockDim.x / (1 << d))) { + int k = sharedIdx * (1 << (d + 1)); + int t = partialSum[k + (1 << d) - 1]; + partialSum[k + (1 << d) - 1] = partialSum[k + (1 << (d + 1)) - 1]; + partialSum[k + (1 << (d + 1)) - 1] += t; + } + } + __syncthreads(); + //Write to input array in place + idata[index * 2] = partialSum[sharedIdx * 2]; + idata[index * 2 + 1] = partialSum[sharedIdx * 2 + 1]; + } + + // Function to add offset buffer to each block + // ex. offset = [10, 20, 30], add 10 to block 0, add 20 to block 1, add 30 to block 2 + __global__ void addOffsets(int n, int* idata, int* offsets) { + // n is num elements in idata + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index > n) { + return; + } + idata[index] += offsets[(int)index / (blockDim.x * 2)]; + } + + void scan(int n, int* odata, const int* idata) { + int paddedN = (1 << ilog2ceil(n)); + int* dev_idata; + cudaMalloc((void**)&dev_idata, paddedN * sizeof(int)); + checkCUDAError("cudaMalloc dev_idata failed!"); + cudaMemcpy(dev_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + cudaMemset(dev_idata + n, 0, (paddedN - n) * sizeof(int)); + cudaDeviceSynchronize(); + + timer().startGpuTimer(); + //Determine size of temp array after 1 pass + int tempSize = paddedN / (blockSize * 2); + dim3 gridSize(tempSize); + int* dev_temp; + int* temp = (int*) malloc(tempSize * sizeof(int)); + cudaMalloc((void**)& dev_temp, tempSize * sizeof(int)); + cudaDeviceSynchronize(); + kernSharedScan << > > (paddedN, dev_idata, dev_temp); + checkCUDAError("kernSharedScan failed!"); + cudaDeviceSynchronize(); + cudaMemcpy(temp, dev_temp, tempSize * sizeof(int), cudaMemcpyDeviceToHost); + cudaDeviceSynchronize(); + int prev = 0; + for (int i = 0; i < tempSize; ++i) { // In-place CPU exclusive scan + int tempVal = temp[i]; + temp[i] = prev; + prev += tempVal; + } + + cudaMemcpy(dev_temp, temp, tempSize * sizeof(int), cudaMemcpyHostToDevice); + cudaDeviceSynchronize(); + dim3 offsetGridSize(paddedN / blockSize); + addOffsets << > > (paddedN, dev_idata, dev_temp); + checkCUDAError("addOffsets failed!"); + cudaDeviceSynchronize(); + timer().endGpuTimer(); + + cudaMemcpy(odata, dev_idata, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaFree(dev_idata); + cudaFree(dev_temp); + free(temp); + } __global__ void kernZeroRoot(int n, int* idata) { // Root is last element @@ -42,7 +161,7 @@ namespace StreamCompaction { /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ - void scan(int n, int *odata, const int *idata) { + void oldScan(int n, int *odata, const int *idata) { // Account for non-powers of 2 by padding by 0 int paddedN = (1 << ilog2ceil(n)); int* dev_idata; @@ -78,8 +197,6 @@ namespace StreamCompaction { cudaFree(dev_idata); } - - /** * Performs stream compaction on idata, storing the result into odata. * All zeroes are discarded. @@ -112,6 +229,15 @@ namespace StreamCompaction { checkCUDAError("cudaMalloc dev_indices failed!"); cudaDeviceSynchronize(); + + //Determine size of temp array after 1 pass + int tempSize = paddedN / (blockSize * 2); + dim3 gridSize(tempSize); + int* dev_temp; + int* temp = (int*)malloc(tempSize * sizeof(int)); + cudaMalloc((void**)&dev_temp, tempSize * sizeof(int)); + checkCUDAError("cudaMalloc dev_temp failed!"); + timer().startGpuTimer(); // Binarize dim3 nGridSize((n + blockSize - 1) / blockSize); @@ -123,28 +249,46 @@ namespace StreamCompaction { cudaMemcpy(dev_indices, dev_bool, paddedN * sizeof(int), cudaMemcpyDeviceToDevice); checkCUDAError("cudaMemcpy failed!"); cudaDeviceSynchronize(); - - // Copied Scan code from above - // Upsweep - for (int i = 0; i < ilog2ceil(n); ++i) { - int numThreads = paddedN / (1 << (i + 1)); - dim3 upSweepGridSize((numThreads + blockSize - 1) / blockSize); - kernUpSweep << > > - (numThreads, i, dev_indices); - checkCUDAError("kernUpSweep failed!"); - cudaDeviceSynchronize(); + + // Shared scan copied from above + kernSharedScan << > > (paddedN, dev_indices, dev_temp); + checkCUDAError("kernSharedScan failed!"); + cudaDeviceSynchronize(); + cudaMemcpy(temp, dev_temp, tempSize * sizeof(int), cudaMemcpyDeviceToHost); + cudaDeviceSynchronize(); + int prev = 0; + for (int i = 0; i < tempSize; ++i) { // In-place CPU exclusive scan + int tempVal = temp[i]; + temp[i] = prev; + prev += tempVal; } + cudaMemcpy(dev_temp, temp, tempSize * sizeof(int), cudaMemcpyHostToDevice); + cudaDeviceSynchronize(); + dim3 offsetGridSize(paddedN / blockSize); + addOffsets << > > (paddedN, dev_indices, dev_temp); + checkCUDAError("addOffsets failed!"); + cudaDeviceSynchronize(); + //// Copied Scan code from above + //// Upsweep + //for (int i = 0; i < ilog2ceil(n); ++i) { + // int numThreads = paddedN / (1 << (i + 1)); + // dim3 upSweepGridSize((numThreads + blockSize - 1) / blockSize); + // kernUpSweep << > > + // (numThreads, i, dev_indices); + // checkCUDAError("kernUpSweep failed!"); + // cudaDeviceSynchronize(); + //} - // Downsweep - kernZeroRoot << <1, 1 >> > (paddedN, dev_indices); - for (int i = ilog2ceil(n) - 1; i >= 0; --i) { - int numThreads = paddedN / (1 << (i + 1)); - dim3 downSweepGridSize((numThreads + blockSize - 1) / blockSize); - kernDownSweep << > > - (numThreads, i, dev_indices); - checkCUDAError("kernDownSweep failed!"); - cudaDeviceSynchronize(); - } + //// Downsweep + //kernZeroRoot << <1, 1 >> > (paddedN, dev_indices); + //for (int i = ilog2ceil(n) - 1; i >= 0; --i) { + // int numThreads = paddedN / (1 << (i + 1)); + // dim3 downSweepGridSize((numThreads + blockSize - 1) / blockSize); + // kernDownSweep << > > + // (numThreads, i, dev_indices); + // checkCUDAError("kernDownSweep failed!"); + // cudaDeviceSynchronize(); + //} // Scatter StreamCompaction::Common::kernScatter << > >