From 3d10c5c220be680702932322edb3182e6bba1c51 Mon Sep 17 00:00:00 2001 From: Lindsay Smith Date: Tue, 21 Sep 2021 13:14:41 -0400 Subject: [PATCH 1/6] cpu and naive --- stream_compaction/cpu.cu | 34 ++++++++++++++++++++++++---- stream_compaction/naive.cu | 45 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 719fa11..3d4cedf 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -19,7 +19,11 @@ namespace StreamCompaction { */ void scan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + // TODO (DONE) + odata[0] = 0; + for (int i = 0; i < n - 1; i++) { + odata[i + 1] = idata[i] + odata[i]; + } timer().endCpuTimer(); } @@ -30,9 +34,16 @@ namespace StreamCompaction { */ int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + // TODO (DONE) + int num = 0; + for (int i = 0; i < n; i++) { + if (idata[i]) { + odata[num] = idata[i]; + num++; + } + } timer().endCpuTimer(); - return -1; + return num; } /** @@ -43,8 +54,23 @@ namespace StreamCompaction { int compactWithScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); // TODO + int *arr = new int[n]; + for (int i = 0; i < n; i++) { + arr[i] = idata[i] ? 1 : 0; + } + + int* scanArr = new int[n]; + scan(n, scanArr, arr); + + int num = 0; + for (int i = 0; i < n; i++) { + if (arr[i]) { + odata[scanArr[i]] = idata[i]; + num++; + } + } timer().endCpuTimer(); - return -1; + return num; } } } diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 4308876..6aa5c55 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -11,15 +11,56 @@ namespace StreamCompaction { static PerformanceTimer timer; return timer; } - // TODO: __global__ + // TODO: (DONE) + __global__ void kernNaiveScan(int N, int* odata, int* idata, int offset) { + int idx = threadIdx.x + (blockIdx.x * blockDim.x); + if (idx >= N) { + return; + } + if (idx >= offset) { + odata[idx] = idata[idx - offset] + idata[idx]; + } + else { + odata[idx] = idata[idx]; + } + } /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + // TODO (DONE) + const int blockSize = 128; + dim3 blocksPerGrid((n + blockSize - 1) / blockSize); + int max = ilog2ceil(n); + + //buffers + int* buf1; + int* buf2; + + //malloc + cudaMalloc((void**)&buf1, n * sizeof(int)); + //checkCUDAErrorWithLine("cudaMalloc buf1 failed!"); + cudaMalloc((void**)&buf2, n * sizeof(int)); + //checkCUDAErrorWithLine("cudaMalloc buf2 failed!"); + + //fill array + cudaMemcpy(buf1, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + + //call kernel timer().startGpuTimer(); - // TODO + for (int i = 1; i <= max; i++) { + kernNaiveScan<<>>(n, buf2, buf1, (int)powf(2, i - 1)); + std::swap(buf1, buf2); + } timer().endGpuTimer(); + + //copy data to odata + odata[0] = 0; + cudaMemcpy(odata + 1, buf1, sizeof(int) * n, cudaMemcpyDeviceToHost); + + cudaFree(buf1); + cudaFree(buf2); } } } From 5ce4a69ee2f33e400a9237def7891284a52f7fa0 Mon Sep 17 00:00:00 2001 From: Lindsay Smith Date: Tue, 21 Sep 2021 17:41:53 -0400 Subject: [PATCH 2/6] efficient --- stream_compaction/common.cu | 17 ++++++ stream_compaction/cpu.cu | 6 +- stream_compaction/efficient.cu | 101 ++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/stream_compaction/common.cu b/stream_compaction/common.cu index 2ed6d63..f1b7a52 100644 --- a/stream_compaction/common.cu +++ b/stream_compaction/common.cu @@ -24,6 +24,16 @@ namespace StreamCompaction { */ __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { // TODO + int idx = threadIdx.x + (blockDim.x * blockIdx.x); + if (idx >= n) { + return; + } + if (idata[idx] != 0) { + bools[idx] = 1; + } + else { + bools[idx] = 0; + } } /** @@ -33,6 +43,13 @@ 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] == 1) { + odata[indices[idx]] = idata[idx]; + } } } diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 3d4cedf..932e9d6 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -60,7 +60,11 @@ namespace StreamCompaction { } int* scanArr = new int[n]; - scan(n, scanArr, arr); + //scan(n, scanArr, arr); + scanArr[0] = 0; + for (int i = 0; i < n - 1; i++) { + scanArr[i + 1] = arr[i] + scanArr[i]; + } int num = 0; for (int i = 0; i < n; i++) { diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 2db346e..b4a8894 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -12,13 +12,65 @@ namespace StreamCompaction { return timer; } + int* dev_buf; + int* dev_bools; + int* dev_idata; + int* dev_odata; + int* dev_scanned; + + __global__ void kernUpSweep(int N, int* data, int offset) { + int idx = threadIdx.x + (blockDim.x * blockIdx.x); + if (idx >= N) { + return; + } + + if (idx % (2 * offset) == 0) { + data[idx + offset * 2 - 1] += data[idx + offset - 1]; + } + } + + __global__ void kernDownSweep(int N, int* data, int offset) { + int idx = threadIdx.x + (blockDim.x * blockIdx.x); + if (idx >= N) { + return; + } + + if (idx % (2 * offset) == 0) { + int temp = data[idx + offset - 1]; + data[idx + offset - 1] = data[idx + offset * 2 - 1]; + data[idx + offset * 2 - 1] += temp; + } + } + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + // TODO (DONE) + + //other variables + int blockSize = 128; + int max = ilog2ceil(n); + int numObj = (int)powf(2, max); + dim3 numBlocks((numObj + blockSize - 1) / blockSize); + + //malloc + memcopy + cudaMalloc((void**)&dev_buf, sizeof(int) * numObj); + cudaMemcpy(dev_buf, idata, numObj * sizeof(int), cudaMemcpyHostToDevice); + timer().startGpuTimer(); - // TODO + //call kernels + for (int i = 0; i < max; i++) { + kernUpSweep<<>>(numObj, dev_buf, (int)powf(2, i)); + } + cudaMemset(dev_buf + numObj - 1, 0, sizeof(int)); + for (int i = max - 1; i >= 0; i--) { + kernDownSweep<<>>(numObj, dev_buf, (int)powf(2, i)); + } timer().endGpuTimer(); + + cudaMemcpy(odata, dev_buf, sizeof(int) * n, cudaMemcpyDeviceToHost); + cudaFree(dev_buf); } /** @@ -31,10 +83,53 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { + //variables + int blockSize = 128; + int max = ilog2ceil(n); + int numObj = (int)powf(2, max); + dim3 numBlocks((numObj + blockSize - 1) / blockSize); + + //malloc + cudaMalloc((void**)&dev_bools, sizeof(int) * numObj); + cudaMalloc((void**)&dev_idata, sizeof(int) * numObj); + cudaMalloc((void**)&dev_odata, sizeof(int) * numObj); + cudaMalloc((void**)&dev_scanned, sizeof(int) * numObj); + + cudaMemcpy(dev_idata, idata, numObj * sizeof(int), cudaMemcpyHostToDevice); + timer().startGpuTimer(); - // TODO + // TODO (DONE) + StreamCompaction::Common::kernMapToBoolean<<>>(numObj, dev_bools, dev_idata); + cudaMemcpy(dev_scanned, dev_bools, sizeof(int) * numObj, cudaMemcpyDeviceToDevice); + + for (int i = 0; i < max; i++) { + kernUpSweep<<>>(numObj, dev_scanned, (int)powf(2, i)); + } + cudaMemset(dev_scanned + numObj - 1, 0, sizeof(int)); + for (int i = max - 1; i >= 0; i--) { + kernDownSweep<<>>(numObj, dev_scanned, (int)powf(2, i)); + } + + StreamCompaction::Common::kernScatter<<>>(numObj, dev_odata, dev_idata, dev_bools, dev_scanned); + timer().endGpuTimer(); - return -1; + + int* arr = new int[numObj]; + cudaMemcpy(arr, dev_bools, sizeof(int) * numObj, cudaMemcpyDeviceToHost); + cudaMemcpy(odata, dev_odata, sizeof(int) * n, cudaMemcpyDeviceToHost); + + cudaFree(dev_idata); + cudaFree(dev_bools); + cudaFree(dev_scanned); + cudaFree(dev_odata); + + int count = 0; + for (int i = 0; i < n; i++) { + if (arr[i] == 1) { + count++; + } + } + return count; } } } From e70965052bc2e86dd083942d3fe14a0690498017 Mon Sep 17 00:00:00 2001 From: Lindsay Smith Date: Tue, 21 Sep 2021 18:27:32 -0400 Subject: [PATCH 3/6] thrust --- stream_compaction/efficient.cu | 4 ++-- stream_compaction/thrust.cu | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index b4a8894..92cc5d6 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -49,7 +49,7 @@ namespace StreamCompaction { // TODO (DONE) //other variables - int blockSize = 128; + int blockSize = 256; int max = ilog2ceil(n); int numObj = (int)powf(2, max); dim3 numBlocks((numObj + blockSize - 1) / blockSize); @@ -84,7 +84,7 @@ namespace StreamCompaction { */ int compact(int n, int *odata, const int *idata) { //variables - int blockSize = 128; + int blockSize = 256; int max = ilog2ceil(n); int numObj = (int)powf(2, max); dim3 numBlocks((numObj + blockSize - 1) / blockSize); diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index 1def45e..2fbb3c5 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -18,11 +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) { + //TODO (DONE) + thrust::device_vector dv_in(idata, idata + n); + thrust::device_vector dv_out(n); 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(dv_in.begin(), dv_in.end(), dv_out.begin()); timer().endGpuTimer(); + thrust::copy(dv_out.begin(), dv_out.end(), odata); } } } From 16d9c2ba2746701aaf53676371ae7bfe927cc7ee Mon Sep 17 00:00:00 2001 From: Lindsay Smith Date: Tue, 21 Sep 2021 20:47:45 -0400 Subject: [PATCH 4/6] graph 1 --- img/ScanTimes.png | Bin 0 -> 36478 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/ScanTimes.png diff --git a/img/ScanTimes.png b/img/ScanTimes.png new file mode 100644 index 0000000000000000000000000000000000000000..f10ecb01f685b1fb771f5e79b31b4a4b1dd36046 GIT binary patch literal 36478 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 Date: Tue, 21 Sep 2021 21:07:21 -0400 Subject: [PATCH 5/6] graph 2 --- img/CompactTimes.png | Bin 0 -> 35284 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/CompactTimes.png diff --git a/img/CompactTimes.png b/img/CompactTimes.png new file mode 100644 index 0000000000000000000000000000000000000000..1f34776ca8902724e11f8701fcb814b5e1bbbc4a GIT binary patch literal 35284 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�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 literal 0 HcmV?d00001 From ecb895220e169ed6848249c2120b2c6f22cd5f76 Mon Sep 17 00:00:00 2001 From: Lindsay Smith <56971812+lsmith24@users.noreply.github.com> Date: Tue, 21 Sep 2021 21:16:12 -0400 Subject: [PATCH 6/6] Update README.md --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0e38ddb..9836f11 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,100 @@ 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) +* Lindsay Smith + * [LinkedIn](https://www.linkedin.com/in/lindsay-j-smith/), [personal website](https://lindsays-portfolio-d6aa5d.webflow.io/). +* Tested on: Windows 10, i7-11800H 144Hz 16GB RAM, GeForce RTX 3060 512GB SSD (Personal Laptop) -### (TODO: Your README) +For this project I implemented scan and compact algorithms and compared their various runtimes +on the GPU and CPU, testing with various array sizes and analyzing how efficient each one was. + +Implemenation includes: +* CPU Scan + Stream Compaction +* GPU Naive Scan +* GPU Work-Efficient Scan +* GPU Work-Efficient Compaction +* Thrust Scan (mainly for comparison purposes) + +For all of my analysis I am utilizing a block size of 256, which I found to be optimal. + +![](img/ScanTimes.png) + +In this graph the lower times are better. +We can see that the CPU is actually faster than the GPU for most array sizes. +I did have exceptions to this however in the range of about 2^16 - 2^18, where the GPU scans were faster. Of course we +can also see that the Thrust scan is faster than all of the implementations I wrote, again with an exception at 2^16. +I am not sure the reason for this, but it seems that an array size around 2^16 is somewhat optimal for performance of +my implementations. If I continue with arry sizes into the millions, past what is shown in the graph, the discrepency +in the execution times only widens. + +It is very clear that Thrust has optimizations far beyond my own implementations. With a small data set the differences +are not as apparent, but again once we reach thousands and millions of data points in the array, it is clear how +much more efficient the Thrust algorithm is. I would assume that Thrust takes advantage of memory, as I know that +my implementation could be made more efficient by writing to contiguous memory and allowing the threads that are not working +to be reused. If my implementations took advantage of this I would be able to reduce the number of threads by half at +each kernel call, and therefore would have more threads available to do work for other calls. + +![](img/CompactTimes.png) + +In this graph we also want to note that the lower values are faster runtimes and therefore "better". +It is interesting here that although for scan the CPU was consistently faster than the GPU, once we add the compact step +the CPU is no longer faster. The GPU here is only slower than the CPU for very small array sizes, but once we get into arrays +with thousands and especially millions of elements the GPU is definitively faster. This is probably due to the fact that +the GPU is taking advantages of a very high number of threads, whereas the CPU cannot do that and takes a very long time to +calculate each step of the compact algorithm. + +``` +**************** +** SCAN TESTS ** +**************** + [ 46 29 32 19 41 43 12 31 4 10 2 6 39 ... 0 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.3919ms (std::chrono Measured) + [ 0 46 75 107 126 167 210 222 253 257 267 269 275 ... 6427122 6427122 ] +==== cpu scan, non-power-of-two ==== + elapsed time: 0.3764ms (std::chrono Measured) + [ 0 46 75 107 126 167 210 222 253 257 267 269 275 ... 6427059 6427087 ] + passed +==== naive scan, power-of-two ==== + elapsed time: 0.100352ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.098304ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.206848ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.205824ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.171008ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.17728ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 3 3 0 0 0 3 1 3 2 0 0 2 0 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.6072ms (std::chrono Measured) + [ 3 3 3 1 3 2 2 3 3 3 3 1 3 ... 1 2 ] + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.572ms (std::chrono Measured) + [ 3 3 3 1 3 2 2 3 3 3 3 1 3 ... 2 1 ] + passed +==== cpu compact with scan ==== + elapsed time: 1.4129ms (std::chrono Measured) + [ 3 3 3 1 3 2 2 3 3 3 3 1 3 ... 1 2 ] + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.219264ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.219136ms (CUDA Measured) + passed``` -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.)