From 51bf871b32d364051c4f23509cc445c20c2b71ce Mon Sep 17 00:00:00 2001 From: EvsChen Date: Fri, 18 Sep 2020 16:53:03 -0400 Subject: [PATCH 1/8] Finish basic algorithms --- stream_compaction/common.cu | 10 ++++- stream_compaction/common.h | 2 + stream_compaction/cpu.cu | 32 ++++++++++++--- stream_compaction/efficient.cu | 75 ++++++++++++++++++++++++++++++---- stream_compaction/naive.cu | 27 +++++++++++- stream_compaction/thrust.cu | 4 +- 6 files changed, 130 insertions(+), 20 deletions(-) diff --git a/stream_compaction/common.cu b/stream_compaction/common.cu index 2ed6d63..853d6cb 100644 --- a/stream_compaction/common.cu +++ b/stream_compaction/common.cu @@ -23,7 +23,9 @@ namespace StreamCompaction { * which map to 0 will be removed, and elements which map to 1 will be kept. */ __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { - // TODO + int idx = threadIdx.x + (blockDim.x * blockIdx.x); + if (idx >= n) return; + bools[idx] = idata[idx] == 0 ? 0 : 1; } /** @@ -32,7 +34,11 @@ namespace StreamCompaction { */ __global__ void kernScatter(int n, int *odata, const int *idata, const int *bools, const int *indices) { - // TODO + int idx = threadIdx.x + (blockDim.x * blockIdx.x); + if (idx >= n) return; + if (bools[idx]) { + odata[indices[idx]] = idata[idx]; + } } } diff --git a/stream_compaction/common.h b/stream_compaction/common.h index d2c1fed..c4ca0de 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -13,6 +13,8 @@ #define FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #define checkCUDAError(msg) checkCUDAErrorFn(msg, FILENAME, __LINE__) +#define blockSize 128 + /** * Check for CUDA errors; print and exit if there was a problem. */ diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 719fa11..7e4f9c2 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -19,7 +19,10 @@ namespace StreamCompaction { */ void scan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + odata[0] = 0; + for (int i = 1; i < n; i++) { + odata[i] = odata[i] + idata[n - 1]; + } timer().endCpuTimer(); } @@ -30,9 +33,14 @@ namespace StreamCompaction { */ int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + int j = 0; + for (int i = 0; i < n; i++) { + if (idata[i] != 0) { + odata[j++] = idata[i]; + } + } timer().endCpuTimer(); - return -1; + return j; } /** @@ -41,10 +49,24 @@ namespace StreamCompaction { * @returns the number of elements remaining after compaction. */ int compactWithScan(int n, int *odata, const int *idata) { + int *temp = new int[n], + *tempSum = new int[n]; timer().startCpuTimer(); - // TODO + for (int i = 0; i < n; i++) { + temp[i] = idata[i] == 0 ? 0 : 1; + } + scan(n, tempSum, temp); + int cnt = 0; + for (int i = 0; i < n; i++) { + if (temp[i] == 1) { + odata[tempSum[i]] = idata[i]; + cnt++; + } + } timer().endCpuTimer(); - return -1; + delete[] temp; + delete[] tempSum; + return cnt; } } } diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 2db346e..ad4893d 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -12,13 +12,54 @@ namespace StreamCompaction { return timer; } + __global__ void upSweep(int *data, int d) { + int idx = threadIdx.x + (blockIdx.x * blockDim.x); + int interval = 2 << d; + int mapped = interval * idx + interval - 1; + data[mapped] += data[mapped - (interval >> 1)]; + } + + __global__ void downSweep(int *data, int d) { + int idx = threadIdx.x + (blockIdx.x * blockDim.x); + int interval = 2 << d; + int node = interval * idx + interval - 1; + int left = node / 2; + int temp = data[left]; + data[left] = data[node]; + data[node] += temp; + } + /** * 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(); + void scan(int n, int *dev_odata, const int *dev_idata) { + int iterations = ilog2ceil(n); + int nextN = 2 << iterations; + int *dev_idata_temp; + cudaMalloc((void **) &dev_idata_temp, nextN * sizeof(int)); + cudaMemset(dev_idata_temp, 0, nextN *sizeof(int)); + cudaMemcpy(dev_idata_temp, dev_idata, sizeof(int) * n, cudaMemcpyDeviceToDevice); + timer().startGpuTimer(); + + // Up-sweep + for (int d = 1; d <= iterations; d++) { + int numThreads = 2 << (iterations - d); + dim3 blocks((numThreads + blockSize - 1) / blockSize); + upSweep<<>>(dev_idata_temp, d); + } + + // Down-sweep + // Set the "root" to 0 + cudaMemset(dev_idata + n - 1, 0, sizeof(int)); + for (int d = iterations; d >= 1; d--) { + int numThreads = 2 << (iterations - d); + dim3 blocks((numThreads + blockSize - 1) / blockSize); + downSweep<<>>(dev_idata_temp, d); + } + + timer().endGpuTimer(); + cudaMemcpy(dev_odata, dev_idata_temp, sizeof(int) * n, cudaMemcpyDeviceToDevice); + cudaFree(dev_idata_temp); } /** @@ -31,10 +72,28 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - return -1; + int *bools, *indices, dev_idata, dev_odata; + cudaMalloc((void**) &bools, sizeof(int) * n); + cudaMalloc((void**) &indices, sizeof(int) * n); + cudaMalloc((void**) &dev_idata, sizeof(int) * n); + cudaMalloc((void**) &dev_odata, sizeof(int) * n); + cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + + timer().startGpuTimer(); + + dim3 blocks((n + blockSize - 1) / blockSize); + Common::kernMapToBoolean<<>>(n, bools, dev_idata); + scan(n, indices, bools); + Common::kernScatter<<>>(n, dev_odata, dev_idata, bools, indices); + + timer().endGpuTimer(); + + cudaMemcpy(odata, dev_odata, sizeof(int) * n, cudaMemcpyDeviceToHost); + cudaFree(bools); + cudaFree(indices); + cudaFree(dev_idata); + cudaFree(dev_odata); + return -1; } } } diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 4308876..b765740 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -11,15 +11,38 @@ namespace StreamCompaction { static PerformanceTimer timer; return timer; } - // TODO: __global__ + __global__ void addPrev(int n, int *idata, int *odata, int d) { + int idx = threadIdx.x + (blockIdx.x * blockDim.x); + int base = 2 << (d - 1); + if (base + idx >= n) return; + odata[base + idx] = idata[base + idx] + idata[idx]; + } /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + int *dev_idata, *dev_odata; + cudaMalloc((void **) &dev_idata, n * sizeof(int)); + cudaMalloc((void **) &dev_odata, n * sizeof(int)); + cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + cudaMemcpy(dev_odata, odata, sizeof(int) * n, cudaMemcpyHostToDevice); + timer().startGpuTimer(); - // TODO + int iterations = ilog2ceil(n); + + for (int d = 1; d <= iterations; d++) { + int base = 2 << (d - 1); + int numThreads = n - base; + dim3 blocks((numThreads + blockSize - 1) / blockSize); + addPrev<<>>(n, dev_idata, dev_odata, d); + std::swap(dev_idata, dev_odata); + } + timer().endGpuTimer(); + cudaMemcpy(odata, (iterations % 2 == 0) ? dev_odata : dev_idata, sizeof(int) * n, cudaMemcpyDeviceToHost); + cudaFree(dev_idata); + cudaFree(dev_odata); } } } diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index 1def45e..741b092 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -19,9 +19,7 @@ namespace StreamCompaction { */ 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()); + thrust::exclusive_scan(idata, idata + n, odata); timer().endGpuTimer(); } } From ebfd7c3f7da53d3cd2b5a96de89ee22eef4d3bd0 Mon Sep 17 00:00:00 2001 From: EvsChen Date: Sat, 19 Sep 2020 03:35:49 +0000 Subject: [PATCH 2/8] Finish basic algorithm; has error when n >= 1 << 13 --- src/main.cpp | 2 +- stream_compaction/cpu.cu | 7 +++-- stream_compaction/efficient.cu | 53 ++++++++++++++++++++++++---------- stream_compaction/efficient.h | 2 +- stream_compaction/naive.cu | 27 ++++++++++------- 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 896ac2b..ff73805 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 8; // feel free to change the size of array +const int SIZE = 1 << 12; // feel free to change the size of array const int NPOT = SIZE - 3; // Non-Power-Of-Two int *a = new int[SIZE]; int *b = new int[SIZE]; diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 7e4f9c2..2172a8a 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -21,7 +21,7 @@ namespace StreamCompaction { timer().startCpuTimer(); odata[0] = 0; for (int i = 1; i < n; i++) { - odata[i] = odata[i] + idata[n - 1]; + odata[i] = odata[i - 1] + idata[i - 1]; } timer().endCpuTimer(); } @@ -55,7 +55,10 @@ namespace StreamCompaction { for (int i = 0; i < n; i++) { temp[i] = idata[i] == 0 ? 0 : 1; } - scan(n, tempSum, temp); + tempSum[0] = 0; + for (int i = 1; i < n; i++) { + tempSum[i] = tempSum[i - 1] + temp[i - 1]; + } int cnt = 0; for (int i = 0; i < n; i++) { if (temp[i] == 1) { diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index ad4893d..c724364 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -14,16 +14,16 @@ namespace StreamCompaction { __global__ void upSweep(int *data, int d) { int idx = threadIdx.x + (blockIdx.x * blockDim.x); - int interval = 2 << d; + int interval = 1 << d; int mapped = interval * idx + interval - 1; data[mapped] += data[mapped - (interval >> 1)]; } __global__ void downSweep(int *data, int d) { int idx = threadIdx.x + (blockIdx.x * blockDim.x); - int interval = 2 << d; + int interval = 1 << d; int node = interval * idx + interval - 1; - int left = node / 2; + int left = node - (interval >> 1); int temp = data[left]; data[left] = data[node]; data[node] += temp; @@ -32,33 +32,50 @@ namespace StreamCompaction { /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ - void scan(int n, int *dev_odata, const int *dev_idata) { + void scan(int n, int *dev_odata, const int *dev_idata, bool callFromMain) { int iterations = ilog2ceil(n); - int nextN = 2 << iterations; + int nextN = 1 << iterations; int *dev_idata_temp; cudaMalloc((void **) &dev_idata_temp, nextN * sizeof(int)); + checkCUDAError("cudaMalloc dev_idata_temp failed"); cudaMemset(dev_idata_temp, 0, nextN *sizeof(int)); - cudaMemcpy(dev_idata_temp, dev_idata, sizeof(int) * n, cudaMemcpyDeviceToDevice); - timer().startGpuTimer(); + checkCUDAError("cudaMemset dev_idata_temp failed"); + if (callFromMain) { + cudaMemcpy(dev_idata_temp, dev_idata, sizeof(int) * n, cudaMemcpyHostToDevice); + timer().startGpuTimer(); + } + else { + cudaMemcpy(dev_idata_temp, dev_idata, sizeof(int) * n, cudaMemcpyDeviceToDevice); + } + checkCUDAError("cudaMemcpy dev_idata_temp failed"); // Up-sweep for (int d = 1; d <= iterations; d++) { - int numThreads = 2 << (iterations - d); + int numThreads = 1 << (iterations - d); dim3 blocks((numThreads + blockSize - 1) / blockSize); upSweep<<>>(dev_idata_temp, d); + checkCUDAError("upSweep failed"); } // Down-sweep // Set the "root" to 0 - cudaMemset(dev_idata + n - 1, 0, sizeof(int)); + cudaMemset(&dev_idata_temp[nextN - 1], 0, sizeof(int)); for (int d = iterations; d >= 1; d--) { - int numThreads = 2 << (iterations - d); + int numThreads = 1 << (iterations - d); dim3 blocks((numThreads + blockSize - 1) / blockSize); downSweep<<>>(dev_idata_temp, d); + checkCUDAError("downSweep failed"); } - timer().endGpuTimer(); - cudaMemcpy(dev_odata, dev_idata_temp, sizeof(int) * n, cudaMemcpyDeviceToDevice); + if (callFromMain) { + timer().endGpuTimer(); + cudaMemcpy(dev_odata, dev_idata_temp, sizeof(int) * n, cudaMemcpyDeviceToHost); + } + else { + cudaMemcpy(dev_odata, dev_idata_temp, sizeof(int) * n, cudaMemcpyDeviceToDevice); + } + checkCUDAError("cudaMemcpy dev_odata failed"); + cudaFree(dev_idata_temp); } @@ -72,7 +89,7 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { - int *bools, *indices, dev_idata, dev_odata; + int *bools, *indices, *dev_idata, *dev_odata; cudaMalloc((void**) &bools, sizeof(int) * n); cudaMalloc((void**) &indices, sizeof(int) * n); cudaMalloc((void**) &dev_idata, sizeof(int) * n); @@ -83,17 +100,21 @@ namespace StreamCompaction { dim3 blocks((n + blockSize - 1) / blockSize); Common::kernMapToBoolean<<>>(n, bools, dev_idata); - scan(n, indices, bools); + scan(n, indices, bools, false); Common::kernScatter<<>>(n, dev_odata, dev_idata, bools, indices); timer().endGpuTimer(); - + + int cnt, lastBool; cudaMemcpy(odata, dev_odata, sizeof(int) * n, cudaMemcpyDeviceToHost); + // Copy the count back + cudaMemcpy(&cnt, &indices[n - 1], sizeof(int), cudaMemcpyDeviceToHost); + cudaMemcpy(&lastBool, &bools[n - 1], sizeof(int), cudaMemcpyDeviceToHost); cudaFree(bools); cudaFree(indices); cudaFree(dev_idata); cudaFree(dev_odata); - return -1; + return lastBool ? cnt + 1 : cnt; } } } diff --git a/stream_compaction/efficient.h b/stream_compaction/efficient.h index 803cb4f..5ba93b0 100644 --- a/stream_compaction/efficient.h +++ b/stream_compaction/efficient.h @@ -6,7 +6,7 @@ namespace StreamCompaction { namespace Efficient { StreamCompaction::Common::PerformanceTimer& timer(); - void scan(int n, int *odata, const int *idata); + void scan(int n, int *odata, const int *idata, bool useTimer = true); int compact(int n, int *odata, const int *idata); } diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index b765740..9fd83e9 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -13,9 +13,9 @@ namespace StreamCompaction { } __global__ void addPrev(int n, int *idata, int *odata, int d) { int idx = threadIdx.x + (blockIdx.x * blockDim.x); - int base = 2 << (d - 1); - if (base + idx >= n) return; - odata[base + idx] = idata[base + idx] + idata[idx]; + if (idx >= n) return; + int base = 1 << (d - 1); + odata[idx] = idx >= base ? idata[idx - base] + idata[idx] : idata[idx]; } /** @@ -24,23 +24,30 @@ namespace StreamCompaction { void scan(int n, int *odata, const int *idata) { int *dev_idata, *dev_odata; cudaMalloc((void **) &dev_idata, n * sizeof(int)); + checkCUDAError("cudaMalloc dev_idata failed"); cudaMalloc((void **) &dev_odata, n * sizeof(int)); + checkCUDAError("cudaMalloc dev_odata failed"); cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); - cudaMemcpy(dev_odata, odata, sizeof(int) * n, cudaMemcpyHostToDevice); + checkCUDAError("cudaMemcpy dev_idata failed"); timer().startGpuTimer(); int iterations = ilog2ceil(n); + dim3 blocks((n + blockSize - 1) / blockSize); for (int d = 1; d <= iterations; d++) { - int base = 2 << (d - 1); - int numThreads = n - base; - dim3 blocks((numThreads + blockSize - 1) / blockSize); - addPrev<<>>(n, dev_idata, dev_odata, d); - std::swap(dev_idata, dev_odata); + if (d % 2 == 1) { + addPrev << > > (n, dev_idata, dev_odata, d); + } + else { + addPrev << > > (n, dev_odata, dev_idata, d); + } + checkCUDAError("addPrev failed"); } timer().endGpuTimer(); - cudaMemcpy(odata, (iterations % 2 == 0) ? dev_odata : dev_idata, sizeof(int) * n, cudaMemcpyDeviceToHost); + odata[0] = 0; + cudaMemcpy(odata + 1, (iterations % 2 == 1) ? dev_odata : dev_idata, sizeof(int) * (n - 1), cudaMemcpyDeviceToHost); + checkCUDAError("cudaMemcpy odata failed"); cudaFree(dev_idata); cudaFree(dev_odata); } From 47bcdb1e6356049c857d730bcdea35c33cf52bdd Mon Sep 17 00:00:00 2001 From: EvsChen Date: Tue, 22 Sep 2020 17:48:19 -0400 Subject: [PATCH 3/8] Add debugging code for work-efficient scan --- stream_compaction/efficient.cu | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index c724364..ea00ec2 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -37,9 +37,9 @@ namespace StreamCompaction { int nextN = 1 << iterations; int *dev_idata_temp; cudaMalloc((void **) &dev_idata_temp, nextN * sizeof(int)); - checkCUDAError("cudaMalloc dev_idata_temp failed"); + checkCUDAError("SCAN: cudaMalloc dev_idata_temp failed"); cudaMemset(dev_idata_temp, 0, nextN *sizeof(int)); - checkCUDAError("cudaMemset dev_idata_temp failed"); + checkCUDAError("SCAN: cudaMemset dev_idata_temp failed"); if (callFromMain) { cudaMemcpy(dev_idata_temp, dev_idata, sizeof(int) * n, cudaMemcpyHostToDevice); timer().startGpuTimer(); @@ -47,14 +47,14 @@ namespace StreamCompaction { else { cudaMemcpy(dev_idata_temp, dev_idata, sizeof(int) * n, cudaMemcpyDeviceToDevice); } - checkCUDAError("cudaMemcpy dev_idata_temp failed"); + checkCUDAError("SCAN: cudaMemcpy dev_idata_temp failed"); // Up-sweep for (int d = 1; d <= iterations; d++) { int numThreads = 1 << (iterations - d); dim3 blocks((numThreads + blockSize - 1) / blockSize); upSweep<<>>(dev_idata_temp, d); - checkCUDAError("upSweep failed"); + checkCUDAError("SCAN: upSweep failed"); } // Down-sweep @@ -64,7 +64,7 @@ namespace StreamCompaction { int numThreads = 1 << (iterations - d); dim3 blocks((numThreads + blockSize - 1) / blockSize); downSweep<<>>(dev_idata_temp, d); - checkCUDAError("downSweep failed"); + checkCUDAError("SCAN: downSweep failed"); } if (callFromMain) { @@ -74,7 +74,7 @@ namespace StreamCompaction { else { cudaMemcpy(dev_odata, dev_idata_temp, sizeof(int) * n, cudaMemcpyDeviceToDevice); } - checkCUDAError("cudaMemcpy dev_odata failed"); + checkCUDAError("SCAN: cudaMemcpy dev_odata failed"); cudaFree(dev_idata_temp); } @@ -91,25 +91,35 @@ namespace StreamCompaction { int compact(int n, int *odata, const int *idata) { int *bools, *indices, *dev_idata, *dev_odata; cudaMalloc((void**) &bools, sizeof(int) * n); + checkCUDAError("COMPACT: cudaMalloc bools failed"); cudaMalloc((void**) &indices, sizeof(int) * n); + checkCUDAError("COMPACT: cudaMalloc indices failed"); cudaMalloc((void**) &dev_idata, sizeof(int) * n); + checkCUDAError("COMPACT: cudaMalloc dev_idata failed"); cudaMalloc((void**) &dev_odata, sizeof(int) * n); + checkCUDAError("COMPACT: cudaMalloc dev_odata failed"); cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + checkCUDAError("COMPACT: cudaMalloc idata->dev_idata failed"); timer().startGpuTimer(); dim3 blocks((n + blockSize - 1) / blockSize); Common::kernMapToBoolean<<>>(n, bools, dev_idata); + checkCUDAError("COMPACT: kernMapToBoolean failed"); scan(n, indices, bools, false); Common::kernScatter<<>>(n, dev_odata, dev_idata, bools, indices); + checkCUDAError("COMPACT: kernScatter failed"); timer().endGpuTimer(); int cnt, lastBool; cudaMemcpy(odata, dev_odata, sizeof(int) * n, cudaMemcpyDeviceToHost); + checkCUDAError("COMPACT: cudaMemcpy dev_odata->odata failed"); // Copy the count back cudaMemcpy(&cnt, &indices[n - 1], sizeof(int), cudaMemcpyDeviceToHost); + checkCUDAError("COMPACT: cudaMemcpy indices->cnt failed"); cudaMemcpy(&lastBool, &bools[n - 1], sizeof(int), cudaMemcpyDeviceToHost); + checkCUDAError("COMPACT: cudaMemcpy bools->lastBool failed"); cudaFree(bools); cudaFree(indices); cudaFree(dev_idata); From 758a88e12d2baf646c25b4ffcff347c14ee44aa2 Mon Sep 17 00:00:00 2001 From: EvsChen Date: Wed, 23 Sep 2020 00:52:45 +0000 Subject: [PATCH 4/8] Finish basic version --- src/main.cpp | 2 +- stream_compaction/common.cu | 2 +- stream_compaction/common.h | 5 +++++ stream_compaction/efficient.cu | 10 ++++++---- stream_compaction/thrust.cu | 6 +++++- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ff73805..883d9fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 12; // feel free to change the size of array +const int SIZE = 1 << 18; // feel free to change the size of array const int NPOT = SIZE - 3; // Non-Power-Of-Two int *a = new int[SIZE]; int *b = new int[SIZE]; diff --git a/stream_compaction/common.cu b/stream_compaction/common.cu index 853d6cb..7a373c6 100644 --- a/stream_compaction/common.cu +++ b/stream_compaction/common.cu @@ -36,7 +36,7 @@ namespace StreamCompaction { const int *idata, const int *bools, const int *indices) { int idx = threadIdx.x + (blockDim.x * blockIdx.x); if (idx >= n) return; - if (bools[idx]) { + if (bools[idx] == 1) { odata[indices[idx]] = idata[idx]; } } diff --git a/stream_compaction/common.h b/stream_compaction/common.h index c4ca0de..aa7d58c 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -11,7 +11,12 @@ #include #define FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#ifdef _DEBUG #define checkCUDAError(msg) checkCUDAErrorFn(msg, FILENAME, __LINE__) +#else +#define checkCUDAError(msg) +#endif // _DEBUG + #define blockSize 128 diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index ea00ec2..4878221 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -12,15 +12,17 @@ namespace StreamCompaction { return timer; } - __global__ void upSweep(int *data, int d) { + __global__ void upSweep(int numThreads, int *data, int d) { int idx = threadIdx.x + (blockIdx.x * blockDim.x); + if (idx >= numThreads) return; int interval = 1 << d; int mapped = interval * idx + interval - 1; data[mapped] += data[mapped - (interval >> 1)]; } - __global__ void downSweep(int *data, int d) { + __global__ void downSweep(int numThreads, int *data, int d) { int idx = threadIdx.x + (blockIdx.x * blockDim.x); + if (idx >= numThreads) return; int interval = 1 << d; int node = interval * idx + interval - 1; int left = node - (interval >> 1); @@ -53,7 +55,7 @@ namespace StreamCompaction { for (int d = 1; d <= iterations; d++) { int numThreads = 1 << (iterations - d); dim3 blocks((numThreads + blockSize - 1) / blockSize); - upSweep<<>>(dev_idata_temp, d); + upSweep<<>>(numThreads, dev_idata_temp, d); checkCUDAError("SCAN: upSweep failed"); } @@ -63,7 +65,7 @@ namespace StreamCompaction { for (int d = iterations; d >= 1; d--) { int numThreads = 1 << (iterations - d); dim3 blocks((numThreads + blockSize - 1) / blockSize); - downSweep<<>>(dev_idata_temp, d); + downSweep<<>>(numThreads, dev_idata_temp, d); checkCUDAError("SCAN: downSweep failed"); } diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index 741b092..cb3bf9d 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -18,9 +18,13 @@ namespace StreamCompaction { * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + thrust::host_vector host_idata(idata, idata + n); + thrust::device_vector dev_idata = host_idata; + thrust::device_vector dev_odata(n); timer().startGpuTimer(); - thrust::exclusive_scan(idata, idata + n, odata); + thrust::exclusive_scan(dev_idata.begin(), dev_idata.end(), dev_odata.begin()); timer().endGpuTimer(); + thrust::copy(dev_odata.begin(), dev_odata.end(), odata); } } } From 334a53bd407e8e67adb1349f14520a8a5848b9c1 Mon Sep 17 00:00:00 2001 From: EvsChen Date: Tue, 22 Sep 2020 21:20:52 -0400 Subject: [PATCH 5/8] Add test code --- src/main.cpp | 157 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 43 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 883d9fb..0998ec5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,25 @@ int *a = new int[SIZE]; int *b = new int[SIZE]; int *c = new int[SIZE]; +const int repeatTime = 5; + +float getTimeAvg(float *src) { + float t = 0.f; + for (int i = 0; i < repeatTime; i++) { + t += src[i]; + } + return t / repeatTime; +} + +float printTime(float *src) { + std::cout << "Time record is ["; + std::cout.precision(5); + for (int i = 0; i < repeatTime; i++) { + std::cout << src[i] << ", "; + } + std::cout << "]" << std::endl; +} + int main(int argc, char* argv[]) { // Scan tests @@ -31,27 +50,41 @@ int main(int argc, char* argv[]) { a[SIZE - 1] = 0; printArray(SIZE, a, true); + float record[repeatTime]; + // 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)"); + for (int i = 0; i < 5; i++) { + zeroArray(SIZE, b); + StreamCompaction::CPU::scan(SIZE, b, a); + record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::CPU::scan(NPOT, c, a); + record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::Naive::scan(SIZE, c, a); + record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record) + printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); printCmpResult(SIZE, b, c); /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan @@ -59,39 +92,57 @@ int main(int argc, char* argv[]) { 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); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::Naive::scan(NPOT, c, a); + record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation() + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); 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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::Efficient::scan(SIZE, c, a); + record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::Efficient::scan(NPOT, c, a); + record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); 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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::Thrust::scan(SIZE, c, a); + record[i] = StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + StreamCompaction::Thrust::scan(NPOT, c, a); + record[i] = StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(NPOT, c, true); printCmpResult(NPOT, b, c); @@ -110,40 +161,60 @@ int main(int argc, char* argv[]) { // 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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, b); + count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a); + record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a); + record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + count = StreamCompaction::CPU::compactWithScan(SIZE, c, a); + record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + count = StreamCompaction::Efficient::compact(SIZE, c, a); + record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(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)"); + for (int i = 0; i < repeatTime; i++) { + zeroArray(SIZE, c); + count = StreamCompaction::Efficient::compact(NPOT, c, a); + record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); + } + printTime(record); + printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(count, c, true); printCmpLenResult(count, expectedNPOT, b, c); From b42f2ed51a19de1d9e441a1f4e9c8992d1d5fcdf Mon Sep 17 00:00:00 2001 From: EvsChen Date: Wed, 23 Sep 2020 02:22:04 +0000 Subject: [PATCH 6/8] Add repeat timing --- src/main.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0998ec5..9da4d39 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,13 +13,14 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 18; // feel free to change the size of array +const int SIZE = 1 << 10; // 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]; -const int repeatTime = 5; +const int repeatTime = 100; +float *record = new float[repeatTime]; float getTimeAvg(float *src) { float t = 0.f; @@ -29,11 +30,19 @@ float getTimeAvg(float *src) { return t / repeatTime; } -float printTime(float *src) { - std::cout << "Time record is ["; +void printTime(float *src) { + std::cout << " Time record is ["; std::cout.precision(5); for (int i = 0; i < repeatTime; i++) { - std::cout << src[i] << ", "; + if (repeatTime > 16 && i == 10) { + std::cout << "... "; + i = repeatTime - 2; + continue; + } + std::cout << src[i]; + if (i != repeatTime - 1) { + std::cout << ", "; + } } std::cout << "]" << std::endl; } @@ -49,20 +58,21 @@ int main(int argc, char* argv[]) { genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case a[SIZE - 1] = 0; printArray(SIZE, a, true); + float res[13]; - float record[repeatTime]; // 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. printDesc("cpu scan, power-of-two"); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < repeatTime; i++) { zeroArray(SIZE, b); StreamCompaction::CPU::scan(SIZE, b, a); record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); } printTime(record); - printElapsedTime(getTimeAvg(record), "(std::chrono Measured)"); + res[0] = getTimeAvg(record); + printElapsedTime(res[0], "(std::chrono Measured)"); printArray(SIZE, b, true); @@ -83,7 +93,7 @@ int main(int argc, char* argv[]) { StreamCompaction::Naive::scan(SIZE, c, a); record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(); } - printTime(record) + printTime(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); printCmpResult(SIZE, b, c); @@ -97,7 +107,7 @@ int main(int argc, char* argv[]) { for (int i = 0; i < repeatTime; i++) { zeroArray(SIZE, c); StreamCompaction::Naive::scan(NPOT, c, a); - record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation() + record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); From de87a42547c80c87a39c7d7a3cfdb6a17f8e32f2 Mon Sep 17 00:00:00 2001 From: EvsChen Date: Tue, 22 Sep 2020 22:25:16 -0400 Subject: [PATCH 7/8] Add print code --- src/main.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9da4d39..989423f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,7 +34,7 @@ void printTime(float *src) { std::cout << " Time record is ["; std::cout.precision(5); for (int i = 0; i < repeatTime; i++) { - if (repeatTime > 16 && i == 10) { + if (repeatTime > 16 && i == 13) { std::cout << "... "; i = repeatTime - 2; continue; @@ -83,6 +83,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); } printTime(record); + res[1] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(std::chrono Measured)"); printArray(NPOT, b, true); printCmpResult(NPOT, b, c); @@ -94,6 +95,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[2] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); printCmpResult(SIZE, b, c); @@ -110,6 +112,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[3] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); printCmpResult(NPOT, b, c); @@ -120,6 +123,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[4] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(SIZE, c, true); printCmpResult(SIZE, b, c); @@ -131,6 +135,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[5] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); printCmpResult(NPOT, b, c); @@ -141,6 +146,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[6] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(SIZE, c, true); printCmpResult(SIZE, b, c); @@ -152,6 +158,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[7] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(NPOT, c, true); printCmpResult(NPOT, b, c); @@ -178,6 +185,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); } printTime(record); + res[8] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(std::chrono Measured)"); expectedCount = count; printArray(count, b, true); @@ -190,6 +198,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); } printTime(record); + res[9] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(std::chrono Measured)"); expectedNPOT = count; printArray(count, c, true); @@ -202,6 +211,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(); } printTime(record); + res[10] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(std::chrono Measured)"); printArray(count, c, true); printCmpLenResult(count, expectedCount, b, c); @@ -213,6 +223,7 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[11] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(count, c, true); printCmpLenResult(count, expectedCount, b, c); @@ -224,10 +235,14 @@ int main(int argc, char* argv[]) { record[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(); } printTime(record); + res[12] = getTimeAvg(record); printElapsedTime(getTimeAvg(record), "(CUDA Measured)"); //printArray(count, c, true); printCmpLenResult(count, expectedNPOT, b, c); + std::cout << "Result for n = " << SIZE << " is :" << std::endl; + printTime(res); + system("pause"); // stop Win32 console from closing on exit delete[] a; delete[] b; From 71f91a5438a5890b8b4470c7f383e2241488235f Mon Sep 17 00:00:00 2001 From: EvsChen Date: Tue, 22 Sep 2020 23:41:00 -0400 Subject: [PATCH 8/8] Finish lab2 --- README.md | 122 ++++++++++++++++++++++++++++++++-- doc/analysis.py | 75 +++++++++++++++++++++ doc/compact.png | Bin 0 -> 26129 bytes doc/gpu_scan.png | Bin 0 -> 34622 bytes doc/lab2.csv | 12 ++++ doc/scan_time.png | Bin 0 -> 28680 bytes doc/scan_time_npot.png | Bin 0 -> 30115 bytes doc/thrust_scan_time_npot.png | Bin 0 -> 30990 bytes 8 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 doc/analysis.py create mode 100644 doc/compact.png create mode 100644 doc/gpu_scan.png create mode 100644 doc/lab2.csv create mode 100644 doc/scan_time.png create mode 100644 doc/scan_time_npot.png create mode 100644 doc/thrust_scan_time_npot.png diff --git a/README.md b/README.md index 0e38ddb..ade0b8e 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,122 @@ CUDA Stream Compaction **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** -* (TODO) YOUR NAME HERE - * (TODO) [LinkedIn](), [personal website](), [twitter](), etc. -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) +* Shenyue Chen + * [LinkedIn](https://www.linkedin.com/in/shenyue-chen-5b2728119/), [personal website](http://github.com/EvsChen) +* Tested on: Windows 10, Intel Xeon Platinum 8259CL @ 2.50GHz 16GB, Tesla T4 (AWS g4dn-xlarge) + +### Features +* Implementation of cpu scan, cpu compact, naive scan, work-efficient scan and work-efficient compact +* Optimization of the work-efficient scan algorithm by launching only necessary number of threads in `upSweep` and `downSweep` + * Map thread index to the actual index by `interval * idx + interval - 1`, where interval is `1 << iteration` + * For example, for N = 8, 4 threads is launched in the first iteration, 2 launched in the secondm etc. + +### Performance analysis +Block size: 128 + +Lengh of array: from (2^10 - 2^21) + +**All the time measured in this section is the average of 100 tests, to avoid caching of functions** + +As N increases, the time for cpu algorithms increases in a exponential manner while the GPU algorithms increases much slower. + +

+ +

+ +

+ +

+ +For the GPU algorithms only, the naive algorithm performs the best when N is small. But thrust scan turns out to be the best when N becomes larger. +

+ +

+ +In my experiments, there are no obvious difference for the NPOT version of the work efficient scan algorithm. +

+ +

+ +Similar things happen for the thrust scan. +

+ +

+ + + + +### Sample output +I tested each of the algorithm for 100 times and include some additional information. +``` +**************** +** SCAN TESTS ** +**************** + [ 41 23 25 1 5 46 28 37 30 42 42 25 35 ... 38 0 ] +==== cpu scan, power-of-two ==== + Time record is [11.006, 11.431, 11.774, 13.613, 14.736, 11.656, 11.874, 11.659, 11.823, 12.829, 11.737, 11.989, 11.872, ... 25.619] + elapsed time: 13.311ms (std::chrono Measured) + [ 0 41 64 89 90 95 141 169 206 236 278 320 345 ... 51331714 51331752 ] +==== cpu scan, non-power-of-two ==== + Time record is [6.4447, 6.2375, 20.608, 8.2194, 4.5156, 5.2029, 4.3476, 3.7569, 3.7672, 3.9463, 3.8041, 6.7647, 8.9613, ... 3.7673] + elapsed time: 4.7256ms (std::chrono Measured) + [ 0 41 64 89 90 95 141 169 206 236 278 320 345 ... 51331652 51331692 ] + passed +==== naive scan, power-of-two ==== + Time record is [1.6997, 1.6947, 1.6957, 1.6964, 1.6937, 1.6972, 1.6957, 1.6955, 1.6977, 1.6956, 1.6957, 1.697, 1.6957, ... 1.5053] + elapsed time: 1.5804ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + Time record is [1.505, 1.5154, 1.5114, 1.5073, 1.5134, 1.5131, 1.5095, 1.5173, 1.5183, 1.5173, 1.5181, 1.5193, 1.5177, ... 1.5286] + elapsed time: 1.5617ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + Time record is [1.0465, 0.9728, 0.92182, 0.9257, 0.93184, 2.3247, 0.92374, 0.9345, 0.92896, 0.92176, 0.92269, 0.92266, 0.93555, ... 0.9264] + elapsed time: 0.97037ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + Time record is [0.93405, 0.92058, 0.92365, 0.91706, 0.93229, 0.92541, 0.9175, 0.93056, 0.9216, 0.9176, 0.91802, 0.93424, 0.91955, ... 0.91955] + elapsed time: 0.92851ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + Time record is [0.27674, 0.29424, 0.37693, 0.28387, 0.26618, 0.26726, 0.29562, 0.27222, 0.27443, 0.29901, 0.31325, 0.30925, 0.27082, ... 0.26301] + elapsed time: 0.30972ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + Time record is [0.2639, 0.36099, 0.28035, 0.26765, 0.39936, 0.30883, 0.29104, 0.27306, 0.26934, 0.2631, 0.29914, 0.26224, 0.2863, ... 0.29773] + elapsed time: 0.31379ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 0 1 1 3 0 1 0 2 3 3 1 1 1 ... 3 0 ] +==== cpu compact without scan, power-of-two ==== + Time record is [7.5451, 5.9954, 5.9785, 5.7061, 6.2471, 6.2241, 5.9236, 5.7947, 6.4508, 5.8406, 5.8629, 5.7438, 5.7671, ... 5.7358] + elapsed time: 6.2666ms (std::chrono Measured) + [ 1 1 3 1 2 3 3 1 1 1 3 1 2 ... 1 3 ] + passed +==== cpu compact without scan, non-power-of-two ==== + Time record is [7.3508, 8.2913, 5.9938, 5.9339, 5.8238, 5.7023, 5.9023, 5.8208, 6.926, 6.5035, 5.7348, 6.8928, 7.7841, ... 5.8204] + elapsed time: 6.2747ms (std::chrono Measured) + [ 1 1 3 1 2 3 3 1 1 1 3 1 2 ... 2 3 ] + passed +==== cpu compact with scan ==== + Time record is [28.751, 24.819, 23.735, 23.725, 23.829, 23.911, 23.968, 26.001, 24.981, 24.231, 23.606, 24.335, 23.51, ... 26.916] + elapsed time: 24.973ms (std::chrono Measured) + [ 1 1 3 1 2 3 3 1 1 1 3 1 2 ... 1 3 ] + passed +==== work-efficient compact, power-of-two ==== + Time record is [1.9505, 1.6153, 1.6267, 1.6086, 1.6013, 1.6535, 1.6727, 1.7992, 1.7735, 2.1627, 1.7832, 1.7375, 1.7575, ... 1.682] + elapsed time: 1.8556ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + Time record is [1.6855, 1.9108, 1.7044, 1.6872, 1.7303, 1.9761, 1.7651, 1.9041, 1.6835, 1.6977, 1.7791, 1.6812, 1.7178, ... 1.6495] + elapsed time: 1.7805ms (CUDA Measured) + passed +Result for n = 2097152 is : + Time record is [13.311, 4.7256, 1.5804, 1.5617, 0.97037, 0.92851, 0.30972, 0.31379, 6.2666, 6.2747, 24.973, 1.8556, 1.7805, ... 0] +``` -### (TODO: Your README) -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) diff --git a/doc/analysis.py b/doc/analysis.py new file mode 100644 index 0000000..ce7ab35 --- /dev/null +++ b/doc/analysis.py @@ -0,0 +1,75 @@ +import csv +import matplotlib.pyplot as plt + +data = [] +with open('lab2.csv', 'r') as csvfile: + spamreader = csv.reader(csvfile, delimiter=',') + for row in spamreader: + drow = [] + for data_str in row: + drow.append(float(data_str)) + data.append(drow) + +start = 10 +end = 21 + +cpu_scan = [] +naive_scan = [] +efficient_scan = [] +efficient_scan_npot = [] +thrust_scan = [] +thrust_scan_npot = [] +cpu_compact = [] +efficient_compact = [] + +x = [] + +# import pdb; pdb.set_trace() + +for i in range(start, end + 1): + x.append(i) + row = data[i - 10] + cpu_scan.append(row[0]) + naive_scan.append(row[2]) + efficient_scan.append(row[4]) + efficient_scan_npot.append(row[6]) + thrust_scan.append(row[6]) + thrust_scan_npot.append(row[7]) + cpu_compact.append(row[8]) + efficient_compact.append(row[11]) + +fig, ax = plt.subplots() + +### Scan +# plt.plot(x, cpu_scan, label="cpu_scan") +# plt.plot(x, naive_scan, label="naive_scan") +# plt.plot(x, efficient_scan, label="work_efficient") +# plt.plot(x, thrust_scan, label="thrust_scane") +# plt.title("Scan time") + +### NPOT +# plt.plot(x, efficient_scan, label="work-efficient scan") +# plt.plot(x, efficient_scan_npot, label="work-efficient scan NPOT") +# plt.title("Scan time") + + +### Thrust NPOT +# plt.plot(x, thrust_scan, label="thrust scan") +# plt.plot(x, thrust_scan_npot, label="thrust scan NPOT") +# plt.title("Scan time") + +### Compact +# plt.plot(x, cpu_compact, label="cpu compact") +# plt.plot(x, efficient_compact, label="work efficient compact") +# plt.title("Compact time") + +### GPU +plt.plot(x, naive_scan, label="naive_scan") +plt.plot(x, efficient_scan, label="work_efficient") +plt.plot(x, thrust_scan, label="thrust_scan") +plt.title("GPU Scan time") + +plt.xlabel("Number (in base 2)") +plt.ylabel("Time (ms)") +plt.legend() +plt.show() \ No newline at end of file diff --git a/doc/compact.png b/doc/compact.png new file mode 100644 index 0000000000000000000000000000000000000000..36a6aae2354e38022df87b2557efea9ee408f18f GIT binary patch literal 26129 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 btpCM+V^`%GP6shZ3jQ40f0X{1W)=8fi=7EM literal 0 HcmV?d00001 diff --git a/doc/gpu_scan.png b/doc/gpu_scan.png new file mode 100644 index 0000000000000000000000000000000000000000..9a8c82aab64d8f00e1e186cc8768f06c1c15d295 GIT binary patch literal 34622 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 AH2?qr literal 0 HcmV?d00001 diff --git a/doc/scan_time_npot.png b/doc/scan_time_npot.png new file mode 100644 index 0000000000000000000000000000000000000000..54012965baec8b869d00ac759c9ab913d6d8fbfc GIT binary patch literal 30115 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 BP=x>h literal 0 HcmV?d00001 diff --git a/doc/thrust_scan_time_npot.png b/doc/thrust_scan_time_npot.png new file mode 100644 index 0000000000000000000000000000000000000000..c3bcdf451927a8d3c86c6feaa6ac588822f43b1c GIT binary patch literal 30990 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 YKP>h0ZTFVGhiqchRp4ruT(k`TAGM3dT>t<8 literal 0 HcmV?d00001