From 0656f11c9a6afc9aa2690a3e353f7fe8780a9ebe Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Wed, 12 Sep 2018 13:36:34 -0400 Subject: [PATCH 01/15] add: CPU algorithms for scan/compact/compactWithScan --- stream_compaction/CMakeLists.txt | 2 +- stream_compaction/cpu.cu | 65 ++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/stream_compaction/CMakeLists.txt b/stream_compaction/CMakeLists.txt index cdbef77..c8709e7 100644 --- a/stream_compaction/CMakeLists.txt +++ b/stream_compaction/CMakeLists.txt @@ -13,5 +13,5 @@ set(SOURCE_FILES cuda_add_library(stream_compaction ${SOURCE_FILES} - OPTIONS -arch=sm_20 + OPTIONS -arch=sm_50 ) diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 05ce667..b430dad 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -1,15 +1,16 @@ #include #include "cpu.h" -#include "common.h" +#include "common.h" +#include namespace StreamCompaction { namespace CPU { - using StreamCompaction::Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; + using StreamCompaction::Common::PerformanceTimer; + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; } /** @@ -19,7 +20,12 @@ namespace StreamCompaction { */ void scan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + odata[0] = 0; + for (int idx = 1; idx < n; ++idx) + { + odata[idx] = odata[idx - 1] + idata[idx - 1]; + } + timer().endCpuTimer(); } @@ -30,9 +36,20 @@ namespace StreamCompaction { */ int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + + int outIdx = 0; + for (int idx = 0; idx < n; ++idx) + { + const int inputData = idata[idx]; + if (inputData != 0) + { + odata[outIdx] = inputData; + ++outIdx; + } + } + timer().endCpuTimer(); - return -1; + return outIdx; } /** @@ -41,10 +58,36 @@ namespace StreamCompaction { * @returns the number of elements remaining after compaction. */ int compactWithScan(int n, int *odata, const int *idata) { + const std::unique_ptr conditionArray = std::make_unique(n); + const std::unique_ptr scanArray = std::make_unique(n); + timer().startCpuTimer(); - // TODO + + for (int idx = 0; idx < n; ++idx) + { + conditionArray[idx] = idata[idx] != 0 ? 1 : 0; + } + + scanArray[0] = 0; + for (int idx = 1; idx < n; ++idx) + { + scanArray[idx] = scanArray[idx - 1] + conditionArray[idx - 1]; + } + + int outIdx = 0; + for (int idx = 0; idx < n; ++idx) + { + const int inputData = idata[idx]; + if (conditionArray[idx] == 1) + { + outIdx = scanArray[idx]; + odata[outIdx] = inputData; + } + } + timer().endCpuTimer(); - return -1; + + return outIdx + 1; } } } From 8c35c7cba5d773b10f8344786e90e5b111417767 Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Wed, 12 Sep 2018 14:48:32 -0400 Subject: [PATCH 02/15] add: naive gpu scan --- src/main.cpp | 4 +- stream_compaction/naive.cu | 91 ++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1850161..0d88eac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,7 +51,7 @@ int main(int argc, char* argv[]) { printDesc("naive scan, power-of-two"); StreamCompaction::Naive::scan(SIZE, c, a); printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); + printArray(SIZE, c, true); printCmpResult(SIZE, b, c); /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) { printDesc("naive scan, non-power-of-two"); StreamCompaction::Naive::scan(NPOT, c, a); printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); + printArray(SIZE, c, true); printCmpResult(NPOT, b, c); zeroArray(SIZE, c); diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 9218f8e..c17a78d 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -2,24 +2,79 @@ #include #include "common.h" #include "naive.h" +#include -namespace StreamCompaction { - namespace Naive { - using StreamCompaction::Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } - // TODO: __global__ - - /** - * Performs prefix-sum (aka scan) on idata, storing the result into odata. - */ - void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - } +#define blockSize 256 + +namespace StreamCompaction +{ + namespace Naive + { + int* device_idata; + int* device_odata; + int numObjects; + + using StreamCompaction::Common::PerformanceTimer; + + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } + + __global__ void kernel_NaiveParallelScan(int N, int powD, int* odata, int* idata) + { + const int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= N) { + return; + } + + if (index < powD) + { + odata[index] = idata[index]; + return; + } + + odata[index] = idata[index - powD] + idata[index]; + } + + /** + * Performs prefix-sum (aka scan) on idata, storing the result into odata. + */ + void scan(int n, int* odata, const int* idata) + { + numObjects = n; + cudaMalloc((void**)&device_idata, numObjects * sizeof(int)); + checkCUDAError("cudaMalloc device_idata failed!"); + + cudaMalloc((void**)&device_odata, numObjects * sizeof(int)); + checkCUDAError("cudaMalloc device_odata failed!"); + + cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); + + dim3 fullBlocksPerGrid((numObjects + blockSize - 1) / blockSize); + + const int logN = ilog2ceil(numObjects); + + int* loopInputBuffer = device_idata; + int* loopOutputBuffer = device_odata; + + timer().startGpuTimer(); + for (int d = 1; d <= logN; ++d) + { + const int powD = std::pow(2, d - 1); + kernel_NaiveParallelScan<<>>(numObjects - 1, powD, loopOutputBuffer, loopInputBuffer); + + int* temp = loopInputBuffer; + loopInputBuffer = loopOutputBuffer; + loopOutputBuffer = temp; + } + timer().endGpuTimer(); + + cudaMemcpy((odata + 1), loopInputBuffer, sizeof(int) * (numObjects - 1), cudaMemcpyDeviceToHost); + + cudaFree(device_idata); + cudaFree(device_odata); } + } } From af369b11245198f5444252eb13293513cec7a4a7 Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sat, 15 Sep 2018 15:22:35 -0400 Subject: [PATCH 03/15] add: implementation details for all the remaining scans --- src/main.cpp | 17 ++-- src/testing_helpers.hpp | 3 +- stream_compaction/efficient.cu | 157 ++++++++++++++++++++++++++------- stream_compaction/thrust.cu | 55 ++++++++---- 4 files changed, 172 insertions(+), 60 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0d88eac..e66f268 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,7 @@ int main(int argc, char* argv[]) { printf("****************\n"); printf("** SCAN TESTS **\n"); printf("****************\n"); + printf("Size of Array: %d", SIZE); genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case a[SIZE - 1] = 0; @@ -38,20 +39,20 @@ int main(int argc, char* argv[]) { printDesc("cpu scan, power-of-two"); StreamCompaction::CPU::scan(SIZE, b, a); printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(SIZE, b, true); + // printArray(SIZE, b, true); zeroArray(SIZE, c); printDesc("cpu scan, non-power-of-two"); StreamCompaction::CPU::scan(NPOT, c, a); printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(NPOT, b, true); + //printArray(NPOT, b, true); printCmpResult(NPOT, b, c); zeroArray(SIZE, c); printDesc("naive scan, power-of-two"); StreamCompaction::Naive::scan(SIZE, c, a); printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - printArray(SIZE, c, true); + // printArray(SIZE, c, true); printCmpResult(SIZE, b, c); /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan @@ -64,35 +65,35 @@ int main(int argc, char* argv[]) { printDesc("naive scan, non-power-of-two"); StreamCompaction::Naive::scan(NPOT, c, a); printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - printArray(SIZE, c, true); + // printArray(SIZE, c, true); printCmpResult(NPOT, b, c); zeroArray(SIZE, c); printDesc("work-efficient scan, power-of-two"); StreamCompaction::Efficient::scan(SIZE, c, a); printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); + // printArray(SIZE, c, true); printCmpResult(SIZE, b, c); zeroArray(SIZE, c); printDesc("work-efficient scan, non-power-of-two"); StreamCompaction::Efficient::scan(NPOT, c, a); printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(NPOT, c, true); + // printArray(NPOT, c, true); printCmpResult(NPOT, b, c); zeroArray(SIZE, c); printDesc("thrust scan, power-of-two"); StreamCompaction::Thrust::scan(SIZE, c, a); printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); + // printArray(SIZE, c, true); printCmpResult(SIZE, b, c); zeroArray(SIZE, c); printDesc("thrust scan, non-power-of-two"); StreamCompaction::Thrust::scan(NPOT, c, a); printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(NPOT, c, true); + // printArray(NPOT, c, true); printCmpResult(NPOT, b, c); printf("\n"); diff --git a/src/testing_helpers.hpp b/src/testing_helpers.hpp index 46337ab..87028e5 100644 --- a/src/testing_helpers.hpp +++ b/src/testing_helpers.hpp @@ -50,7 +50,8 @@ void onesArray(int n, int *a) { } void genArray(int n, int *a, int maxval) { - srand(time(nullptr)); + // srand(time(nullptr)); + srand(1231412); for (int i = 0; i < n; i++) { a[i] = rand() % maxval; diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 36c5ef2..ece9d21 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -3,38 +3,129 @@ #include "common.h" #include "efficient.h" -namespace StreamCompaction { - namespace Efficient { - using StreamCompaction::Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } - - /** - * Performs prefix-sum (aka scan) on idata, storing the result into odata. - */ - void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - } - - /** - * Performs stream compaction on idata, storing the result into odata. - * All zeroes are discarded. - * - * @param n The number of elements in idata. - * @param odata The array into which to store elements. - * @param idata The array of elements to compact. - * @returns The number of elements remaining after compaction. - */ - int compact(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - return -1; - } +#define blockSize 256 + +namespace StreamCompaction +{ + namespace Efficient + { + int* device_idata; + int* device_odata; + int numObjects; + + using StreamCompaction::Common::PerformanceTimer; + + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } + + __global__ void kernel_UpSweep(int N, int powDP1, int* idata) + { + const int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= N) { + return; + } + + if (index % powDP1 != 0) + { + return; + } + + // x[k + 2d+1 – 1] += x[k + 2d – 1]; + idata[index + powDP1 - 1] += idata[index + (powDP1 / 2) - 1]; + } + + __global__ void kernel_DownSweep(int N, int powDP1, int* idata) + { + const int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= N) { + return; + } + + if (index % powDP1 != 0) + { + return; + } + + // Calculate some indices + const int leftChildIdx = index + (powDP1 / 2) - 1; + const int rightChildIdx = index + powDP1 - 1; + + // Save the left child + const int leftChild = idata[leftChildIdx]; + + // Set Left Child to Current Node's Value + idata[leftChildIdx] = idata[rightChildIdx]; + + // Set Right Child to Left + Right + idata[rightChildIdx] += leftChild; + } + + /** + * Performs prefix-sum (aka scan) on idata, storing the result into odata. + */ + void scan(int n, int* odata, const int* idata) + { + numObjects = n; + const int logN = ilog2ceil(numObjects); + const int nearestPower2 = std::pow(2, logN); + + cudaMalloc((void**)&device_idata, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_idata failed!"); + + cudaMemcpy(device_idata, idata, sizeof(int) * nearestPower2, cudaMemcpyHostToDevice); + + const int numBlocks = (numObjects + blockSize - 1) / blockSize; + dim3 fullBlocksPerGrid(numBlocks); + + int* loopInputBuffer = device_idata; + + // Up Sweep + timer().startGpuTimer(); + for (int d = 0; d < logN; ++d) + { + const int powDP1 = std::pow(2, d + 1); + kernel_UpSweep<<>>(numObjects, powDP1, loopInputBuffer); + } + timer().endGpuTimer(); + + // Set x[n-1] = 0 + // This seems really weird that we need to copy a 0 from host to the device. + // Might need to find a more efficient way. + const int lastValue = 0; + cudaMemcpy(&loopInputBuffer[nearestPower2 - 1], &lastValue, sizeof(int), cudaMemcpyHostToDevice); + + // Down Sweep + timer().startGpuTimer(); + for (int d = logN - 1; d >= 0; --d) + { + const int powDP1 = std::pow(2, d + 1); + kernel_DownSweep<<>>(numObjects, powDP1, loopInputBuffer); + } + timer().endGpuTimer(); + + cudaMemcpy(odata, loopInputBuffer, sizeof(int) * (numObjects), cudaMemcpyDeviceToHost); + + cudaFree(device_idata); + } + + /** + * Performs stream compaction on idata, storing the result into odata. + * All zeroes are discarded. + * + * @param n The number of elements in idata. + * @param odata The array into which to store elements. + * @param idata The array of elements to compact. + * @returns The number of elements remaining after compaction. + */ + int compact(int n, int* odata, const int* idata) + { + timer().startGpuTimer(); + // TODO + timer().endGpuTimer(); + return -1; } + } } diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index 36b732d..eed1bee 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -6,23 +6,42 @@ #include "common.h" #include "thrust.h" -namespace StreamCompaction { - namespace Thrust { - using StreamCompaction::Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } - /** - * Performs prefix-sum (aka scan) on idata, storing the result into odata. - */ - void scan(int n, int *odata, const int *idata) { - 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()); - timer().endGpuTimer(); - } +namespace StreamCompaction +{ + namespace Thrust + { + using StreamCompaction::Common::PerformanceTimer; + + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } + + /** + * Performs prefix-sum (aka scan) on idata, storing the result into odata. + */ + void scan(int n, int* odata, const int* idata) + { + // 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::host_vector thrust_host_idata = thrust::host_vector(n); + + for (int idx = 0; idx < n; ++idx) + { + thrust_host_idata[idx] = idata[idx]; + } + + thrust::device_vector thrust_device_idata = thrust_host_idata; + thrust::device_vector thrust_device_odata = thrust::device_vector(n, 0); + + timer().startGpuTimer(); + thrust::exclusive_scan(thrust_device_idata.begin(), thrust_device_idata.end(), thrust_device_odata.begin()); + timer().endGpuTimer(); + + thrust::copy(thrust_device_odata.begin(), thrust_device_odata.end(), odata); } + } } From 0f745d858efdf7c3c424e94ace05434894cd99bf Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sat, 15 Sep 2018 15:52:20 -0400 Subject: [PATCH 04/15] add: work efficient compaction --- stream_compaction/common.cu | 25 ++++++++++-- stream_compaction/efficient.cu | 75 +++++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/stream_compaction/common.cu b/stream_compaction/common.cu index 8fc0211..e189baa 100644 --- a/stream_compaction/common.cu +++ b/stream_compaction/common.cu @@ -22,17 +22,34 @@ namespace StreamCompaction { * Maps an array to an array of 0s and 1s for stream compaction. Elements * 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 + __global__ void kernMapToBoolean(int N, int *bools, const int *idata) { + + const int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= N) { + return; + } + + bools[index] = int(idata[index] != 0); } /** * Performs scatter on an array. That is, for each element in idata, * if bools[idx] == 1, it copies idata[idx] to odata[indices[idx]]. */ - __global__ void kernScatter(int n, int *odata, + __global__ void kernScatter(int N, int *odata, const int *idata, const int *bools, const int *indices) { - // TODO + + const int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= N) { + return; + } + + const int inputData = idata[index]; + if (bools[index] == 1) + { + const int outIdx = indices[index]; + odata[outIdx] = inputData; + } } } diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index ece9d21..a9943c4 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -2,6 +2,7 @@ #include #include "common.h" #include "efficient.h" +#include "naive.h" #define blockSize 256 @@ -10,6 +11,8 @@ namespace StreamCompaction namespace Efficient { int* device_idata; + int* device_bools; + int* device_scannedBools; int* device_odata; int numObjects; @@ -122,10 +125,78 @@ namespace StreamCompaction */ int compact(int n, int* odata, const int* idata) { + numObjects = n; + const int logN = ilog2ceil(numObjects); + const int nearestPower2 = std::pow(2, logN); + + cudaMalloc((void**)&device_idata, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_idata failed!"); + + cudaMalloc((void**)&device_odata, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_odata failed!"); + + cudaMalloc((void**)&device_bools, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_bools failed!"); + + cudaMalloc((void**)&device_scannedBools, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_scannedBools failed!"); + + cudaMemcpy(device_idata, idata, sizeof(int) * nearestPower2, cudaMemcpyHostToDevice); + + const int numBlocks = (numObjects + blockSize - 1) / blockSize; + dim3 fullBlocksPerGrid(numBlocks); + + // 1. Get Bool Array 1st timer().startGpuTimer(); - // TODO + Common::kernMapToBoolean<<>>(numObjects, device_bools, device_idata); timer().endGpuTimer(); - return -1; + + cudaMemcpy(device_scannedBools, device_bools, sizeof(int) * nearestPower2, cudaMemcpyDeviceToDevice); + + // 2. Scan the Bool Array + int* loopInputBuffer = device_scannedBools; + + // Up Sweep + timer().startGpuTimer(); + for (int d = 0; d < logN; ++d) + { + const int powDP1 = std::pow(2, d + 1); + kernel_UpSweep<<>>(numObjects, powDP1, loopInputBuffer); + } + timer().endGpuTimer(); + + // Set x[n-1] = 0 + // This seems really weird that we need to copy a 0 from host to the device. + // Might need to find a more efficient way. + const int lastValue = 0; + cudaMemcpy(&loopInputBuffer[nearestPower2 - 1], &lastValue, sizeof(int), cudaMemcpyHostToDevice); + + // Down Sweep + timer().startGpuTimer(); + for (int d = logN - 1; d >= 0; --d) + { + const int powDP1 = std::pow(2, d + 1); + kernel_DownSweep<<>>(numObjects, powDP1, loopInputBuffer); + } + timer().endGpuTimer(); + + // 3. Store in OData + Common::kernScatter<<>>(numObjects, device_odata, device_idata, device_bools, device_scannedBools); + + int boolArrayLast = 0; + cudaMemcpy(&boolArrayLast, &device_bools[nearestPower2 - 1], sizeof(int), cudaMemcpyDeviceToHost); + + int scannedLast = 0; + cudaMemcpy(&scannedLast, &device_scannedBools[nearestPower2 - 1], sizeof(int), cudaMemcpyDeviceToHost); + + const int totalEntries = scannedLast + boolArrayLast; + cudaMemcpy(odata, device_odata, sizeof(int) * (totalEntries), cudaMemcpyDeviceToHost); + + cudaFree(device_idata); + cudaFree(device_odata); + cudaFree(device_bools); + cudaFree(device_scannedBools); + return totalEntries; } } } From 238a046345588b64e26658f36d625567e22f61c6 Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sat, 15 Sep 2018 15:55:10 -0400 Subject: [PATCH 05/15] add: example related to count of elements after compaction in efficient.cu --- stream_compaction/efficient.cu | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index a9943c4..bbfe9dc 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -189,6 +189,16 @@ namespace StreamCompaction int scannedLast = 0; cudaMemcpy(&scannedLast, &device_scannedBools[nearestPower2 - 1], sizeof(int), cudaMemcpyDeviceToHost); + // Eg: + // 0101 is our bools + // Scanned: 0 0 1 1 (Exclusive) + // + // 01010 is our bools + // Scanned: 0 0 1 1 2 + // + // So we add bools[last] + Scanned[last] to get final count. + // In 1st case: 1 + 1 = 2 entries (final compaction count) + // In 2nd case: 2 + 0 = 2 entries (final compaction count) const int totalEntries = scannedLast + boolArrayLast; cudaMemcpy(odata, device_odata, sizeof(int) * (totalEntries), cudaMemcpyDeviceToHost); From 4433a0fd5225665a51cf9618d8c2a4aa5a4a322c Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sat, 15 Sep 2018 18:47:19 -0400 Subject: [PATCH 06/15] add: let timer accumulate data --- src/main.cpp | 9 +- stream_compaction/common.h | 233 ++++++++++++++++++++----------------- stream_compaction/naive.cu | 5 +- 3 files changed, 131 insertions(+), 116 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e66f268..64475db 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 = 128000; // 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]; @@ -26,7 +26,6 @@ int main(int argc, char* argv[]) { printf("****************\n"); printf("** SCAN TESTS **\n"); printf("****************\n"); - printf("Size of Array: %d", SIZE); genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case a[SIZE - 1] = 0; @@ -116,7 +115,7 @@ int main(int argc, char* argv[]) { count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a); printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); expectedCount = count; - printArray(count, b, true); + // printArray(count, b, true); printCmpLenResult(count, expectedCount, b, b); zeroArray(SIZE, c); @@ -124,14 +123,14 @@ int main(int argc, char* argv[]) { count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a); printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); expectedNPOT = count; - printArray(count, c, true); + // printArray(count, c, true); printCmpLenResult(count, expectedNPOT, b, c); zeroArray(SIZE, c); printDesc("cpu compact with scan"); count = StreamCompaction::CPU::compactWithScan(SIZE, c, a); printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(count, c, true); + // printArray(count, c, true); printCmpLenResult(count, expectedCount, b, c); zeroArray(SIZE, c); diff --git a/stream_compaction/common.h b/stream_compaction/common.h index 99a1b04..3e15dd7 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -16,117 +16,132 @@ /** * Check for CUDA errors; print and exit if there was a problem. */ -void checkCUDAErrorFn(const char *msg, const char *file = NULL, int line = -1); - -inline int ilog2(int x) { - int lg = 0; - while (x >>= 1) { - ++lg; - } - return lg; +void checkCUDAErrorFn(const char* msg, const char* file = NULL, int line = -1); + +inline int ilog2(int x) +{ + int lg = 0; + while (x >>= 1) + { + ++lg; + } + return lg; } -inline int ilog2ceil(int x) { - return x == 1 ? 0 : ilog2(x - 1) + 1; +inline int ilog2ceil(int x) +{ + return x == 1 ? 0 : ilog2(x - 1) + 1; } -namespace StreamCompaction { - namespace Common { - __global__ void kernMapToBoolean(int n, int *bools, const int *idata); - - __global__ void kernScatter(int n, int *odata, - const int *idata, const int *bools, const int *indices); - - /** - * This class is used for timing the performance - * Uncopyable and unmovable - * - * Adapted from WindyDarian(https://github.com/WindyDarian) - */ - class PerformanceTimer - { - public: - PerformanceTimer() - { - cudaEventCreate(&event_start); - cudaEventCreate(&event_end); - } - - ~PerformanceTimer() - { - cudaEventDestroy(event_start); - cudaEventDestroy(event_end); - } - - void startCpuTimer() - { - if (cpu_timer_started) { throw std::runtime_error("CPU timer already started"); } - cpu_timer_started = true; - - time_start_cpu = std::chrono::high_resolution_clock::now(); - } - - void endCpuTimer() - { - time_end_cpu = std::chrono::high_resolution_clock::now(); - - if (!cpu_timer_started) { throw std::runtime_error("CPU timer not started"); } - - std::chrono::duration duro = time_end_cpu - time_start_cpu; - prev_elapsed_time_cpu_milliseconds = - static_cast(duro.count()); - - cpu_timer_started = false; - } - - void startGpuTimer() - { - if (gpu_timer_started) { throw std::runtime_error("GPU timer already started"); } - gpu_timer_started = true; - - cudaEventRecord(event_start); - } - - void endGpuTimer() - { - cudaEventRecord(event_end); - cudaEventSynchronize(event_end); - - if (!gpu_timer_started) { throw std::runtime_error("GPU timer not started"); } - - cudaEventElapsedTime(&prev_elapsed_time_gpu_milliseconds, event_start, event_end); - gpu_timer_started = false; - } - - float getCpuElapsedTimeForPreviousOperation() //noexcept //(damn I need VS 2015 - { - return prev_elapsed_time_cpu_milliseconds; - } - - float getGpuElapsedTimeForPreviousOperation() //noexcept - { - return prev_elapsed_time_gpu_milliseconds; - } - - // remove copy and move functions - PerformanceTimer(const PerformanceTimer&) = delete; - PerformanceTimer(PerformanceTimer&&) = delete; - PerformanceTimer& operator=(const PerformanceTimer&) = delete; - PerformanceTimer& operator=(PerformanceTimer&&) = delete; - - private: - cudaEvent_t event_start = nullptr; - cudaEvent_t event_end = nullptr; - - using time_point_t = std::chrono::high_resolution_clock::time_point; - time_point_t time_start_cpu; - time_point_t time_end_cpu; - - bool cpu_timer_started = false; - bool gpu_timer_started = false; - - float prev_elapsed_time_cpu_milliseconds = 0.f; - float prev_elapsed_time_gpu_milliseconds = 0.f; - }; - } +namespace StreamCompaction +{ + namespace Common + { + __global__ void kernMapToBoolean(int n, int* bools, const int* idata); + + __global__ void kernScatter(int n, int* odata, + const int* idata, const int* bools, const int* indices); + + /** + * This class is used for timing the performance + * Uncopyable and unmovable + * + * Adapted from WindyDarian(https://github.com/WindyDarian) + */ + class PerformanceTimer + { + public: + PerformanceTimer() + { + cudaEventCreate(&event_start); + cudaEventCreate(&event_end); + } + + ~PerformanceTimer() + { + cudaEventDestroy(event_start); + cudaEventDestroy(event_end); + } + + void startCpuTimer() + { + if (cpu_timer_started) { throw std::runtime_error("CPU timer already started"); } + cpu_timer_started = true; + + time_start_cpu = std::chrono::high_resolution_clock::now(); + } + + void endCpuTimer() + { + time_end_cpu = std::chrono::high_resolution_clock::now(); + + if (!cpu_timer_started) { throw std::runtime_error("CPU timer not started"); } + + std::chrono::duration duro = time_end_cpu - time_start_cpu; + prev_elapsed_time_cpu_milliseconds = + static_cast(duro.count()); + + cpu_timer_started = false; + + accumulated_cpu_time_milliseconds += prev_elapsed_time_cpu_milliseconds; + } + + void startGpuTimer() + { + if (gpu_timer_started) { throw std::runtime_error("GPU timer already started"); } + gpu_timer_started = true; + + cudaEventRecord(event_start); + } + + void endGpuTimer() + { + cudaEventRecord(event_end); + cudaEventSynchronize(event_end); + + if (!gpu_timer_started) { throw std::runtime_error("GPU timer not started"); } + + cudaEventElapsedTime(&prev_elapsed_time_gpu_milliseconds, event_start, event_end); + gpu_timer_started = false; + + accumulated_gpu_time_milliseconds += prev_elapsed_time_gpu_milliseconds; + } + + float getCpuElapsedTimeForPreviousOperation() //noexcept //(damn I need VS 2015 + { + const float returnTime = accumulated_cpu_time_milliseconds; + accumulated_cpu_time_milliseconds = 0; + return returnTime; + } + + float getGpuElapsedTimeForPreviousOperation() //noexcept + { + const float returnTime = accumulated_gpu_time_milliseconds; + accumulated_gpu_time_milliseconds = 0; + return returnTime; + } + + // remove copy and move functions + PerformanceTimer(const PerformanceTimer&) = delete; + PerformanceTimer(PerformanceTimer&&) = delete; + PerformanceTimer& operator=(const PerformanceTimer&) = delete; + PerformanceTimer& operator=(PerformanceTimer&&) = delete; + + private: + cudaEvent_t event_start = nullptr; + cudaEvent_t event_end = nullptr; + + using time_point_t = std::chrono::high_resolution_clock::time_point; + time_point_t time_start_cpu; + time_point_t time_end_cpu; + + bool cpu_timer_started = false; + bool gpu_timer_started = false; + + float prev_elapsed_time_cpu_milliseconds = 0.f; + float prev_elapsed_time_gpu_milliseconds = 0.f; + float accumulated_cpu_time_milliseconds = 0.f; + float accumulated_gpu_time_milliseconds = 0.f; + }; + } } diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index c17a78d..06633ff 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -59,17 +59,18 @@ namespace StreamCompaction int* loopInputBuffer = device_idata; int* loopOutputBuffer = device_odata; - timer().startGpuTimer(); + for (int d = 1; d <= logN; ++d) { const int powD = std::pow(2, d - 1); + timer().startGpuTimer(); kernel_NaiveParallelScan<<>>(numObjects - 1, powD, loopOutputBuffer, loopInputBuffer); + timer().endGpuTimer(); int* temp = loopInputBuffer; loopInputBuffer = loopOutputBuffer; loopOutputBuffer = temp; } - timer().endGpuTimer(); cudaMemcpy((odata + 1), loopInputBuffer, sizeof(int) * (numObjects - 1), cudaMemcpyDeviceToHost); From c380f3500d484c52a4ae5c67b53ac770c4fbc6df Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sat, 15 Sep 2018 19:04:32 -0400 Subject: [PATCH 07/15] fix: access violation bug --- src/main.cpp | 275 +++++++++++++++++---------------- stream_compaction/common.h | 2 +- stream_compaction/efficient.cu | 8 +- stream_compaction/naive.cu | 8 +- 4 files changed, 149 insertions(+), 144 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 64475db..b9ae0df 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,142 +13,143 @@ #include #include "testing_helpers.hpp" -const int SIZE = 128000; // feel free to change the size of array +const int SIZE = 5'000'000; // 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]; -int *c = new int[SIZE]; - -int main(int argc, char* argv[]) { - // Scan tests - - printf("\n"); - printf("****************\n"); - printf("** SCAN TESTS **\n"); - printf("****************\n"); - - genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case - a[SIZE - 1] = 0; - printArray(SIZE, a, true); - - // initialize b using StreamCompaction::CPU::scan you implement - // We use b for further comparison. Make sure your StreamCompaction::CPU::scan is correct. - // At first all cases passed because b && c are all zeroes. - zeroArray(SIZE, b); - printDesc("cpu scan, power-of-two"); - StreamCompaction::CPU::scan(SIZE, b, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - // printArray(SIZE, b, true); - - zeroArray(SIZE, c); - printDesc("cpu scan, non-power-of-two"); - StreamCompaction::CPU::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - //printArray(NPOT, b, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("naive scan, power-of-two"); - StreamCompaction::Naive::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan - onesArray(SIZE, c); - printDesc("1s array for finding bugs"); - StreamCompaction::Naive::scan(SIZE, c, a); - printArray(SIZE, c, true); */ - - zeroArray(SIZE, c); - printDesc("naive scan, non-power-of-two"); - StreamCompaction::Naive::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(SIZE, c, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient scan, power-of-two"); - StreamCompaction::Efficient::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient scan, non-power-of-two"); - StreamCompaction::Efficient::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(NPOT, c, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("thrust scan, power-of-two"); - StreamCompaction::Thrust::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - zeroArray(SIZE, c); - printDesc("thrust scan, non-power-of-two"); - StreamCompaction::Thrust::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(NPOT, c, true); - printCmpResult(NPOT, b, c); - - printf("\n"); - printf("*****************************\n"); - printf("** STREAM COMPACTION TESTS **\n"); - printf("*****************************\n"); - - // Compaction tests - - genArray(SIZE - 1, a, 4); // Leave a 0 at the end to test that edge case - a[SIZE - 1] = 0; - printArray(SIZE, a, true); - - int count, expectedCount, expectedNPOT; - - // initialize b using StreamCompaction::CPU::compactWithoutScan you implement - // We use b for further comparison. Make sure your StreamCompaction::CPU::compactWithoutScan is correct. - zeroArray(SIZE, b); - printDesc("cpu compact without scan, power-of-two"); - count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - expectedCount = count; - // printArray(count, b, true); - printCmpLenResult(count, expectedCount, b, b); - - zeroArray(SIZE, c); - printDesc("cpu compact without scan, non-power-of-two"); - count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - expectedNPOT = count; - // printArray(count, c, true); - printCmpLenResult(count, expectedNPOT, b, c); - - zeroArray(SIZE, c); - printDesc("cpu compact with scan"); - count = StreamCompaction::CPU::compactWithScan(SIZE, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - // printArray(count, c, true); - printCmpLenResult(count, expectedCount, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient compact, power-of-two"); - count = StreamCompaction::Efficient::compact(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); - printCmpLenResult(count, expectedCount, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient compact, non-power-of-two"); - count = StreamCompaction::Efficient::compact(NPOT, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); - printCmpLenResult(count, expectedNPOT, b, c); - - system("pause"); // stop Win32 console from closing on exit - delete[] a; - delete[] b; - delete[] c; +int* a = new int[SIZE]; +int* b = new int[SIZE]; +int* c = new int[SIZE]; + +int main(int argc, char* argv[]) +{ + // Scan tests + + printf("\n"); + printf("****************\n"); + printf("** SCAN TESTS **\n"); + printf("****************\n"); + + genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case + a[SIZE - 1] = 0; + printArray(SIZE, a, true); + + // initialize b using StreamCompaction::CPU::scan you implement + // We use b for further comparison. Make sure your StreamCompaction::CPU::scan is correct. + // At first all cases passed because b && c are all zeroes. + zeroArray(SIZE, b); + printDesc("cpu scan, power-of-two"); + StreamCompaction::CPU::scan(SIZE, b, a); + printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); + // printArray(SIZE, b, true); + + zeroArray(SIZE, c); + printDesc("cpu scan, non-power-of-two"); + StreamCompaction::CPU::scan(NPOT, c, a); + printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); + //printArray(NPOT, b, true); + printCmpResult(NPOT, b, c); + + zeroArray(SIZE, c); + printDesc("naive scan, power-of-two"); + StreamCompaction::Naive::scan(SIZE, c, a); + printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(SIZE, c, true); + printCmpResult(SIZE, b, c); + + /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan + onesArray(SIZE, c); + printDesc("1s array for finding bugs"); + StreamCompaction::Naive::scan(SIZE, c, a); + printArray(SIZE, c, true); */ + + zeroArray(SIZE, c); + printDesc("naive scan, non-power-of-two"); + StreamCompaction::Naive::scan(NPOT, c, a); + printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(SIZE, c, true); + printCmpResult(NPOT, b, c); + + zeroArray(SIZE, c); + printDesc("work-efficient scan, power-of-two"); + StreamCompaction::Efficient::scan(SIZE, c, a); + printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(SIZE, c, true); + printCmpResult(SIZE, b, c); + + zeroArray(SIZE, c); + printDesc("work-efficient scan, non-power-of-two"); + StreamCompaction::Efficient::scan(NPOT, c, a); + printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(NPOT, c, true); + printCmpResult(NPOT, b, c); + + zeroArray(SIZE, c); + printDesc("thrust scan, power-of-two"); + StreamCompaction::Thrust::scan(SIZE, c, a); + printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(SIZE, c, true); + printCmpResult(SIZE, b, c); + + zeroArray(SIZE, c); + printDesc("thrust scan, non-power-of-two"); + StreamCompaction::Thrust::scan(NPOT, c, a); + printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(NPOT, c, true); + printCmpResult(NPOT, b, c); + + printf("\n"); + printf("*****************************\n"); + printf("** STREAM COMPACTION TESTS **\n"); + printf("*****************************\n"); + + // Compaction tests + + genArray(SIZE - 1, a, 4); // Leave a 0 at the end to test that edge case + a[SIZE - 1] = 0; + printArray(SIZE, a, true); + + int count, expectedCount, expectedNPOT; + + // initialize b using StreamCompaction::CPU::compactWithoutScan you implement + // We use b for further comparison. Make sure your StreamCompaction::CPU::compactWithoutScan is correct. + zeroArray(SIZE, b); + printDesc("cpu compact without scan, power-of-two"); + count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a); + printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); + expectedCount = count; + // printArray(count, b, true); + printCmpLenResult(count, expectedCount, b, b); + + zeroArray(SIZE, c); + printDesc("cpu compact without scan, non-power-of-two"); + count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a); + printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); + expectedNPOT = count; + // printArray(count, c, true); + printCmpLenResult(count, expectedNPOT, b, c); + + zeroArray(SIZE, c); + printDesc("cpu compact with scan"); + count = StreamCompaction::CPU::compactWithScan(SIZE, c, a); + printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); + // printArray(count, c, true); + printCmpLenResult(count, expectedCount, b, c); + + zeroArray(SIZE, c); + printDesc("work-efficient compact, power-of-two"); + count = StreamCompaction::Efficient::compact(SIZE, c, a); + printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + //printArray(count, c, true); + printCmpLenResult(count, expectedCount, b, c); + + zeroArray(SIZE, c); + printDesc("work-efficient compact, non-power-of-two"); + count = StreamCompaction::Efficient::compact(NPOT, c, a); + printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + //printArray(count, c, true); + printCmpLenResult(count, expectedNPOT, b, c); + + system("pause"); // stop Win32 console from closing on exit + delete[] a; + delete[] b; + delete[] c; } diff --git a/stream_compaction/common.h b/stream_compaction/common.h index 3e15dd7..8839022 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -107,7 +107,7 @@ namespace StreamCompaction accumulated_gpu_time_milliseconds += prev_elapsed_time_gpu_milliseconds; } - float getCpuElapsedTimeForPreviousOperation() //noexcept //(damn I need VS 2015 + float getCpuElapsedTimeForPreviousOperation() //noexcept { const float returnTime = accumulated_cpu_time_milliseconds; accumulated_cpu_time_milliseconds = 0; diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index bbfe9dc..6d2aa57 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -3,6 +3,7 @@ #include "common.h" #include "efficient.h" #include "naive.h" +#include #define blockSize 256 @@ -78,7 +79,8 @@ namespace StreamCompaction cudaMalloc((void**)&device_idata, nearestPower2 * sizeof(int)); checkCUDAError("cudaMalloc device_idata failed!"); - cudaMemcpy(device_idata, idata, sizeof(int) * nearestPower2, cudaMemcpyHostToDevice); + cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); + checkCUDAError("cudaMemcpy failed!"); const int numBlocks = (numObjects + blockSize - 1) / blockSize; dim3 fullBlocksPerGrid(numBlocks); @@ -141,7 +143,7 @@ namespace StreamCompaction cudaMalloc((void**)&device_scannedBools, nearestPower2 * sizeof(int)); checkCUDAError("cudaMalloc device_scannedBools failed!"); - cudaMemcpy(device_idata, idata, sizeof(int) * nearestPower2, cudaMemcpyHostToDevice); + cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); const int numBlocks = (numObjects + blockSize - 1) / blockSize; dim3 fullBlocksPerGrid(numBlocks); @@ -181,7 +183,9 @@ namespace StreamCompaction timer().endGpuTimer(); // 3. Store in OData + timer().startGpuTimer(); Common::kernScatter<<>>(numObjects, device_odata, device_idata, device_bools, device_scannedBools); + timer().endGpuTimer(); int boolArrayLast = 0; cudaMemcpy(&boolArrayLast, &device_bools[nearestPower2 - 1], sizeof(int), cudaMemcpyDeviceToHost); diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 06633ff..e3360df 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -52,25 +52,25 @@ namespace StreamCompaction cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); - dim3 fullBlocksPerGrid((numObjects + blockSize - 1) / blockSize); + const int numBlocks = (numObjects + blockSize - 1) / blockSize; + dim3 fullBlocksPerGrid(numBlocks); const int logN = ilog2ceil(numObjects); int* loopInputBuffer = device_idata; int* loopOutputBuffer = device_odata; - + timer().startGpuTimer(); for (int d = 1; d <= logN; ++d) { const int powD = std::pow(2, d - 1); - timer().startGpuTimer(); kernel_NaiveParallelScan<<>>(numObjects - 1, powD, loopOutputBuffer, loopInputBuffer); - timer().endGpuTimer(); int* temp = loopInputBuffer; loopInputBuffer = loopOutputBuffer; loopOutputBuffer = temp; } + timer().endGpuTimer(); cudaMemcpy((odata + 1), loopInputBuffer, sizeof(int) * (numObjects - 1), cudaMemcpyDeviceToHost); From 0f72cf34120a3f87fd4bc5426337dc2d7c6b9a0b Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sun, 16 Sep 2018 20:07:00 -0400 Subject: [PATCH 08/15] add: shared memory implementation on UpSweep --- src/main.cpp | 11 +++- stream_compaction/efficient.cu | 108 +++++++++++++++++++++++++++++++++ stream_compaction/efficient.h | 1 + stream_compaction/naive.cu | 52 ++++++++++++++++ stream_compaction/naive.h | 1 + stream_compaction/thrust.cu | 9 +-- 6 files changed, 172 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b9ae0df..64e66c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 5'000'000; // feel free to change the size of array +const int SIZE = 1 << 16; // 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]; @@ -72,7 +72,7 @@ int main(int argc, char* argv[]) printDesc("work-efficient scan, power-of-two"); StreamCompaction::Efficient::scan(SIZE, c, a); printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - // printArray(SIZE, c, true); + printArray(SIZE, c, true); printCmpResult(SIZE, b, c); zeroArray(SIZE, c); @@ -82,6 +82,13 @@ int main(int argc, char* argv[]) // printArray(NPOT, c, true); printCmpResult(NPOT, b, c); + zeroArray(SIZE, c); + printDesc("work-efficient scan optimized v1, power-of-two"); + StreamCompaction::Efficient::scanOptimized_v1(SIZE, c, a); + printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + printArray(SIZE, c, true); + printCmpResult(SIZE, b, c); + zeroArray(SIZE, c); printDesc("thrust scan, power-of-two"); StreamCompaction::Thrust::scan(SIZE, c, a); diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 6d2aa57..0b2b4c7 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -17,6 +17,18 @@ namespace StreamCompaction int* device_odata; int numObjects; + void printArray(int n, int *a, bool abridged = false) { + printf(" [ "); + for (int i = 0; i < n; i++) { + if (abridged && i + 2 == 15 && n > 16) { + i = n - 2; + printf("... "); + } + printf("%3d ", a[i]); + } + printf("]\n"); + } + using StreamCompaction::Common::PerformanceTimer; PerformanceTimer& timer() @@ -41,6 +53,39 @@ namespace StreamCompaction idata[index + powDP1 - 1] += idata[index + (powDP1 / 2) - 1]; } + __global__ void kernel_UpSweepOptimized_v1(int N, int numThreads, int powD, int* idata) + { + extern __shared__ int temp[]; + + const int threadID = threadIdx.x; + const int threadID2X = 2 * threadIdx.x; + const int staticIdx = threadID2X + (blockIdx.x * N) + (powD - 1); + + int offset = 1; + + temp[threadID2X] = idata[staticIdx]; + temp[threadID2X + 1] = idata[staticIdx + powD]; + + // build sum in place up the tree + for (int d = numThreads; d > 0; d >>= 1) + { + __syncthreads(); + if (threadID < d) + { + const int ai = offset * (threadID2X + 1) - 1; + const int bi = offset * (threadID2X + 2) - 1; + temp[bi] += temp[ai]; + } + + offset *= 2; + } + + __syncthreads(); + + idata[staticIdx] = temp[threadID2X]; + idata[staticIdx + powD] = temp[threadID2X + 1]; + } + __global__ void kernel_DownSweep(int N, int powDP1, int* idata) { const int index = threadIdx.x + (blockIdx.x * blockDim.x); @@ -101,7 +146,70 @@ namespace StreamCompaction // Might need to find a more efficient way. const int lastValue = 0; cudaMemcpy(&loopInputBuffer[nearestPower2 - 1], &lastValue, sizeof(int), cudaMemcpyHostToDevice); + + // Down Sweep + timer().startGpuTimer(); + for (int d = logN - 1; d >= 0; --d) + { + const int powDP1 = std::pow(2, d + 1); + kernel_DownSweep<<>>(numObjects, powDP1, loopInputBuffer); + } + timer().endGpuTimer(); + + cudaMemcpy(odata, loopInputBuffer, sizeof(int) * (numObjects), cudaMemcpyDeviceToHost); + + cudaFree(device_idata); + } + void scanOptimized_v1(int n, int* odata, const int* idata) + { + numObjects = n; + const int logN = ilog2ceil(numObjects); + const int nearestPower2 = std::pow(2, logN); + + cudaMalloc((void**)&device_idata, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_idata failed!"); + + cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); + checkCUDAError("cudaMemcpy failed!"); + + const int numBlocks = (numObjects + blockSize - 1) / blockSize; + dim3 fullBlocksPerGrid(numBlocks); + + int* loopInputBuffer = device_idata; + + const int numCount = nearestPower2; + + int upSweepBlockCount = (numCount + blockSize - 1) / blockSize; + + int depth = 0; + + // Up Sweep + timer().startGpuTimer(); + while(upSweepBlockCount > 0) + { + const int powD = std::pow(2, depth); + const int powD1 = std::pow(2, depth + 1); + + dim3 upSweepBlocks(upSweepBlockCount); + + const int numObjectsPerBlock = numCount / upSweepBlockCount; + + const int threadsPerBlock = numObjectsPerBlock / powD1; + + kernel_UpSweepOptimized_v1<<>>(numObjectsPerBlock, threadsPerBlock, powD, loopInputBuffer); + + upSweepBlockCount /= 2; + depth = ilog2ceil(numObjectsPerBlock); + } + timer().endGpuTimer(); + + // Set x[n-1] = 0 + // This seems really weird that we need to copy a 0 from host to the device. + // Might need to find a more efficient way. + const int lastValue = 0; + cudaMemcpy(&loopInputBuffer[nearestPower2 - 1], &lastValue, sizeof(int), cudaMemcpyHostToDevice); + // Down Sweep timer().startGpuTimer(); for (int d = logN - 1; d >= 0; --d) diff --git a/stream_compaction/efficient.h b/stream_compaction/efficient.h index 803cb4f..338a2b9 100644 --- a/stream_compaction/efficient.h +++ b/stream_compaction/efficient.h @@ -7,6 +7,7 @@ namespace StreamCompaction { StreamCompaction::Common::PerformanceTimer& timer(); void scan(int n, int *odata, const int *idata); + void scanOptimized_v1(int n, int *odata, const int *idata); int compact(int n, int *odata, const int *idata); } diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index e3360df..97d286b 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -38,6 +38,34 @@ namespace StreamCompaction odata[index] = idata[index - powD] + idata[index]; } + __global__ void kernel_NaiveSharedParallelScan(int N, int* odata, int* idata) + { + extern __shared__ float temp[]; + const int index = threadIdx.x; + int pout = 0; + int pin = 1; + + temp[pout * N + index] = (index > 0) ? idata[index - 1] : 0; + __syncthreads(); + + for (int offset = 1; offset < N; offset *= 2) + { + // swap double buffer indices + pout = 1 - pout; + pin = 1 - pout; + + if (index >= offset) { + temp[pout * N + index] += temp[pin * N + index - offset]; + } + else { + temp[pout * N + index] = temp[pin * N + index]; + } + __syncthreads(); + } + + odata[index] = temp[pout * N + index]; // write output + } + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ @@ -77,5 +105,29 @@ namespace StreamCompaction cudaFree(device_idata); cudaFree(device_odata); } + + void scanShared(int n, int* odata, const int* idata) + { + numObjects = n; + cudaMalloc((void**)&device_idata, numObjects * sizeof(int)); + checkCUDAError("cudaMalloc device_idata failed!"); + + cudaMalloc((void**)&device_odata, numObjects * sizeof(int)); + checkCUDAError("cudaMalloc device_odata failed!"); + + cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); + + const int numBlocks = (numObjects + blockSize - 1) / blockSize; + dim3 fullBlocksPerGrid(numBlocks); + + timer().startGpuTimer(); + kernel_NaiveSharedParallelScan<<>>(numObjects, device_odata, device_idata); + timer().endGpuTimer(); + + cudaMemcpy(odata, device_odata, sizeof(int) * (numObjects), cudaMemcpyDeviceToHost); + + cudaFree(device_idata); + cudaFree(device_odata); + } } } diff --git a/stream_compaction/naive.h b/stream_compaction/naive.h index 37dcb06..3c7a284 100644 --- a/stream_compaction/naive.h +++ b/stream_compaction/naive.h @@ -7,5 +7,6 @@ namespace StreamCompaction { StreamCompaction::Common::PerformanceTimer& timer(); void scan(int n, int *odata, const int *idata); + void scanShared(int n, int *odata, const int *idata); } } diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index eed1bee..ff7ca6a 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -27,14 +27,7 @@ namespace StreamCompaction // example: for device_vectors dv_in and dv_out: // thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); - thrust::host_vector thrust_host_idata = thrust::host_vector(n); - - for (int idx = 0; idx < n; ++idx) - { - thrust_host_idata[idx] = idata[idx]; - } - - thrust::device_vector thrust_device_idata = thrust_host_idata; + thrust::device_vector thrust_device_idata(idata, idata + n); thrust::device_vector thrust_device_odata = thrust::device_vector(n, 0); timer().startGpuTimer(); From dc88054d9fedf222a878ac399cc2f8b6baa92abe Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sun, 16 Sep 2018 22:47:33 -0400 Subject: [PATCH 09/15] add: remaining code for tasks --- src/main.cpp | 14 +++---- stream_compaction/efficient.cu | 68 +++++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 64e66c7..0e8a2c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 16; // feel free to change the size of array +const int SIZE = 4; // 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]; @@ -82,12 +82,12 @@ int main(int argc, char* argv[]) // printArray(NPOT, c, true); printCmpResult(NPOT, b, c); - zeroArray(SIZE, c); - printDesc("work-efficient scan optimized v1, power-of-two"); - StreamCompaction::Efficient::scanOptimized_v1(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); + // zeroArray(SIZE, c); + // printDesc("work-efficient scan optimized v1, power-of-two"); + // StreamCompaction::Efficient::scanOptimized_v1(SIZE, c, a); + // printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(SIZE, c, true); + // printCmpResult(SIZE, b, c); zeroArray(SIZE, c); printDesc("thrust scan, power-of-two"); diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 0b2b4c7..fc2f39b 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -5,7 +5,7 @@ #include "naive.h" #include -#define blockSize 256 +#define blockSize 4 namespace StreamCompaction { @@ -86,6 +86,43 @@ namespace StreamCompaction idata[staticIdx + powD] = temp[threadID2X + 1]; } + __global__ void kernel_DownSweepOptimized_v1(int N, int numThreads, int powD, int* idata, int* odata) + { + extern __shared__ int temp[]; + + const int threadID = threadIdx.x; + const int threadID2X = 2 * threadIdx.x; + const int staticIdx = threadID2X + (blockIdx.x * N) + (powD - 1); + + int offset = N / 2; + + temp[threadID2X] = idata[staticIdx]; + temp[threadID2X + 1] = idata[staticIdx + powD]; + + // traverse down tree & build scan + for (int d = 1; d <= numThreads; d *= 2) + { + offset >>= 1; + + __syncthreads(); + + if (threadID < d) + { + const int ai = (threadID2X + 1) - 1; + const int bi = (threadID2X + 2) - 1; + + const int t = temp[ai]; + temp[ai] = temp[bi]; + temp[bi] += t; + } + } + + __syncthreads(); + + idata[staticIdx] = temp[threadID2X]; + idata[staticIdx + powD] = temp[threadID2X + 1]; + } + __global__ void kernel_DownSweep(int N, int powDP1, int* idata) { const int index = threadIdx.x + (blockIdx.x * blockDim.x); @@ -169,6 +206,9 @@ namespace StreamCompaction cudaMalloc((void**)&device_idata, nearestPower2 * sizeof(int)); checkCUDAError("cudaMalloc device_idata failed!"); + + cudaMalloc((void**)&device_odata, nearestPower2 * sizeof(int)); + checkCUDAError("cudaMalloc device_idata failed!"); cudaMemcpy(device_idata, idata, sizeof(int) * numObjects, cudaMemcpyHostToDevice); checkCUDAError("cudaMemcpy failed!"); @@ -181,6 +221,7 @@ namespace StreamCompaction const int numCount = nearestPower2; int upSweepBlockCount = (numCount + blockSize - 1) / blockSize; + const int downSweepBlockCount = (numCount + blockSize - 1) / blockSize; int depth = 0; @@ -209,17 +250,32 @@ namespace StreamCompaction // Might need to find a more efficient way. const int lastValue = 0; cudaMemcpy(&loopInputBuffer[nearestPower2 - 1], &lastValue, sizeof(int), cudaMemcpyHostToDevice); - + + depth = logN - 1; + int currentDownSweepBlockCount = 1; // Down Sweep timer().startGpuTimer(); - for (int d = logN - 1; d >= 0; --d) + while(currentDownSweepBlockCount <= downSweepBlockCount) { - const int powDP1 = std::pow(2, d + 1); - kernel_DownSweep<<>>(numObjects, powDP1, loopInputBuffer); + int powD = std::pow(2, depth); + dim3 downSweepBlocks(currentDownSweepBlockCount); + + const int numObjectsPerBlock = numObjects / currentDownSweepBlockCount; + int threadsPerBlock = 1; + + if (currentDownSweepBlockCount == downSweepBlockCount) + { + threadsPerBlock = blockSize / 2; + powD = 1; + } + + kernel_DownSweepOptimized_v1<<>>(numObjectsPerBlock, threadsPerBlock, powD, loopInputBuffer, device_odata); + currentDownSweepBlockCount *= 2; + depth--; } timer().endGpuTimer(); - cudaMemcpy(odata, loopInputBuffer, sizeof(int) * (numObjects), cudaMemcpyDeviceToHost); + cudaMemcpy(odata, device_odata, sizeof(int) * (numObjects), cudaMemcpyDeviceToHost); cudaFree(device_idata); } From 9716e6bedaab7384334fcb02a319abb109188eca Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Sun, 16 Sep 2018 23:23:52 -0400 Subject: [PATCH 10/15] add: stats --- src/main.cpp | 11 +- stats.txt | 683 +++++++++++++++++++++++++++++++++ stream_compaction/efficient.cu | 28 +- stream_compaction/naive.cu | 2 +- 4 files changed, 697 insertions(+), 27 deletions(-) create mode 100644 stats.txt diff --git a/src/main.cpp b/src/main.cpp index 0e8a2c8..d2c8fed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 4; // feel free to change the size of array +const int SIZE = 1 << 20; // 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]; @@ -72,7 +72,7 @@ int main(int argc, char* argv[]) printDesc("work-efficient scan, power-of-two"); StreamCompaction::Efficient::scan(SIZE, c, a); printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - printArray(SIZE, c, true); + // printArray(SIZE, c, true); printCmpResult(SIZE, b, c); zeroArray(SIZE, c); @@ -96,6 +96,13 @@ int main(int argc, char* argv[]) // printArray(SIZE, c, true); printCmpResult(SIZE, b, c); + zeroArray(SIZE, c); + printDesc("thrust scan, power-of-two"); + StreamCompaction::Thrust::scan(SIZE, c, a); + printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); + // printArray(SIZE, c, true); + printCmpResult(SIZE, b, c); + zeroArray(SIZE, c); printDesc("thrust scan, non-power-of-two"); StreamCompaction::Thrust::scan(NPOT, c, a); diff --git a/stats.txt b/stats.txt new file mode 100644 index 0000000..d261f0c --- /dev/null +++ b/stats.txt @@ -0,0 +1,683 @@ +2^8 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 42 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.000485ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.000485ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.027648ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.02672ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.062464ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.053248ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 2.9655ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.012288ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.012288ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.000969ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.000969ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.00097ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.06144ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.072704ms (CUDA Measured) + passed + + +2^9 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 42 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.00097ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.001455ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.07168ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.068608ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.16384ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.159744ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 5.3432ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.037888ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.065536ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.020849ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.001455ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.002909ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.291872ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.274432ms (CUDA Measured) + passed +Press any key to continue . . . + +2^10 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 33 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.001454ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.001455ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.121856ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.120832ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.262144ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.260096ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 4.86912ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.066592ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.065536ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 3 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.003394ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.002424ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.004849ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.296928ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.296928ms (CUDA Measured) + passed +Press any key to continue . . . + +2^11 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 32 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.002909ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.00291ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.138208ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.13824ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.292864ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.29696ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 4.81174ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.099328ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.098304ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 0 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.007758ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.005819ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.010182ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.330784ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.338912ms (CUDA Measured) + passed +Press any key to continue . . . + +2^12 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 34 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.006303ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.007272ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.094208ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.093184ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.195584ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.195584ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 4.67661ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.068608ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.068608ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.011636ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.016ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.050909ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.234464ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.238592ms (CUDA Measured) + passed +Press any key to continue . . . + +2^13 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 37 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.011636ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.012121ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.104416ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.104448ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.227264ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.22528ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 5.12ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.114688ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.114656ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 3 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.054304ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.020848ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.055272ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.442304ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.413696ms (CUDA Measured) + passed + +2^14 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 39 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.024727ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.024242ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.134176ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.123904ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.32256ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.31744ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 5.11894ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.19248ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.191456ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 1 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.077091ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.067878ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.092121ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.557024ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.5816ms (CUDA Measured) + passed +Press any key to continue . . . + +2^15 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 30 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.049455ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.055273ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.16688ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.166912ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.40336ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.423904ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 4.97254ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.224224ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.22016ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 0 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.123152ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.112ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.157576ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.785088ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.767744ms (CUDA Measured) + passed +Press any key to continue . . . + +2^16 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 15 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.090182ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.100364ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.42864ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.427808ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 1.12845ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 1.12813ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 5.9095ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.39424ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.343072ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 3 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.246788ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.269576ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.343758ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 1.21734ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 1.23866ms (CUDA Measured) + passed + +2^17 + +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 48 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.188121ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.27103ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 0.390816ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.390144ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 1.0687ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 1.05984ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 5.56237ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.55088ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.451584ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 0 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.390788ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.402424ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 0.555637ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 2.16781ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 2.13808ms (CUDA Measured) + passed + +2^18 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 32 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 1.07976ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.442182ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 1.35885ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 1.34733ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 3.74992ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 3.77731ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 5.58698ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.605184ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.628736ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 1.06182ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.744727ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 1.53648ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 4.00554ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 4.0591ms (CUDA Measured) + passed + +2^19 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 18 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 2.2177ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 0.796606ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 2.67267ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 2.64694ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 7.54173ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 7.57734ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 6.18493ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.754688ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.709632ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 1.488ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 1.48994ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 2.63418ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 7.96368ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 7.97901ms (CUDA Measured) + passed + +2^20 +**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 4 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 5.36679ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 1.74352ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 3.00848ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 2.95424ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 15.3444ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 15.3364ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 6.64576ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 1.1745ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 1.1223ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 2.69624ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 2.80679ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 4.72727ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 16.1515ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 16.1321ms (CUDA Measured) + passed \ No newline at end of file diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index fc2f39b..a06a881 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -5,7 +5,7 @@ #include "naive.h" #include -#define blockSize 4 +#define blockSize 512 namespace StreamCompaction { @@ -251,27 +251,12 @@ namespace StreamCompaction const int lastValue = 0; cudaMemcpy(&loopInputBuffer[nearestPower2 - 1], &lastValue, sizeof(int), cudaMemcpyHostToDevice); - depth = logN - 1; - int currentDownSweepBlockCount = 1; // Down Sweep timer().startGpuTimer(); - while(currentDownSweepBlockCount <= downSweepBlockCount) + for (int d = logN - 1; d >= 0; --d) { - int powD = std::pow(2, depth); - dim3 downSweepBlocks(currentDownSweepBlockCount); - - const int numObjectsPerBlock = numObjects / currentDownSweepBlockCount; - int threadsPerBlock = 1; - - if (currentDownSweepBlockCount == downSweepBlockCount) - { - threadsPerBlock = blockSize / 2; - powD = 1; - } - - kernel_DownSweepOptimized_v1<<>>(numObjectsPerBlock, threadsPerBlock, powD, loopInputBuffer, device_odata); - currentDownSweepBlockCount *= 2; - depth--; + const int powDP1 = std::pow(2, d + 1); + kernel_DownSweep<<>>(numObjects, powDP1, loopInputBuffer); } timer().endGpuTimer(); @@ -315,15 +300,12 @@ namespace StreamCompaction // 1. Get Bool Array 1st timer().startGpuTimer(); Common::kernMapToBoolean<<>>(numObjects, device_bools, device_idata); - timer().endGpuTimer(); - cudaMemcpy(device_scannedBools, device_bools, sizeof(int) * nearestPower2, cudaMemcpyDeviceToDevice); // 2. Scan the Bool Array int* loopInputBuffer = device_scannedBools; // Up Sweep - timer().startGpuTimer(); for (int d = 0; d < logN; ++d) { const int powDP1 = std::pow(2, d + 1); @@ -344,10 +326,8 @@ namespace StreamCompaction const int powDP1 = std::pow(2, d + 1); kernel_DownSweep<<>>(numObjects, powDP1, loopInputBuffer); } - timer().endGpuTimer(); // 3. Store in OData - timer().startGpuTimer(); Common::kernScatter<<>>(numObjects, device_odata, device_idata, device_bools, device_scannedBools); timer().endGpuTimer(); diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 97d286b..39049e1 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -4,7 +4,7 @@ #include "naive.h" #include -#define blockSize 256 +#define blockSize 512 namespace StreamCompaction { From 12ee231a7cac7adb4cd097f3f6dfdae13dddbe0e Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Mon, 17 Sep 2018 00:09:10 -0400 Subject: [PATCH 11/15] add: initial readme --- README.md | 80 ++++++++++++++++++++++++++++++++++++++++---- img/compactNPO2.PNG | Bin 0 -> 36377 bytes img/compactPO2.PNG | Bin 0 -> 28792 bytes img/scanNPO2.PNG | Bin 0 -> 34743 bytes img/scanPO2.PNG | Bin 0 -> 30349 bytes 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 img/compactNPO2.PNG create mode 100644 img/compactPO2.PNG create mode 100644 img/scanNPO2.PNG create mode 100644 img/scanPO2.PNG diff --git a/README.md b/README.md index 0e38ddb..516b153 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,80 @@ CUDA Stream Compaction ====================== -**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** +**University of Pennsylvania, CIS 565: GPU Programming and Architecture, +Project 1 - Flocking** -* (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) +* Vasu Mahesh + * [LinkedIn](http://linkedin.com/in/vasumahesh) + * [Code Blog](http://www.codeplaysleep.com) -### (TODO: Your README) +* Tested on a Laptop: + * Windows 10 + * i7-8650U @ 1.90GHz + * 16GB RAM + * GTX 1060 6GB + * Visual Studio 2017 (with v140 toolset) + * CUDA v8.0 -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +![](img/intro.PNG) +## Build + +Build Command: +``` +cmake -G "Visual Studio 15 2017 Win64" -DCUDA_TOOLKIT_ROOT_DIR="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0" -T v140,cuda=8.0 .. +``` +I tried to implement the shared memory and thread optimziation. But had issues with DownSweep and kind of ran out of time. + +## Results + +### Scan Performance + +If we just implement the barebones scan algorithm it turns out that they are quite slower. A point to note here Thrust initially had a pretty slow time of around 4ms and then the subsequent Thrust calls are very fast. I suspect Thrust lazy loads some modules and since the thrust scan function was the 1st one, it affected the readings. To avoid this, I ended up calling scan again and got optimal performance. + +![](img/scanPO2.PNG) + +![](img/scanNPO2.PNG) + +| Elements in Array | CPU Scan (Power of 2) | CPU Scan (Non Power of 2) | Naive Scan (Power of 2) | Naive Scan (Non Power of 2) | Work Efficient Scan (Power of 2) | Work Efficient Scan (Non Power of 2) | Thrust Scan (Power of 2) | Thrust Scan (Non Power of 2) | +| ----------- |------------------------------------|-------------------------------------- |-----------------|-----------------|-----------------|-----------------|-----------------|-----------------| + +| 2^8 | 0.000485 | 0.000485 | 0.027648 | 0.02672 | 0.062464 | 0.053248 | 0.012288 | 0.012288 | +| 2^9 | 0.00097 | 0.001455 | 0.07168 | 0.068608 | 0.16384 | 0.159744 | 0.037888 | 0.065536 | +| 2^10 | 0.001454 | 0.001455 | 0.121856 | 0.120832 | 0.262144 | 0.260096 | 0.066592 | 0.065536 | +| 2^11 | 0.002909 | 0.00291 | 0.138208 | 0.13824 | 0.292864 | 0.29696 | 0.099328 | 0.098304 | +| 2^12 | 0.006303 | 0.007272 | 0.094208 | 0.093184 | 0.195584 | 0.195584 | 0.068608 | 0.068608 | +| 2^13 | 0.011636 | 0.012121 | 0.104416 | 0.104448 | 0.227264 | 0.22528 | 0.114688 | 0.114656 | +| 2^14 | 0.024727 | 0.024242 | 0.134176 | 0.123904 | 0.32256 | 0.31744 | 0.19248 | 0.191456 | +| 2^15 | 0.049455 | 0.055273 | 0.16688 | 0.166912 | 0.40336 | 0.423904 | 0.224224 | 0.22016 | +| 2^16 | 0.090182 | 0.100364 | 0.42864 | 0.427808 | 1.12845 | 1.12813 | 0.39424 | 0.343072 | +| 2^17 | 0.188121 | 0.27103 | 0.390816 | 0.390144 | 1.0687 | 1.05984 | 0.55088 | 0.451584 | +| 2^18 | 1.07976 | 0.442182 | 1.35885 | 1.34733 | 3.74992 | 3.77731 | 0.605184 | 0.628736 | +| 2^19 | 2.2177 | 0.796606 | 2.67267 | 2.64694 | 7.54173 | 7.57734 | 0.754688 | 0.709632 | +| 2^20 | 5.36679 | 1.74352 | 3.00848 | 2.95424 | 15.3444 | 15.3364 | 1.1745 | 1.1223 | + + + +### Compaction Performance + +I suffered similar performance issues with work efficient scans in the compact as well. + +![](img/compactPO2.PNG) + +![](img/compactNPO2.PNG) + +| Elements in Array | CPU Compact without scan (Power of 2) | CPU Compact without scan (Non Power of 2) | CPU Compact with Scan | Work Efficient Compact (Power of 2) | Work Efficient Compact (Non Power of 2) | +| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | +| 2^8 | 0.000969 | 0.000969 | 0.00097 | 0.06144 | 0.072704 | +| 2^9 | 0.020849 | 0.001455 | 0.002909 | 0.291872 | 0.274432 | +| 2^10 | 0.003394 | 0.002424 | 0.004849 | 0.296928 | 0.296928 | +| 2^11 | 0.007758 | 0.005819 | 0.010182 | 0.330784 | 0.338912 | +| 2^12 | 0.011636 | 0.016 | 0.050909 | 0.234464 | 0.238592 | +| 2^13 | 0.054304 | 0.020848 | 0.055272 | 0.442304 | 0.413696 | +| 2^14 | 0.077091 | 0.067878 | 0.092121 | 0.557024 | 0.5816 | +| 2^15 | 0.123152 | 0.112 | 0.157576 | 0.785088 | 0.767744 | +| 2^16 | 0.246788 | 0.269576 | 0.343758 | 1.21734 | 1.23866 | +| 2^17 | 0.390788 | 0.402424 | 0.555637 | 2.16781 | 2.13808 | +| 2^18 | 1.06182 | 0.744727 | 1.53648 | 4.00554 | 4.0591 | +| 2^19 | 1.488 | 1.48994 | 2.63418 | 7.96368 | 7.97901 | +| 2^20 | 2.69624 | 2.80679 | 4.72727 | 16.1515 | 16.1321 | diff --git a/img/compactNPO2.PNG b/img/compactNPO2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..b40e02edcc9713d6592ddf4f71278ccd49603a50 GIT binary patch literal 36377 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 literal 0 HcmV?d00001 diff --git a/img/compactPO2.PNG b/img/compactPO2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..afb113fdcba68c84802a505b7bf36f3709843b14 GIT binary patch literal 28792 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 literal 0 HcmV?d00001 diff --git a/img/scanNPO2.PNG b/img/scanNPO2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..7dba75bf557d8d7e16b590d2281ee6ecfa92bf5a GIT binary patch literal 34743 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 E2SK&ywEzGB literal 0 HcmV?d00001 diff --git a/img/scanPO2.PNG b/img/scanPO2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f188838008348fc4117d85848503047e116f42bd GIT binary patch literal 30349 zcmdSBc{tSV`!}u>MYu~P*{O(Z$-a}US+ZrBC}b!5I#fcXEZLHM%NDYYWf-BXk*qP6 z?8Y$Gu?)j=&5Zl=e7?tXJjd_f=XW37$9;RhulKc_*Ll9q*ZI0Gz0uWHrJ=e?MMg$O zqpo)M0T~&20U6oJ8)qoMlQQj}gcm0~9;hmjmGm&9zz?Tv74Iv8S5edlk57Z2&puN# z@gO6kZ6W-7qRlnmnvBewQ~j=@f$yW0aY|q25wCeXB%op2UtY4fq5OQiRv_0&w+g}K9RxmHjDHp|D|Ev7miDWm(K$^|8HOYe|G!-MgxTxKU1ZROKRt@ zGTydUtJ_*-5_3|c3&5fBatjMJ92^|_jwn7T?dNO{^Oe@$_RZaTTibZeZBN)2B{`E8 zfbrXux$U{ATTom~6P9&hQEX@?*=3=%we_zd*(-xMmIlizdhePo1q%p-pIayGoM~bh zg~8+js{ZCq)stTO$+fALeg+9KNW+<7Y%aQD0L?c^f!ugHQxZ~FSNC_&ZdA1x`ryyO zMXR(AH3vT)(6$XV-Ho#HAKP$_knl9K&luds?2Dd5N%C6Y{NELLLS>I?+L+<@$Q0C6 z7^%{qL36oJ!5vMgyeSQjDvuZk_saarr~J!w?fhe=OPDMS`$B(MnoT%0ADLXpYrHO; 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 i|91`k-N)A@J0BhL>RPv#<$SMoTbSBjue Date: Mon, 17 Sep 2018 00:09:51 -0400 Subject: [PATCH 12/15] fix: readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 516b153..b85945e 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,6 @@ If we just implement the barebones scan algorithm it turns out that they are qui | Elements in Array | CPU Scan (Power of 2) | CPU Scan (Non Power of 2) | Naive Scan (Power of 2) | Naive Scan (Non Power of 2) | Work Efficient Scan (Power of 2) | Work Efficient Scan (Non Power of 2) | Thrust Scan (Power of 2) | Thrust Scan (Non Power of 2) | | ----------- |------------------------------------|-------------------------------------- |-----------------|-----------------|-----------------|-----------------|-----------------|-----------------| - | 2^8 | 0.000485 | 0.000485 | 0.027648 | 0.02672 | 0.062464 | 0.053248 | 0.012288 | 0.012288 | | 2^9 | 0.00097 | 0.001455 | 0.07168 | 0.068608 | 0.16384 | 0.159744 | 0.037888 | 0.065536 | | 2^10 | 0.001454 | 0.001455 | 0.121856 | 0.120832 | 0.262144 | 0.260096 | 0.066592 | 0.065536 | From 399e860af34b65afc951b960566ca00da1822a37 Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Mon, 17 Sep 2018 00:15:58 -0400 Subject: [PATCH 13/15] add: missing images --- img/intro.PNG | Bin 0 -> 119769 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/intro.PNG diff --git a/img/intro.PNG b/img/intro.PNG new file mode 100644 index 0000000000000000000000000000000000000000..0b7daec3f2bbbb047add8d716ea562df4902baa1 GIT binary patch literal 119769 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%0Du6Z&({p1C?0(=$U%v?{p5-M{7C(44v|42LC^6 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�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 Rmm(_daWku<#fQ&c`#;Jn!|wn9 literal 0 HcmV?d00001 From 4a31e270b704ebb5d666a746cd024b6ff9dd51eb Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Tue, 18 Sep 2018 17:01:34 -0400 Subject: [PATCH 14/15] add: final details of shared mem --- README.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++- img/shared.PNG | Bin 0 -> 27012 bytes 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 img/shared.PNG diff --git a/README.md b/README.md index b85945e..0fa3bfc 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,13 @@ If we just implement the barebones scan algorithm it turns out that they are qui | 2^19 | 2.2177 | 0.796606 | 2.67267 | 2.64694 | 7.54173 | 7.57734 | 0.754688 | 0.709632 | | 2^20 | 5.36679 | 1.74352 | 3.00848 | 2.95424 | 15.3444 | 15.3364 | 1.1745 | 1.1223 | +There seems to be such a discrepency in my Work Efficient one because I believe it is highly inefficient (shared memory difference below). The Work efficient one performed poorly for me even against my CPU. This could be because the threads aren't grouped and the waste the SM's utilization. After the class, I realized that the implemented code could be way faster as I was launching N threads for N numbers (in total). This was later resolved to N/2. The values however you see are for the "naive" version of the work efficient algorithm. +### Scan with Shared Memory + +I implemented a partial implementation of the Work Efficient Scan (Only UpSweep). I got a significant boost because I ended up launching only the required amount of threads for the entries in the array. However, this implementation was a little different and I believe less efficient than the one shown in class. This is because the threads are not clumped together. Grouping of threads is much better because it helps in early warp termination. + +![](img/shared.PNG) ### Compaction Performance @@ -60,7 +66,57 @@ I suffered similar performance issues with work efficient scans in the compact a ![](img/compactPO2.PNG) -![](img/compactNPO2.PNG) +![](img/compactNPO2.PNG)**************** +** SCAN TESTS ** +**************** + [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 4 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 7.32024ms (std::chrono Measured) +==== cpu scan, non-power-of-two ==== + elapsed time: 2.39758ms (std::chrono Measured) + passed +==== naive scan, power-of-two ==== + elapsed time: 1.45482ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 1.45306ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 1.80938ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 1.8143ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 4.02115ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.503808ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.471008ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 3 3 3 0 1 2 0 0 0 1 1 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 4.38158ms (std::chrono Measured) + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 3.77454ms (std::chrono Measured) + passed +==== cpu compact with scan ==== + elapsed time: 12.5959ms (std::chrono Measured) + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 2.10064ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 2.10413ms (CUDA Measured) + passed +Press any key to continue . . . | Elements in Array | CPU Compact without scan (Power of 2) | CPU Compact without scan (Non Power of 2) | CPU Compact with Scan | Work Efficient Compact (Power of 2) | Work Efficient Compact (Non Power of 2) | | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | @@ -77,3 +133,10 @@ I suffered similar performance issues with work efficient scans in the compact a | 2^18 | 1.06182 | 0.744727 | 1.53648 | 4.00554 | 4.0591 | | 2^19 | 1.488 | 1.48994 | 2.63418 | 7.96368 | 7.97901 | | 2^20 | 2.69624 | 2.80679 | 4.72727 | 16.1515 | 16.1321 | + + +### Output Log + +``` + +``` \ No newline at end of file diff --git a/img/shared.PNG b/img/shared.PNG new file mode 100644 index 0000000000000000000000000000000000000000..db22ca3e6822577546782b2aa4011786c1531e67 GIT binary patch literal 27012 zcmdSBc{tSV`#-Eri=^d7B}p6ElO<%3L?mR(IwIMPeXr1T<>c+m)H3^&-0pI>)ummKXm#K3kwVT z9gSP}Sy=WIv#{(II=~8^EUx@^0Y7$m-dDfLQrLEe2!7dXr=qRG!crW`w()Qu`2C=p zhKVN&%aKOL-(AhH+(#@d4yW$iQZaa9IX6T}KGT!5MV~C{C!mvSYgP;EY9g*bb#Weh zZZaC|Y!mYQuf|P{bI(s+JgRX%;=u9q2SU$1KdKkv(S{XN|3_fbOUbixy6NS#zVy&F z-Y>S5Mc{)s^e0 zeExSpsO)Ulbj+&-B^|?`88C^k`VA<3TiyQW>|ID&IQyqFu3|kTTVho})zVtX5(rmhh z!*2ej>^4cua|yKInsj#P=aomqvmTNl`;s_j2DAMez4>%U6bPnjfZqa-FH4XRqX&v#?d{B`IL!Z!g;+ zGHj$+qdQ%zM!z-vu|IRIk)4ke&`YMm3Pob8V45Cn@e!#Uy=1*bIWfjkZk5s-dF)6r zM5AfD?=9gUDIQkW!Pz(mBlkDej2$osR$?HhLqdk!Dbe~mfm!r#K9{6@RC3TgHY}iGPv>kn+wftAS?Db+fBR|q(}TWv)c;%Wp`d^!(wV-n zPxs(xiJRhuUYqmC!MXXkK&duc%o4pYLA%QvpU~N-kR`8;kDvT^>mL=sAJo~q*+#gLwg(u9fb#K1G-_F8#(Jp=Y zHnZC4Z9)rZe(~E5pSOi41LvHOV3KJ*< z7FE)`NUWR>kU3j6I4R19KY~|JZm(>Ae4R#Gg;jBQy^p9Hfixq_!rLYzY*J)NTCCp5 z&I++&jTPEkJ!u6x<=Wq;k8OUeY6(yKN;zL&ipbo0>mRZEj>;>wAEg48h`;S|kdOF)5w<)2 zySjpg1XkUMKc3S*{k8nFCbV(hDRRc|oAdiZ0^+Kt7GGtUIKfMlP%Hb9lc6 zx-L;Yj;v-$y!r|+TdCwZZkaw6wx-K{Sj=SxHUCn$w)SI0Wv?#1h&xda5k+1VR^URd zoHh%r`mIajbLEqbC@X*z;zt89&Q*V#LW}B(mJ>N_FOGhj=%T-x=2Hws&Asy9{CX%& zzbTuRx@XYW3mWQw#Br_IZA>_&eUlH;wa8J(_U8N4m)H~JIZ~)Y;eS*9S|RoFjkDl%XP2rb&k+KVh}jt} zK80aDo5mql!YXo9uC}deQbE+h#{hi>`Um`4t6;!05ZBlJk*&o|bzqa;{@sKVfFiZ&l^&Ye(>8!f^gb0w2r z@+yszLgE!56!J?bFt2vj`YX zy@V|D+a+VkDSTPZs2bx&Mmpl%wvaZe)%2V!7jN3KyW+hH-U@bVQDk9P{76L7byxI{ zVi^>Q-ILN>F=X47uj7@}3mq7qo0;DjfXirWHJ8D7#S~&i#nLB*Sfp5__x*^8 zr=8CpTpxYFrBy+Ea)>_b)V2yG(lbKy#8UVb zo0%h(#l8q`7l=D;>MWG7)}1!D=7>fP+8l#a#)?mkSzjN$Sv`knCJY%9R&Tr0>fyD{ zNqSv98f_|+we|QSS~TWIQ6$W{Dsug1jsLN^dzH=K@Ykae#xg}lSJP}f<$Ojw>rCmL2nyns(;V)ekOD=vyE|9w(I!18&6VOZ+8DUVU#ceYhL4yDvHENejO2N@DqIX> z5kZ!_{w30x=To8DVBi71qIbWXBAwWCw%(Svj3@5SQhueT=9$))Vfpn_UjWs5vV@JV zAeTE3UN^$c4&S`q+eCTxuS0ko9r~R*3^lXOC$fjrYjK^eU*k~2oB{Nj7 z+mySz_^tBgn+@=H>Eg38b-KJb^AhuMgD%s$xQb&pCV zN0W*I_sO(K?MNQD`{F6?)`43oVeWK^*j$Ki#jmQbkZ8{iMf9f#y}=)WA95kZft0xz zUYwi#*YW4gGa9QF{iAx#(g|0cyBhJ2+XdX0gep@oL!?~y&tCn#ZIyhhH+W=2zx{2> z#PsqE!_#sXtej1|i*+k3Miw3}YagvtD)2(hCu_OWAGe3B78yMWg#PhrkGtNRt-B=T zA8?VL<1ANwMnC-@hVNIS`e=OtBLabxzn3D)4=RmBdIfUIYLAyh|R=wbE|$whLB>qudiPelDBlm?2b^ zcXE}@839KKBBG+%^B`;Mz)RZ0i?qVoh1|{Zh0mOq98Xm*7kJPb+56X*YhDz%UGLm1 z2ip{@@fh+k^BG)|Qk~Ng!?cb+5gdXkM!MW^AZ|6ntZ%I(|IV31*kBQ-?5Y@3Y zMHiBc)f7n{xMM%S31*+(=l}lcQ?+=6yUw47)ZLuYP%)j=FAtXTsvLw8yl;tKz_DGd zN$lkIg(h}1yU3}=SstzuUt4|Bz4_UE^(xKIAN~13SNRJgD&q@r?pyCm^BiE zDzzcAi9c5IL~*z#_9#=N&Vay3{l~wn7ZPmjT)uJN9mwfTI4wE%SDz1_kcT%t;68e@ zf3$kpp?jg*drHl-TW++*zRbaWhPOq|-sVT8>k0VV(ObWBW-6P9=pM}$Yt>CS%kW2p zIPI`$C}MEn)@##HMUub%cg`Liy+~Ts$5t1oT_zMozUsGZwli<1m2kSW7)*(W+*vWj zVbW0d{AQI+TT`e7_k*FUeTd883-k_n=_v>dTt{ zRtSik3H;=EoldT3d3lzNAa7AIm@DI_lEdvtLIFMDPgn9)pHXlcukXwk?4Fx5JDK zA1vkeOfwhv32>(C(Q-Wcn@7IdBJnQVm#ax(cy;+A%h@r%{eYVpyCw(pU41=cZ02gt zGs@~s#|<@C(SMHjnIyZVnWc9xnc}PXb@9_OoFO$w5)@Ol(n4ts5ieI$+Q^o-gpFy;wnJ zaSmRikUM&}de?7AOO)`8@zBfbtF=*DTk3N;#SZQ^iV345qix(IEroj(MXRNX%~MM$ zzw;uiZKMZ_8iyd#z$|_%U^g+ga>`eZ0kS(NVCSzc9pV4bTCwMTNcrqo)o2o8NqEted4#vhJ48B$I$0aZvV;x@(&!Mvr8a= zurIpq>-w`)+P9N%cU$24%0jO1TgPu+a6IJ>BvV!uXh7QM+U;}OU0fN#-+|D>wZ>VR ze|HJP!$_OeGhu$aa4r=Nq^qmp{FG0UX`8aZdLE#uO<9|>tNw+}B98u}tBrG$g1wi| z{F(jxpj{D4IMVFa{Gz0JbfQwmRjJCR9xg^)=$OM2L9%y2ZvV^EOCyu5^9&!7iKVf| z#T7-yYIBeYApEdP7wyO>VKU|&ME$vmM(0vS>QR4oJ*2iwD59Z@-F5Z-SywxJ5vCZ@JJ~5=kx-K#@b;0V?ULhoS5V=| zTeco=gseHI7YB8ovX-{3Rv~m^(9{J*6bHF4A3Xtin{}8 zo}4|ZiF4{I`-Vt&HXZbf^EY3T+aISeQJ%8sl4kUT@Yfz+weD3jXghJgk~qMp z%4;KR5mDYVxo0MC{?Jx20r7(`*^8`JnUCl@cmkPmW* zS{k80RQMIJq$QK_fgmyX#;x*Qn&C&o^cvwK7MLrnlfI=G)CXK%@pM%~9PPZGmYV9>@a`pN8O49-X^fr!eTXq`*QeS=KI zhQ(DaoJbXSb)NE={VRyugjc&Pa#mXSeSE|nKQecylHGXi1A`hg<&-a^s8@um8V>r- zo^Gl7N*vkr0Pv^uJ=|SX0Um&`a{1evciZDgQ@F2xYFS!F(-)n=J_+CjF3EsyGlYjP z%iZ*Dz8hO*Yfm^*?m|5?!U~Jg+5!Z-3e)S&ksx{@p*R6k{RRJ5q4I5c*E#v_CtgG+ zz3b1Zn(d8(u1~rb6?3X)I_6%Tplmp0VU|vjYGp(To1XnhbxGIYn-{)Y8+3AOvMW)) zO+%7qwpOlEj+n*H{|JLD)No&*ZdGxsWzBSO@58eqMh-%c_DKz8GsLw!wIb|z`C&?m zEoHZ+_<`Als>QmRBKk2@VrO6pyg6fP-}{PU-~6<)Eoc9~tDWkTU2G>PiA2fJ0j{j2 zX?IU?Q!hEa(c1}=h0Q~O_#$%}!PaGQ2%dreLke*XvpB5ol5mfMT(b$~TXL}*3>=e$ z6ok7*V#I{Jhvz+3)~43&@rgQHptxht3zf>U^B^pl3%@ zZ9)4G#1=7!uM~8*X`FID^Ci4w?oAB~UmJ>}2kqlrW)b@_{$u+ddC^)I)jF@ z*S#`WljELd{WC7r3@JjlcPj4pIbr?ME|YEt3w%3vVM_VxQR}BSj#)olbQf=)b3re zsg@6jDd#9!iDk>XEy#yC|K2+RR@RaDXVLXN;#XN8d}>zfRn>{>H!cvBYDU|54rrYJ zzqZ!;zbOb`=;W_Jp)8x;o{IS_C@n3WR#}W)XVj2c;slEME53Z0W^3rqK_caa%LW1% zkAqudejas#8_!HnLpZ)bY?>o}--Q!z$cQsOOfR`8`5hU0sMv3^$I#47YrEPVd?;@E zsMFJ)XZb@f*a<1y1#p8C-cd3&&p+ox zQ`P%NjroV&;)fL0JC+W&ZtN22<{FLIu7ao6-siENqd*Z44f!~NMouvHagNS-27ibk z+?=KLS~DIgQ?q2g3n9$+f^_@%_e=fy<469+!n$z>73b9W{)Pyqb>)I;IDTi^7d=qV){j_lRx6I z(JPn0#ds@6Tc)WgzgdAxwe%3TVmYmAD$r-kaz&UeB8}oUoixm$uj~|r_M>zqdp(n# ziLJHSf}%OC@y1I3+%34VGx&3AqqoT}qdYRUI9+XgXKKxI)OCn(eFY@QU!q)+xz}?q zsD-I5hrXH)(Fh!-2A7#9&(v+EMcVG`YkG;|zFT0vGwH`BUqb7lVqQL_Q~&cYi8Mrh zwC_Q|(|9eFuvWF5lQ|Tws~QEn_E70iG+>@!3Aq#-3Yjno6eIt?X3Fh zIRJak zY2&_#iPT;Z{+?>)_p;Ij`z7%#yMO1K%N7urXAK^T8~~8eE!_> zTn|bt6J#pJ0av}b4&HPl7^_ifAzT?|=T)~O!CND3HrOv<26yM1#Re<|?r!l++%^D(Ll_9lJxB$Fc1#S*`#(r7n(H3GH~1 zUnW1e5vnm6r63a1s%WT0Z=o9jET7iaHN zV#t{+dN}+1k)79bC+lA_1h6$tOyBpH+0RaYZfd#a1c1OI&`yF=bq9xDFI&jJ1McQ` z1aZ8qUUz4u^K(vIKqc8PVF$9$bMLJ5u8FoKApG5@Ta^8O9zG@U!nPr2wJCj{$Bqvl zw-21&0%yX{TzmHUCns}LZ}KV2sf^S6d#HEpuHI4fyYjlL!ou}3N}DrQLW?`^pFch2 z92Z)%bqTEIijcN{8t`8p&-o+Utf#wsuRa5^(l_K~MHon2x}~3q7H5o<`EF!rh~WP~ zwNGX=dIehcK6tim6w(RZzAc+$lT_$cQI>lK^t)uBTH{r}_fZnst zM9zcPLI36RLX(cZt4y1}2*YdUTWca-l@qCxPqrmDNQEdcfYvX<`GBd_#qH4CvZ!{C z@nQ5QdWx^ft_ost+CKfO_g^0_=DLT->Us-9#^H}J255dNQZHV|#rJIzN- zf0UXYTm+WulDK~9)RZHesa58VNuB$x6&MFX<8ZBP;+vbyOA^YvmQ(xU8GC4-Wj9Sf zx-*o;rAWK|(AVEOgwuD`J~FM>>N)E`;bU-UQVMLJsO}E@octK!-3|=3sT#_W{V9t1 zzQj#!wn9b(A}b!htH#gtYOB3Sj=)&36jdzkuxa|gLw6ToNDOU;M1BN4bH>Re?$V9# zF&0V<;oC2&YtJf zQQgBk?}x_czrI0^2X@WCjIqK`EohO{AT7;=zrwSTO=VB4skN%JpK9RcQFm%C=$|$(* z1}$&6!oY`9|3~P9f}6$kk2`$Z(X0E1FAi+4RQT}|{QZ8zyB92)bJwhMo<806FMYUu z$D4Oekbz>B@+21>TVn=y5Q07kXRBl!P$IT>9R3)@T-zYF>`#Nh_lM8|PHT_1v$Mt? z__)C~Q<#4Uwige8a)gnXak`rQB)ni8UIOWrZ;=Qh5%-2f;+u;aJHGE>U$qrf3YZPj z?%8LJ-8+^rJ+N-Xm+~Lt^aLwnRaIaPhrl|MVg=oSp2EmlXrh!Cs0! zzo%|Uh3!8t^e*>l15-it>;bc|@66KU>1D&%nqrWk{nN~yDauWusQ?#~6Nb6&s_kSE zZ#C(^xf%SGk_r#u+9@*x>wO;0Xa;;4xWkd`^PidSa67AMn*8`hUjzr&e*Jd_J4d@m zK~Wg*Lr1H@(U>gJs@uVr)DBSA`^R%Dp=c)4ureUlJh{kFTz3(NX=Yc?glkge-&cdz zZAyQc`$;T$USfLFNy7nxuLN*>ML!z}>AI#i!X+qrsjFRUkITO!q*X0IQ<5HM>(&&Ie61+i7@lz=%ZY8t(s@=Y3k0obdOGp0-2T z+3nTBDU0+Lo;v>3d17z6;ZCY_lG9ITj*(E**{$vs#oGOiMhvr%unW%Y8zh+r}oRW*(I=ul|7a1|F**1X+eSHO*#f z$V`TU-{4Ftr5JFxPPTGHmX%Rj+wELdLi=1^@`M=0g>9Qm`d?|q#S8$Ho1_ge=$9WU zO12)dHB3xbv)x(CUh!owgZH5@0?)XJ3)2FVwYz*;V*r7Ti)7C6saynojY0nBaaN9g zvr7Gc*}uvfxI~AATd3si9Ahb0Et5V=_3WFA4&Hy z#ww5QA^ZeMUfK=LyV@_M&BXln%+7I;kC?s{1MGceWhJTJ)Xa?Mh6lhh?Fo1A21|w+ zrO*&KkyHALX2<#UdlvQyGnbt~h$EcLx0xJxW|W~dt(qTdWbExNz3m0TQc6oTz`rUa zEz$So_RK1hJtyIuOm375?6Dd4Uc3 z#n1A^B6pIMT(9nTd;G@%mj>Xb4-;Lk&@pux^41MBC~x4gCTu=QgQsS0XF-n5_Ezjc zC)}?-%b(-;mp-)=b-^Ifz?gq+z&|T}Z3kJ7wCjiwEZAZVdk^GKMpwhVcx~B=S7}8f zUqR(0!S}|-3!MvBB_x!0%321RUwju585Gg65ad#hKla-JyP#g%Upp6L`XhGWD9?)M zcb}IPQQMMJmR~+I#Gn*@?RMe0LX$& z7=5Blqj10RnFZE90fPLovfw-3+o7AKYhfV&>FaY$a>~yt7bH~|eJ{|lldoeAda&N&=CJ8zhCyzt_ zVgCx!&y3~N!DD5bsb6xAJlQiV%y)@KfyXdo!#QsxrEZerYe-L>op*?wb)p$K zpZ9u-O4!)@<+VUqFv4YMJ$>Kp9mVLGLX!Ys0?N<7N3mt|HX$od$9Kt1uW+R=>R%Mf2cDYkf%K}I(cQAK?L8L8Y}~b1`-vQgQl1CwbY9? ztR?cPH)nfQ!&QX;+0Asues8|D4jxP3Ehx@1%|ib)C185(1#-M)$~!4UtRcCdj&*BC z`|ojX7SI8ravI+T{>2kCKtGumxr0lHu)6agfdKlds3ftOUcx<%5e05V?+*7EaWw8Y z^nzJ2)RhsHMuS1|+?%J%G%A#g$jhO99B}g^rs*9_F|~ej8J7aGG?lu|iUi2pvNE67 zT)S%(=m#VgJBh(1T=A+N7zCJ8Ci(uN>Yw+b+`tOj*?d5jvy&%W>M0+$g#n%-hrDVZ zXPzVO^Aj%MIv?71!7e6fzucVAc}B|H0?J{KqGFq7*6qyr;+^)7I<+H)c}_GQmApqh z=qE+8^{DF2Qjj|U^o{Re+}_VrC9H>dc=sj%J&a}ufIY4*e~B4pQGok05`_5aqh=Ns zDa?vjv`cz{%4t3n2+R24L?Gh|c3L4of7pa`LSgD=I_DeF9)6=e`K%^jVwRR(^CfkL zlWeZ0tCdJstp3!#R{2DAw(Wwpig4^rM^$GF3yaI&dwY9XBN^j0KK0_Vfnt_ylwzK? z0b)_|+uW~%$10%!ROysIXUcqceA08&OkY1{9Vg0O#dxK)h)xIctZ;9`Ws?7Pf>-L6 zM@(SB1%A`Y9lNt)K}n8qceVs3R9GZFC~h=U@^8Jmwdh`5-A`aq_X0NFfRNIokTwf6 zIg{fYC91&TJNfYq?UFI04qj8Zdex>*)l9HL>ECkOxKXoGKqs)Xdv&GX6?CxE^$m@S zc_x4l`TUqx9QMt1V$gB*zkvcq`avI6XY1=({*6y^M(yjWST}Nz-yUb${;;~Gi^X4{ z^1w|Z(Z1jCsZ@VXeGqW5Ur%rP{LNJ;V;u2K5xVZqd#=szK<18QVEqJzWHA7P1TNA+ z({%Hla(Y^IZ(1X>%8)K)n#w!FzFnTMe-|JCaY}#@%0W3J&}oDEODfj*3kd1woPH3( z89cri~ZdvJd2=QhsBIS&6pSE#11kUCFJfjZ0O*fPmG4mhbu_71Bf!Z9nPR_{0#|p-)l^7<4#RHP} zwG`C?2&E5&%fWf>peg?yrjssWjTA6ER>@qO4_F5Phit+142f3`qK9~_WoK(nm)*qf zOqLJ0KJb!uCXu{?#^XJSSj*cdBD#FrX-GC|_H>Su0x~ z0WFgS*~JcRzu*3jogstr@i;Kzj2wP~{VO4*Oz$3a_JAq>P7YzcVsYa#yXPjJ$4X&1 zNXkC$Y>@AhO4;v){T^3AuEP}PD=APC(2g7$V`rpM`wOr(dUHT67W1v0U_%ki4c*7E zRRR%c{pMrv+>rjR*H@)xpy zD#a9eRIe=@M1PQnvzcaMoMzfUAo_j@Aijq1_F@vP<#p1{JfN()rOaw71_U|!=Q9^9 zm_8D#?Xjt8*Kx>!*-5!w9HEoC%G#HA4Sf+|*X4^_ta$0;t2(hZQbtztpC zTcK2c#Hjr#M~D%z#BKa4Fp}kR8x^)p-t9XL- zS1!{BtYQHp&^*nz77ET)WOB4jGeNQW{TMAq)=$-$p46MpDYT0@l^UxbGSjz39LQ-d z?g}u<>h8Wv=peTo+4|l06UCgglVRhd2mYU+q?H)Z@WOfU?-rv z00k766#?S}t3_6^_%D5!!*=#?m)*MbIgtUo7i^l|w)_LUDp-6v-)tICGxDY}QL#<{ z7^nNLRqE&DM_aGs(=Q2Wt3B_dQmO5GM7FoM_6hW)*7nR=d6Ug}$}~B4&rTT~W28kw z`k>*mEwlPgf9o3AT1Ri!C;VWxy$>=W-+Oy{Y@g)~hhN&x4TEq5H>1;&2;dKl)*53P z5rb(}(B8DUHe$F6cPiz%Z1qtveA#K^O&{`%Yb}dsJB; z5CRO=^L9EkbPMpR9_Nv&|IR>O7qt!L(RcZLMXu&Aw8eBI`#Mh1j{QY6C)X|Mwd7iB zy1ZH$fivJu!gS@s;Ja%4G~3sdnKTa5tUc&GVa%q$xpBXH&IwKX(SQxl<$>HJYtJsO zor3?BUj41lQo~zlfSgF{n*d%9eEq4W_JV=+R#L=)ufITS0|~!LW|6FYQo!B^W6WYj zrY@eRl;O7^*U(}l3AT&Jtln{Kdr;JQdiZ44coM<4G0$jJl@K%B<^Qa=MLk#zwQXU_ zn#*VU&xLaYG=jNJQ)w~Fm6iuh1^9MxH8Rcfe!5dv*zh06p3NhKn{Rj8gBQ*5W}dYT zJztzK!YUZAbM@92nX}zok%dOZzgKz^k{7?}(g%3)vtFWd@DB~9A?%%&t1#I%7O+_S z@MXGa!uIEC{M(oj{G2$j5iMI~T3+;?r|d4Uq(jUU;GzZ|?^)N-qq)a*;HZ_J#@II5@ zrN2d1pr+XijTnufvb)^7MRv-(v3F<+ON`TbjxMI#BEbuHw--$R4(i657|)ZcyOmoSGjL@i=>4bM;$P%>l z(ru|=VjIJAZ)p|G^7;Dn%s^i+aoDT;&P>>7ZG&MRD2m0B_VBS5bcL~m?bQ8zrxk0U+f)nK zf5L_)Rg9OzG>3Z^*Bz#q7CY+v0S3vI**s)P#zPJ`; zlLBVE9jt~0Gln{(1G;Nr!Fz*IO?i74@O13*ln%oKeHYrZ$e@4fjRdD=<>a(xHrQTZ z>n1H6K;LD1gSL!z061VcOITShC|<)smm9lP$so?Umb`qT3qWCQk*UBEfEzm82i+)g zeQ1zQ#ZfO`Ce`g0{2W3X-{=ZjWX0Y6y%GH(fNZi=dnNz3!jabB6jzWu^4%RiM=r#Z zQzAe8{gNnj`TKw@CpYM5{acYS?DuwFGOfP8rM@{Y|A3nhsS@Gh*RB9N{U0#=N7`Vg zd6jnux+gzS!Tsvt!-scT+nkmb{y2?B#Vry@Z9&s5b~E)Jxz-^+j6J28kAE0m+poZ< zHh%wy!7-3^FhW5{8aQ0=hF9Q5Cd29isxI1_oLb|3kZHoGcp0-Zx)sVOP!yFUNX)Vo znzF;U^1R3Lhdw6kmc{aqxv)z${)cyiCy#6d@E&ZjUo~1|Xky zJ|`E;_+E3c4rP-g6L3OCqUHU=Lb7A%7<1SgFboW^x-O4XoCBu7OIG44%RjUCfx+=@ zC%FCc=`IHgx!(+@d%O|jMKDr9_odi!G`OTzdG?8aIVV`AbvJ}pohSD9&5307lP zWz#>coY~MgO`?l4v~3cY1FU;rf$;uaTyfiY9sH)pq_UgGykLOf55!<{;A`%qZRaw` ztiU}67H3FllMRWFd%+T>x!sIWR%39E_i1b4vQ^;30U^t&!zaoLMfN^;%VdfMZ&Oug zGC{7z*pY2N;Zb^qoV^8@_@wAIEax5oVQ2|h)hc{)zi3y{=K}TBv#|J{WbvOdu(a4y z()-7euX(_5&h6n>x(ER(NJ`p1BNFyntYzl%(Maeri-ak8OIX8Y>cSn_lVk^#b+T*<%iQbg4;kD)38>`f-NgLk-*H`NBwI8L@&ewmsza2D=KT6LL z_Iz0~Ix3L0vX1_~iO?59nWmx@Jt;B=2NY;y^F*U{E7~RB)uAp)+PbO-UbSYMZtj`V z00^nM-6#~iK*?y()(RYFw=vkv;`0}KS(+gKsB4qecO}NNI@mynjf+ULkG)^$7Wws@%4Fm(0@{Gs%8fE0sv9QP zek^&gvSear`z;!=__Nh!aX?`5(b7{^xuC3TeVSHY+nLQj8f#`DL&4I~j#U(;{d)$| zBtI5UPBk^S4Iaxsc8ZR`p$eXyM6G3MHnXi}X|8v3WIM+eFTqMK%CZB z+q$2Xi(E&!NUpTdOUA-aEcS-BKbm}Zxq48lcAow1b~Y4jew~lK7yWtQ3BkB-m)G_2 zK&dLgkE~umGx=bOh=qX!*18JPK$>-@vKNMqXW)b6)4S+*Mq8m%I(E+Qu2P)ipuYy* zSLdxI%i+f>IcB2>N>$fR3~$z2Rc?5XoUL9eR`kIAt&=1!Ad+mggC>+G;39TPa6wOF zU8S35bnG#c`BpuXs>MW+FN$JegzI8Dwch8K{1deZikI5aaQP*7d;;W#a8Y2uJ!8WTBOK>vJVH%ow&wl1#%zUZcu6Vhjt`$xJVL;9?9XST z&q`gFo7*ZeEo{6V6ZdmIps|;@Pa`E&iautUy~q1y7L*#x*U&O^Dxp-`{%6D0mzT0M zLoi~K2}1No)W_?1D*~kI6QoNZjZ`OJr8I}-9x!5Q+(zVi!5``&{*f-!Z|WiV8tT|o zf5k8I!@`q?m6xE9=z~e<#JV1y#9W52~j9`cqH^3r+q7@)OH_~R}mbCj>GAM(C zg8LW_SfAdmbb7-vPU^S#uzE-`Ye>YfcR&#SlCSIUD@ipQUpH3X4J~$^O0IkQS_n#~ zYsEz@W@#!vV^HS$sV>@&NLJZ@)-oE5Ez>TnI6)IQAj1Nn<}I|eFbHbMS8zI_b7ZUg zstJLgv1t=zA7I7DpQA*c+Hlv|n-=_V1aSi$kd5Er_B)b4vA6nzCd-ypq3)<^7Y2!cM zz^VSIpJq3fk&{su1v5kt~Rwx z20fc7_nsV!15gtPh4&9!TO54fb-$EqFyXos155d}_ZIz{G*wo65*;8_n&O#&!yv@Z z#GACAjjnMz(pr|o@iSI{g2`;AU@XEYwyWysN1AA7O|+LLIzSWsd^%nZe+{ac1-+LA zZSxvk{+%RVfE6#oiWg(WOR2qU;+tY3K$vg0?@~s&)>&Zv1GMxYr)zDeR~9!i6&_Ka ztB++bz!3ZroEfOAu5}w!)Lc?@knqUXLWSDLqOw8W$G>@v4nuMlgz%&B5$S^^q$0RzGM`&BM~ z804=LsL%w75LO>;>35_c22g2D3aUIwX&qZf;{{PO+sh@$0$EWjl#*;2-Nuf|TTD)f%uwn}M*6324xp(K?Yi z{=*%MoIT=z*z{rC?JeuxP&<<+CI{qxT76RJi&%rf6_OZs3zfBPZV;-WetD3=rLJDYF*ZN#Ve6;jyXSdW%>-V4gME$<%#NDedqXDjG zf^_Tzv1QQPR|iSSk1w=_UYIJ)`W#l7d5^ zCb??E^gZ|1&G%<(7=`Y!Fu3{IjS4Bqe7N|ayF=9^fpLQ&nvn=+zeFkYZBiS2gW{__ zyEeLES>yfqOz(a|ri)u0wZ_eFe=eeDu)*bnQdM2#o#tj8b`r)jNy)pjd`_A;T&{_v z93fS%Hgtw#^Wd4Rv^%tXD6MFr7StkImW!9&7m_sm&Q8fmJo!M~A88EOH?C=;zhR-! z2I2Mr&bM)WDGM?rUs1^(;l$e|pQ_|{b6}e4Zse8bV@_&DgHlTIrKOq=RE0EZ zK?NCxzPSHhg@%ojj>Pp{EI&X#zc^kqI17RyBjFiB{YOxB_U%A zvN=}izr+z|GkNlg!VY6W1{!-=!+474bhupY$9HmPQKPrQsY2cAAwhEfW)ql~%UW-i zF>ib4Q0LX#EAIFkL)~`oX3-P{mm9LPZ*O020RKhMK7HMLigk1>c33#!bj^78i`8GU z0@Ka8GQ9Rb17bb}c6|(N99g8aKSFitqFcUFvo0`*W)e*F4B8$xVRk4;0q#Fxc5nrM zU`2<^-a^SCW$^mKo>SKrEUJC6c#oM(+<0UR^d0)HrP%0YMS&9nilT-w2|pEMxLXl1 zlbG5oOOG1HXpcI_k`}+mI^4fz8!eJ7X=(YMD(mYqoiGkl)!EICIvJIg#!ypI}&1gdhfL<{!tSAcKmoG=I9<+!FagWlV} zF(u18-JB|BJ{Nsr5-$m@E((%$X+-5MjznNe97pX+7GpdYzxn5k6DuQH{u-}hE{M-Y zt+zYJ?&k^;p@=>)e*D{Cm4qVOCP9{blVny-CCR(%O=OssUN*qcPn?aKeqB2L?#?ya zh3`VXj@VniKG^Ff5TcK-?P40M`1L?>n9jPAiNd<^VrT5tlECTk65m$#63=PMBXT#a z<>QyFI2*&QOF4O)s*vQ>B99krKHv@+%%YI0Uah+#?h!bUAPMK!F+!+C7$XdUm@3bt zQk9aTDq-`!-jr_g&xp^2I2V1icyiA0Ii8#i4M@u3iS?|tCs z(D`s>N#IxXet|(@Pk~?Wh1617%2}>n&A19*tGf zi;eD1e=$k%gY-s z;QCVf!8Z^7ygMWzagNu87wfkE<%1I9-n}!B%P)QA;uMoBF%^+YaoSFhSfs3Ri+WM5 zm{USQRF8Cf>lcBvsLHbzf-sTX_<{Z87#taGW|^j_W|<~uIh?p)?CUx062dJ|*;=FT z+7>YAI24;^EB0vl(`|9LWovcufaUX3<~`_^EQhVJI(u+;=JZ_Fh+fF(=Y~lw#Bled z4&v;P{5Y-T;dG?!Pr zZFza5(iT3QT~ski{0Oq6!+Q=EVmbSB!y!I{TB*`L%@bEpvUMwL7Sb!CuwQkM!JgNZ zRVTtRIu!Fb9UqH$&@YcJ$BVVrB#S>9{u$s&_x)U;kmjqpG#=U38pijbrM7r|wg$|l z)2g3$uXPlb8l_g=Y&+uA{HWpoRClFOO=Vk}dOo!jFjgU=Af&LAh#-TMVGb4)P6z=9 z1|dX63Ykq9!jOO^lZp_ONsCE90Rh7#2?0q;L;{34K#&9?#xNKXhCo6HLtm_3{rXR@ z?mxYH^^dHqb?>>!KIiOx&fRx^-*NYdh`nbpY{X*Ty>6f0XWYyj`z;H7t#UN)Qurwi>hK37!Te zVowQY@|HWO*_r7<>DiEVH_zPACf%Gh)ff|)~x5%MqQAqXM;^K9t5gry=!xMA!i4RZLv|`HTI{~ z9=)@3pQqK;o12O;QA>p0+y@~>m^cj$wnMYs3(TV>;p6f1weW3~Xqe)2%!@Y#;a70R zjM&laC}TUB>l|8|y8Y^Sqd|nm^g=&3wBc*4QNiav!>WR>E1`EP`6f(50@s~J{Cg`6 z)8(5C8?OBoZ;Ix$MxMMpx8EV^;_p{1wT*mWkUAkkQ_@qBNyb-ZeWh7F+1`sij@M)9 z!7JJNy#zBoeM+pB(&8__;A&+TwDt)PDm*y5!-fmsXVBgTSBMz#jO_8Te{8^x$vuJr z=qj<(XM-l23I-$S^0NB4Jhc3+HwLk!7dA<-8#3OAVS0B0JMA1Fk*!Vb_@}jEoa#SM z{nJlwa9+}W{rNzjF~(rN`%l-rT~VrwzkC{lQGPcVY5s{cUVm8hgPCH8@tz$-@VGSJ z12c7Y@wGYATWE$2S&NeP#49c~pI77UybSGByqfa`!Z4=y3davyQGF`bzK#bje#>n` zFzs_wf-W|%uW4Tt(`GK_5%Miu3r0bfSVW#K&mYw{^4rsH*{hKO09%eo^v!ie&VzIt zeemNXq~&ouCH&%kD#{~2g8$nj+;$qVXI;x-J#X?`Zi@|thGdtB8KSKe{bcL~YyIiv z9J6K2^W|j6CHyjf?%52-dJw-LfQ{e~bR{?Hs#P_Cog{Tcz3S1txh?LCEiVxzmW6Y>DcCk-7c;n1rR`q*1_sjC)3&khd-6 z?c(#)FvH%k#+Ar4jcl7V4T~P;y``?TdrQ~%(vO~t-AFt$l>H@OhzeRyJTq@NFt4V% zYB(U-LDF1QOzA)c-@e%U$X}wUsLpw2{L2nn!;bfboW2N6nPSR9fAH;T)XHQ-W7i53 zRYl|Dhs=#=cRH11Mwrc|pywL=(s7tJeFvVJdRe^yENI9*2wCMTCGDVbUI96NO`(pc zX>Cp82mo<$Mrk@Ln*n63j7B}@g`?J##*@{wcr9yc zytS4Bx|9}_C9(_341uR+8o@bwK7MWVnJGxeD;|UQ<)IsTF_VnG>0N)Q0_U3AOa?xp zj6-gs+(T|n9$&2@Z1==^=p=m|e{7>R-1)A%p#6_PzW1j1L~StB;Uft{ogIrUs|=e@ zi+$_(@|8{8I(6;-jl5jqEy>V>W=Bv<$u&;6pU!4s|05*$dlUh@Bx`ri#N6# zCc$;=sLkKW(sBDm(K9t(DZ{uEUk>e*Kwbm5ljWJIUq^8^Hq_k7#&>D!&F`Q<@zgWu zY2&Xk9`%|=bM~0vF5M}YI%r3CopHxzH<`G`=^fK0b+Zn8Rgl_|lfjv+so=-v8smq# zJ4igjSyKB8TX*lyPegk)cH2RCQ2H}?VEV^67MAmg*ozBF>WYp@x&ji?@A1rekCn}N z{n_E2McJ56Zk6x}#FKRt-b}Ic8y`8*OCh^^y4Ih~0*Pr4hoZk^o{IM7jW%DBy@N%H z-s2X+u2WP;LM2pos z5AEa_enYXAuWjLfc4`vu*9QraZ#4-XFEP=2-7Ch@fJv7xYn7W>b&{CNJ>#1QQ}ekU zrk8QWxwsV-w6KQLPCiOa7r|39Lr%qJhV-UnhtNyfKPoeLUG%yyOBE9O46}kan1gSB zbv2nc*aW9{)c1Bi0A8deYR+azwkICc#&iJuy zV}g@?OtpY-wC@Z6dpvu4g`{3e@LoW#gJ;v`_TRe`D_hP;_8P*c!K2X!2fPq}t=;W7&rs5X!lz3NCMeih7 z4~GN`@S>Y@!yLEGnf${|yNmGr`3L)rpR?1CTcpi)I22$X<#nCc2)!Wt3wO8%(pLuY z=WpYrXIL5@L{c+yG(a5G!>F6#NJlKZVFGdlsfM%~LE{9;-9(xNkNLk(sy&Qe)yJCpv zU`PI~MtzEa2vLbX93s;$p9{!8Qs<=#iwQR@m%X4_u_42tMm%wo0`W$~tUR#umA!Zb z!XR4$4zX$!BHOe$+3IcWGAijyC*k-%AtlBjONL znwoQ|PasL@w$1~cXHQk%EC3M?aa`?ovo_{Y&d`|G1uaX4f*h>G$S)u>U0~;0*t0WG zNeJf4=2vvGf!3=L5uTWj=dZKoSowuLNd}zS*_u0Gf9jXoF7!{WTBiq<(kuy^s}5Rf zcP5kuFo#Qj9Smo6yb5h(wdJ?Ihaj$Sj+`GPvbe{;p8wD)D1`;BPY!G_VD|q|V@{~_ z%|}S;QMLkqSAyU|poy22E{CgH--Ff`OFtFk{OJz&fUzEiALpPh@BRP-KWXT_0elr@ z6&z_CYfOO(Q-Hrt>`gJq(ZEm|o``dwKg7YNHxdi2|18w(`_vXksL7XE_OLsionC+CXiXLTdbNsuO9P*35*0yM~<~huVd*C zM_v3YHnkKrq2Gmmir<-Q`K&Qc%TJE~cC}&Hahvh0+4F-KbRztCpbs2644;6C4;MmZxp>KEV-`0+wVJ>t~}N>w<5`LK-F0fOYpR*+7gZ%8S@O?}Sn}t0NQScd3C9tT5Knf&r3K*08aQ z5q|#Qw(^XrxRjkT7rJp!XW>5J+GSU_f&`}1o&+=SmBHGg$p@;z=TF~1@w0g$IugCS z&>b9Sztij5KCkH4;1-DQk0a?0n#2=d&zlM#u=D@w>_~+d>Sdu3&YDcO?;9->RAu6O z<{8$6y1f@ru-|G>ChVzC*4jhT=UzwFA_&})eW6WuIM{(`&!z2mFC7Pt?XmO+k28#;WxD_;lcw624lQ)LmXn;qLMwfS7ig0keM^X_n`iRjux zgfg7smXqv@nw>&>B!^KHU9@|Xj`1{c78;KGSY>drcNBeQ_gw={lx_4II<|Au z^v9eLv4w3n37XEb!vzbM0$!Sdi`wolyPFm$b*`^o$2pcQgU)L9CKYBWpE@&Zayu5_ z(GeAPhxHf5b(0=p;e+V@K>gtdKVXWolGU>dJuixWz*H9Jr*)1QH^y+nQ+^}Jt_X3) z9}dWzXsmrAtXk@&0uW5>;n5!0o=u>7OvS1Cu`{eqffY@lKbDBrUY70+yHSoS0UptX z!}g=s$+_Hc6tZXPyRH6|p`I@-pqo9lCYB4?y}N+uM7uc;y53hc-PHd|?1g?> zY7JHP>r+X$H2t!A>j_BUjtGA;l6N;DKYEQuB_&41=K0Jbt zF4P`2OR5029kKn&0@}(YLxy$aQBDK)Jm>GC!uE6TnSyyH;Mt;KL@DC(zE#&R7nq3Y zn%lC2n1DcqEPh!3)vuy=s}QV1Mjd=>pSDFHv!4*Cj#D-SAg+Y2)i50&t5(g{tfzSg zoHF&*t_LZvw(9>9J@BX;3(uNgn}BeS^abt?F1<=&`NQWayY=Zzq6gM%=rtCpyS(co z>Cg#`8=0t+V2#H$_04CVsOaPC#-npVlyE7bBCRtF7Vit*_tjb(37DBtRfQ&3pU47E zcQQAnsZG|}OZAU~4?64d>she+a-xn2W)4x2u`jyX*JA3zYbq!*RaCgadOKVBj z>TT*g_nI__c4zXtyZwM}v0G5Wb z#iFf~NRfHRrm}~tgJI2LK_W}fU7EwGdG2zK4nXzufM)Y^Mw7l?)3m%*KB##F+_854 zmn-+{V?wsYB|g5uPr6XT9acf>K9!aza|tu&tY;l>T$A*xv=wW>4_gA_na&(F#AvDS zN4Q+(7D@c)=PGEY@93C?Y5!u)lxbdnPR~5iYy%OVJz)I$0Im6{CiJ-6q^d&t zPt3sOF~p9$XaHmWmjMs`_|TrB@KUF#dU=da(_IoT(T?dQ;=gUvV9W$LRxgi+>bT<< zPxK-Z-3fPc%3ytg)ljou#~U9?l5A4(O|$bB6S!eOJM&7xjTNld1z*nSf+CzDYE>y) zGBk%?10;Y6(^RNNWr}?Wtwfz)woo40NEG!;LmS;2$IED$!R8kuG}MZnfE~n!MGk%Y%ZCq1ezTi+vjCI~iN&Sz`B zuIf&!U~C|dmkXAgj99Y+F=4X)RV43ZNlW0x6_e4o6Qc7Uf61dwGGdd81T8%I>y)rn z4GihM!l|AX(TF%nX2awWdM6pYrk1JFhod{e?$oOh=7}NWzoo=^5Y^=XWLM`In?ikE zEplj%{mS7k2>ZqOH+FW&YU0Em`ovBUw z>}k@Z!kW07Au@e08NEfmTN^ zag&a&+;*2(EIrtLmqNp_4%EkLS>We9oF{0-tM8dKV9aS*#XNDpql{b3Dx=qgoG1v~ zDQB&Fw{{_+^_PsA*RH`(HN65^wmlQ&jW z?y;)dm33-xdox{ZczShqsxZrY z%DG|IgYLun?(Sas=K%vtPB(QV4grI<*>?J~?BuS7z5_897FCN|BiXzc)C(S;EQ>4_ zcmLy^W6|hL)Do)cPPc7@8cxQmP4>pH0%Mnu%Jm#*FpTAL+jsR?P3E}ep1K7!VYD~* zeX31FuC$G^8%!!gm9u@JLU!Q&B0;F^^E6RvowH@DpBiUP%L0BSHr{qQNkG-{1EVKc zlm>6w|%>4S%MWMF_lhL z1r^K{nPMjnei$XIyuOf~Lti7zL-*7x?oaa|a)_2rvONBVa{5M$@1L+sm4)VO<~5zG z1IByCd?_2l+|SV#7K9e=N9Fu1{s;rwh(HzfM02>5z&Gp3Kj!aJounlt3dgC^u{ zId8*JuL5yJ#8Ypp8Wl)Lz)7EGHNo`)mBvAc>>e(#LS*}}UWoXitQgi=j@Lw3f_|kT zHi#;-F0_{~FxRr^&YIHGvB*bId{;vvW)l;b6UFrTKoT&X;lBZyv0A-g!kfP)JdpYo zWDfB#3tlk(ES2~E35 zA*5b`d(I^B!PhzuB8Uul!5*#7Hpi6%4ZwmsL7Z5aU9_*G6}45=h9%I|lNyl})J(L6 zpIV?oqc>O2PeUR-t;5{t3tx?R+EiI)I0s11ZhjEpYq^2mEVDt_*+BEV-_)ay-cpG| zsR)7RGWP-K;N2g;!POoq07!}p--uEMC%<7)fmiL^9$rg|T}k>>y7mpIC?|LHZ<^5m z;H^CWm$w>DgM01%LkiI;fp9NrL^RbK?eg2d4*qUhMFhe!TS)=WQK+BUoR*_ixmZ&qM$K literal 0 HcmV?d00001 From 9b1b6838b4e4479cef21b19634832079c13e42e6 Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Tue, 18 Sep 2018 17:02:32 -0400 Subject: [PATCH 15/15] fix: issue with readme --- README.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0fa3bfc..3d144b8 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,29 @@ I suffered similar performance issues with work efficient scans in the compact a ![](img/compactPO2.PNG) -![](img/compactNPO2.PNG)**************** +![](img/compactNPO2.PNG) + +| Elements in Array | CPU Compact without scan (Power of 2) | CPU Compact without scan (Non Power of 2) | CPU Compact with Scan | Work Efficient Compact (Power of 2) | Work Efficient Compact (Non Power of 2) | +| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | +| 2^8 | 0.000969 | 0.000969 | 0.00097 | 0.06144 | 0.072704 | +| 2^9 | 0.020849 | 0.001455 | 0.002909 | 0.291872 | 0.274432 | +| 2^10 | 0.003394 | 0.002424 | 0.004849 | 0.296928 | 0.296928 | +| 2^11 | 0.007758 | 0.005819 | 0.010182 | 0.330784 | 0.338912 | +| 2^12 | 0.011636 | 0.016 | 0.050909 | 0.234464 | 0.238592 | +| 2^13 | 0.054304 | 0.020848 | 0.055272 | 0.442304 | 0.413696 | +| 2^14 | 0.077091 | 0.067878 | 0.092121 | 0.557024 | 0.5816 | +| 2^15 | 0.123152 | 0.112 | 0.157576 | 0.785088 | 0.767744 | +| 2^16 | 0.246788 | 0.269576 | 0.343758 | 1.21734 | 1.23866 | +| 2^17 | 0.390788 | 0.402424 | 0.555637 | 2.16781 | 2.13808 | +| 2^18 | 1.06182 | 0.744727 | 1.53648 | 4.00554 | 4.0591 | +| 2^19 | 1.488 | 1.48994 | 2.63418 | 7.96368 | 7.97901 | +| 2^20 | 2.69624 | 2.80679 | 4.72727 | 16.1515 | 16.1321 | + + +### Output Log + +``` +**************** ** SCAN TESTS ** **************** [ 16 29 39 25 25 14 11 20 0 34 28 11 33 ... 4 0 ] @@ -117,26 +139,4 @@ I suffered similar performance issues with work efficient scans in the compact a elapsed time: 2.10413ms (CUDA Measured) passed Press any key to continue . . . - -| Elements in Array | CPU Compact without scan (Power of 2) | CPU Compact without scan (Non Power of 2) | CPU Compact with Scan | Work Efficient Compact (Power of 2) | Work Efficient Compact (Non Power of 2) | -| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | -| 2^8 | 0.000969 | 0.000969 | 0.00097 | 0.06144 | 0.072704 | -| 2^9 | 0.020849 | 0.001455 | 0.002909 | 0.291872 | 0.274432 | -| 2^10 | 0.003394 | 0.002424 | 0.004849 | 0.296928 | 0.296928 | -| 2^11 | 0.007758 | 0.005819 | 0.010182 | 0.330784 | 0.338912 | -| 2^12 | 0.011636 | 0.016 | 0.050909 | 0.234464 | 0.238592 | -| 2^13 | 0.054304 | 0.020848 | 0.055272 | 0.442304 | 0.413696 | -| 2^14 | 0.077091 | 0.067878 | 0.092121 | 0.557024 | 0.5816 | -| 2^15 | 0.123152 | 0.112 | 0.157576 | 0.785088 | 0.767744 | -| 2^16 | 0.246788 | 0.269576 | 0.343758 | 1.21734 | 1.23866 | -| 2^17 | 0.390788 | 0.402424 | 0.555637 | 2.16781 | 2.13808 | -| 2^18 | 1.06182 | 0.744727 | 1.53648 | 4.00554 | 4.0591 | -| 2^19 | 1.488 | 1.48994 | 2.63418 | 7.96368 | 7.97901 | -| 2^20 | 2.69624 | 2.80679 | 4.72727 | 16.1515 | 16.1321 | - - -### Output Log - -``` - ``` \ No newline at end of file