From 63e00ec2907825d426c8c9bb2370dc6a8999a084 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Sun, 18 Sep 2016 14:44:15 -0400 Subject: [PATCH 01/15] change to sm_50; done cpu scan --- stream_compaction/CMakeLists.txt | 2 +- stream_compaction/cpu.cu | 6 +++++- 2 files changed, 6 insertions(+), 2 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 e600c29..26ef1c8 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -9,7 +9,11 @@ namespace CPU { */ void scan(int n, int *odata, const int *idata) { // TODO - printf("TODO\n"); + //printf("TODO\n"); + odata[0] = 0; + for (int i = 1; i < n; ++i) { + odata[i] = odata[i - 1] + idata[i - 1]; + } } /** From 33395d8eaeb8fd5643bb92253393b982b4e8fb29 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Wed, 21 Sep 2016 14:08:46 -0400 Subject: [PATCH 02/15] set block size to 256; done naive scan --- stream_compaction/common.h | 1 + stream_compaction/naive.cu | 67 +++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/stream_compaction/common.h b/stream_compaction/common.h index 4f52663..abfb918 100644 --- a/stream_compaction/common.h +++ b/stream_compaction/common.h @@ -26,6 +26,7 @@ inline int ilog2ceil(int x) { namespace StreamCompaction { + const int BLOCK_SIZE = 256; namespace Common { __global__ void kernMapToBoolean(int n, int *bools, const int *idata); diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 3d86b60..735f6e2 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -7,13 +7,78 @@ namespace StreamCompaction { namespace Naive { // TODO: __global__ +__global__ void accumulate(const int n, const int step, int *idata, int *odata) { + + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index >= n) { + return; + } + + if (index - step < 0) { + odata[index] = idata[index]; + } else { + odata[index] = idata[index] + idata[index - step]; + } +} + +__global__ void shiftRight(const int n, int *idata, int *odata) { + + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index >= n) { + return; + } else if (index == 0) { + odata[index] = 0; + return; + } + + odata[index] = idata[index - 1]; +} + +// swap +inline void swap(int &x, int &y) { + auto tmp = x; x = y; y = tmp; +} /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { // TODO - printf("TODO\n"); + // printf("TODO\n"); + int *dev_data[2]; + int input = 1; + int output = 0; + + // device memory allocation + cudaMalloc((void**)&dev_data[0], sizeof(int) * n); + checkCUDAError("Failed to allocate dev_data[0]"); + + cudaMalloc((void**)&dev_data[1], sizeof(int) * n); + checkCUDAError("Failed to allocate dev_data[1]"); + + // copy input data to device + cudaMemcpy((void*)dev_data[input], (const void*)idata, sizeof(int) * n, + cudaMemcpyHostToDevice); + + // do scan + dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; + + shiftRight<<>>(n, dev_data[input], dev_data[output]); + + for (int step = 1; step < n; step <<= 1) { + swap(input, output); + accumulate<<>>(n, step, dev_data[input], dev_data[output]); + } + + // copy result to host + cudaMemcpy((void*)odata, (const void*)dev_data[output], sizeof(int) * n, + cudaMemcpyDeviceToHost); + + // free memory on device + cudaFree(dev_data[0]); + cudaFree(dev_data[1]); } } From 8cbd75b1dd0b76677d013557037c0657711c6444 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Wed, 21 Sep 2016 14:48:08 -0400 Subject: [PATCH 03/15] done efficient scan --- stream_compaction/efficient.cu | 87 +++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index b2f739b..cd9e866 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -7,13 +7,98 @@ namespace StreamCompaction { namespace Efficient { // TODO: __global__ +__global__ void upSweep(const int n, const int step, int *idata, int *odata) { + + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index >= n) { + return; + } + + int rIndex = n - 1 - index; + int mask = 1; + + for (int i = 1; i != step; (i <<= 1), (mask = mask << 1 | 1)); + + if (index - step < 0 || (rIndex & mask) != 0) { + odata[index] = idata[index]; + } else { + odata[index] = idata[index] + idata[index - step]; + } +} + +__global__ void downSweep(const int n, const int step, int *idata, int *odata) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index >= n) { + return; + } + + int rIndex = n - 1 - index; + int mask = 1; + + for (int i = 1; i != step; (i <<= 1), (mask = mask << 1 | 1)); + + if ((rIndex & mask) == 0 && index - step >= 0) { + odata[index] = idata[index] + idata[index - step]; + odata[index - step] = idata[index]; + } else if (rIndex - step < 0 || (rIndex - step & mask) != 0) { + odata[index] = idata[index]; + } +} + +inline void swap(int &a, int &b) { + auto tmp = a; a = b; b = tmp; +} /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { // TODO - printf("TODO\n"); + // printf("TODO\n"); + int *dev_data[2]; + int input = 1; + int output = 0; + + // device memory allocation + cudaMalloc((void**)&dev_data[0], sizeof(int) * n); + checkCUDAError("Failed to allocate dev_data[0]"); + + cudaMalloc((void**)&dev_data[1], sizeof(int) * n); + checkCUDAError("Failed to allocate dev_data[1]"); + + // copy input data to device + cudaMemcpy((void*)dev_data[input], (const void*)idata, sizeof(int) * n, + cudaMemcpyHostToDevice); + + // do scan + dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; + int step; + + swap(input, output); + // up-sweep + for (step = 1; step < n; step <<= 1) { + swap(input, output); + upSweep<<>>(n, step, dev_data[input], dev_data[output]); + } + + // set last element to 0 + cudaMemset(&dev_data[output][n - 1], 0, sizeof(int)); + + // down-sweep + for (step >>= 1; step > 0; step >>= 1) { + swap(input, output); + downSweep<<>>(n, step, dev_data[input], dev_data[output]); + } + + // copy result to host + cudaMemcpy((void*)odata, (const void*)dev_data[output], sizeof(int) * n, + cudaMemcpyDeviceToHost); + + // free memory on device + cudaFree(dev_data[0]); + cudaFree(dev_data[1]); } /** From 2ae8871c1165662bbf2b7205a16726046b9a9de5 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Wed, 21 Sep 2016 14:48:43 -0400 Subject: [PATCH 04/15] done thrust scan --- stream_compaction/thrust.cu | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/stream_compaction/thrust.cu b/stream_compaction/thrust.cu index d8dbb32..34426af 100644 --- a/stream_compaction/thrust.cu +++ b/stream_compaction/thrust.cu @@ -16,6 +16,28 @@ 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()); + int *dev_data; + + // device memory allocation + cudaMalloc((void**)&dev_data, sizeof(int) * n); + checkCUDAError("Failed to allocate dev_data[0]"); + + // copy input data to device + cudaMemcpy((void*)dev_data, (const void*)idata, sizeof(int) * n, + cudaMemcpyHostToDevice); + + // cast to device ptr + thrust::device_ptr dev_thrust_data(dev_data); + + // do scan + thrust::exclusive_scan(dev_thrust_data, dev_thrust_data + n, dev_thrust_data); + + // copy result to host + cudaMemcpy((void*)odata, (const void*)dev_data, sizeof(int) * n, + cudaMemcpyDeviceToHost); + + // free memory on device + cudaFree(dev_data); } } From c89751f1bb63378ccadb07c1977401c1bbe8d5ad Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Wed, 21 Sep 2016 15:05:42 -0400 Subject: [PATCH 05/15] done cpu compaction --- stream_compaction/cpu.cu | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 26ef1c8..5fae56e 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -23,7 +23,14 @@ void scan(int n, int *odata, const int *idata) { */ int compactWithoutScan(int n, int *odata, const int *idata) { // TODO - return -1; + int m = 0; + + for (int i = 0; i < n; ++i) { + if (idata[i] == 0) continue; + odata[m++] = idata[i]; + } + + return m; } /** @@ -33,7 +40,24 @@ int compactWithoutScan(int n, int *odata, const int *idata) { */ int compactWithScan(int n, int *odata, const int *idata) { // TODO - return -1; + int *nonZero = new int [n]; + int m = 0; + + for (int i = 0; i < n; ++i) { + nonZero[i] = idata[i] == 0 ? 0 : 1; + } + + scan(n, odata, nonZero); + m = odata[n - 1]; + + for (int i = 0; i < n; ++i) { + if (nonZero[i] == 0) continue; + odata[odata[i]] = idata[i]; + } + + delete [] nonZero; + + return m; } } From 805a0689865c60ebdb97f1c231689ff8f61573f8 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Sat, 24 Sep 2016 23:18:24 -0400 Subject: [PATCH 06/15] allocate memory for test data from heap --- src/main.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 675da35..b9b0d3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,9 +14,14 @@ #include "testing_helpers.hpp" int main(int argc, char* argv[]) { - const int SIZE = 1 << 8; + const int SIZE = 1 << 20; const int NPOT = SIZE - 3; - int a[SIZE], b[SIZE], c[SIZE]; + int *a, *b, *c; + + // allocate memory for test data + a = new int [SIZE]; + b = new int [SIZE]; + c = new int [SIZE]; // Scan tests @@ -120,4 +125,9 @@ int main(int argc, char* argv[]) { count = StreamCompaction::Efficient::compact(NPOT, c, a); //printArray(count, c, true); printCmpLenResult(count, expectedNPOT, b, c); + + // free memory + delete [] a; + delete [] b; + delete [] c; } From 495959acf0f03e7d2c3f0a85c6d82c9c740ffecb Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Sun, 25 Sep 2016 00:05:07 -0400 Subject: [PATCH 07/15] fix efficient scan: scan in place --- stream_compaction/efficient.cu | 48 ++++++++++++---------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index cd9e866..323a107 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -7,7 +7,7 @@ namespace StreamCompaction { namespace Efficient { // TODO: __global__ -__global__ void upSweep(const int n, const int step, int *idata, int *odata) { +__global__ void upSweep(const int n, const int step, int *data) { int index = blockIdx.x * blockDim.x + threadIdx.x; @@ -20,14 +20,12 @@ __global__ void upSweep(const int n, const int step, int *idata, int *odata) { for (int i = 1; i != step; (i <<= 1), (mask = mask << 1 | 1)); - if (index - step < 0 || (rIndex & mask) != 0) { - odata[index] = idata[index]; - } else { - odata[index] = idata[index] + idata[index - step]; + if (index - step >= 0 && (rIndex & mask) == 0) { + data[index] = data[index] + data[index - step]; } } -__global__ void downSweep(const int n, const int step, int *idata, int *odata) { +__global__ void downSweep(const int n, const int step, int *data) { int index = blockIdx.x * blockDim.x + threadIdx.x; if (index >= n) { @@ -39,66 +37,52 @@ __global__ void downSweep(const int n, const int step, int *idata, int *odata) { for (int i = 1; i != step; (i <<= 1), (mask = mask << 1 | 1)); - if ((rIndex & mask) == 0 && index - step >= 0) { - odata[index] = idata[index] + idata[index - step]; - odata[index - step] = idata[index]; - } else if (rIndex - step < 0 || (rIndex - step & mask) != 0) { - odata[index] = idata[index]; + if (index - step >= 0 && (rIndex & mask) == 0) { + auto tmp = data[index]; + data[index] += data[index - step]; + data[index - step] = tmp; } } -inline void swap(int &a, int &b) { - auto tmp = a; a = b; b = tmp; -} - /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { // TODO // printf("TODO\n"); - int *dev_data[2]; - int input = 1; - int output = 0; + int *dev_data; // device memory allocation - cudaMalloc((void**)&dev_data[0], sizeof(int) * n); + cudaMalloc((void**)&dev_data, sizeof(int) * n); checkCUDAError("Failed to allocate dev_data[0]"); - cudaMalloc((void**)&dev_data[1], sizeof(int) * n); - checkCUDAError("Failed to allocate dev_data[1]"); - // copy input data to device - cudaMemcpy((void*)dev_data[input], (const void*)idata, sizeof(int) * n, + cudaMemcpy((void*)dev_data, (const void*)idata, sizeof(int) * n, cudaMemcpyHostToDevice); // do scan dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; int step; - swap(input, output); // up-sweep for (step = 1; step < n; step <<= 1) { - swap(input, output); - upSweep<<>>(n, step, dev_data[input], dev_data[output]); + upSweep<<>>(n, step, dev_data); } // set last element to 0 - cudaMemset(&dev_data[output][n - 1], 0, sizeof(int)); + cudaMemset(&dev_data[n - 1], 0, sizeof(int)); // down-sweep for (step >>= 1; step > 0; step >>= 1) { - swap(input, output); - downSweep<<>>(n, step, dev_data[input], dev_data[output]); + downSweep<<>>(n, step, dev_data); } // copy result to host - cudaMemcpy((void*)odata, (const void*)dev_data[output], sizeof(int) * n, + cudaMemcpy((void*)odata, (const void*)dev_data, sizeof(int) * n, cudaMemcpyDeviceToHost); // free memory on device - cudaFree(dev_data[0]); - cudaFree(dev_data[1]); + cudaFree(dev_data); } /** From 4a413661d0d510420e08f3d6827ee659a3f79562 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Sun, 25 Sep 2016 00:36:20 -0400 Subject: [PATCH 08/15] done kernMapToBool and kernScatter --- stream_compaction/common.cu | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/stream_compaction/common.cu b/stream_compaction/common.cu index fe872d4..56143b1 100644 --- a/stream_compaction/common.cu +++ b/stream_compaction/common.cu @@ -24,6 +24,13 @@ namespace Common { */ __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { // TODO + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index >= n) { + return; + } + + bools[index] = idata[index] == 0 ? 0 : 1; } /** @@ -33,6 +40,13 @@ __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) { // TODO + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index >= n || bools[index] == 0) { + return; + } + + odata[indices[index]] = idata[index]; } } From aa197ea4ce80719ac147edcf33c7fabc63cc4d54 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Sun, 25 Sep 2016 01:08:13 -0400 Subject: [PATCH 09/15] done efficient stream compaction --- stream_compaction/efficient.cu | 89 +++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 323a107..0990069 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -44,6 +44,24 @@ __global__ void downSweep(const int n, const int step, int *data) { } } +void scanOnGPU(const int n, int *dev_data) { + dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; + int step; + + // up-sweep + for (step = 1; step < n; step <<= 1) { + upSweep<<>>(n, step, dev_data); + } + + // set last element to 0 + cudaMemset(&dev_data[n - 1], 0, sizeof(int)); + + // down-sweep + for (step >>= 1; step > 0; step >>= 1) { + downSweep<<>>(n, step, dev_data); + } +} + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ @@ -54,28 +72,14 @@ void scan(int n, int *odata, const int *idata) { // device memory allocation cudaMalloc((void**)&dev_data, sizeof(int) * n); - checkCUDAError("Failed to allocate dev_data[0]"); + checkCUDAError("Failed to allocate dev_data"); // copy input data to device cudaMemcpy((void*)dev_data, (const void*)idata, sizeof(int) * n, cudaMemcpyHostToDevice); // do scan - dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; - int step; - - // up-sweep - for (step = 1; step < n; step <<= 1) { - upSweep<<>>(n, step, dev_data); - } - - // set last element to 0 - cudaMemset(&dev_data[n - 1], 0, sizeof(int)); - - // down-sweep - for (step >>= 1; step > 0; step >>= 1) { - downSweep<<>>(n, step, dev_data); - } + scanOnGPU(n, dev_data); // copy result to host cudaMemcpy((void*)odata, (const void*)dev_data, sizeof(int) * n, @@ -96,7 +100,58 @@ void scan(int n, int *odata, const int *idata) { */ int compact(int n, int *odata, const int *idata) { // TODO - return -1; + int count; + int *dev_data; + int *dev_dataCopy; + int *dev_bool; + int *dev_boolScan; + + // device memory allocation + cudaMalloc((void**)&dev_data, sizeof(int) * n); + checkCUDAError("Failed to allocate dev_data"); + + cudaMalloc((void**)&dev_dataCopy, sizeof(int) * n); + checkCUDAError("Failed to allocate dev_dataCopy"); + + cudaMalloc((void**)&dev_bool, sizeof(int) * n); + checkCUDAError("Failed to allocate dev_bool"); + + cudaMalloc((void**)&dev_boolScan, sizeof(int) * n); + checkCUDAError("Failed to allocate dev_boolScan"); + + // copy input data to device + cudaMemcpy((void*)dev_data, (const void*)idata, sizeof(int) * n, + cudaMemcpyHostToDevice); + + dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; + + // map to booleans + Common::kernMapToBoolean<<>>(n, dev_bool, dev_data); + + // scan booleans + cudaMemcpy((void*)dev_boolScan, (const void*)dev_bool, sizeof(int) * n, + cudaMemcpyDeviceToDevice); + scanOnGPU(n, dev_boolScan); + + // scatter + cudaMemcpy((void*)dev_dataCopy, (const void*)dev_data, sizeof(int) * n, + cudaMemcpyDeviceToDevice); + Common::kernScatter<<>>(n, dev_data, dev_dataCopy, + dev_bool, dev_boolScan); + + // copy result to host + cudaMemcpy((void*)odata, (const void*)dev_data, sizeof(int) * n, + cudaMemcpyDeviceToHost); + cudaMemcpy((void*)&count, (const void*)&dev_boolScan[n - 1], sizeof(int), + cudaMemcpyDeviceToHost); + + // free memory on device + cudaFree(dev_data); + cudaFree(dev_dataCopy); + cudaFree(dev_bool); + cudaFree(dev_boolScan); + + return count; } } From 0314aaa66d977bf5bc1947b6f0dd09f87c3fc49b Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Tue, 27 Sep 2016 22:44:07 -0400 Subject: [PATCH 10/15] Update README.md --- README.md | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b71c458..b827944 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,25 @@ -CUDA Stream Compaction -====================== +# University of Pennsylvania, CIS 565: GPU Programming and Architecture +## Project 2 - Stream Compaction +* Liang Peng +* Tested on: Windows 10, i7-6700HQ @ 2.6GHz, 8GB, GTX 960M (Personal Computer) -**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** +## Screenshots +* Result +
![](http://i.imgur.com/fDr2pRK.jpg) -* (TODO) YOUR NAME HERE -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) +## Analysis +* Time measurement with std::chrono +
+high_resolution_clock::time_point t1;
+kernel<<<..., ...>>>(...);
+cudaDeviceSynchronize();
+high_resolution_clock::time_point t2;
+duration t = t1 = t2;
+print t.count();
+
-### (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.) +* Array size +
![](http://i.imgur.com/fDr2pRK.jpg) +* Block size +
![](http://i.imgur.com/fDr2pRK.jpg) From 331efe27fa9a117ea38d754cf92bed4fe34464e2 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Tue, 27 Sep 2016 22:46:25 -0400 Subject: [PATCH 11/15] add timing --- img/Capture1.PNG | Bin 0 -> 42625 bytes img/Capture2.PNG | Bin 0 -> 24732 bytes src/main.cpp | 2 +- stream_compaction/cpu.cu | 9 +++++++++ stream_compaction/efficient.cu | 14 ++++++++++++++ stream_compaction/naive.cu | 14 ++++++++++++++ 6 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 img/Capture1.PNG create mode 100644 img/Capture2.PNG diff --git a/img/Capture1.PNG b/img/Capture1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..88ec082de216b903143ad44f964a3d5f0c6e404f GIT binary patch literal 42625 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 literal 0 HcmV?d00001 diff --git a/img/Capture2.PNG b/img/Capture2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1bb6135fa65227a3b14d14bafc977103f0682168 GIT binary patch literal 24732 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 G{r@kckLcO} literal 0 HcmV?d00001 diff --git a/src/main.cpp b/src/main.cpp index b9b0d3d..accd8f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ #include "testing_helpers.hpp" int main(int argc, char* argv[]) { - const int SIZE = 1 << 20; + const int SIZE = 1 << 23; const int NPOT = SIZE - 3; int *a, *b, *c; diff --git a/stream_compaction/cpu.cu b/stream_compaction/cpu.cu index 5fae56e..04a08b6 100644 --- a/stream_compaction/cpu.cu +++ b/stream_compaction/cpu.cu @@ -1,5 +1,10 @@ #include +#include +using namespace std::chrono; #include "cpu.h" +#include +using std::cout; +using std::endl; namespace StreamCompaction { namespace CPU { @@ -10,10 +15,14 @@ namespace CPU { void scan(int n, int *odata, const int *idata) { // TODO //printf("TODO\n"); + high_resolution_clock::time_point t1 = high_resolution_clock::now(); odata[0] = 0; for (int i = 1; i < n; ++i) { odata[i] = odata[i - 1] + idata[i - 1]; } + high_resolution_clock::time_point t2 = high_resolution_clock::now(); + duration t12 = duration_cast>(t2 - t1); + cout << "----------Time consumed: " << t12.count() << " ms----------" << endl; } /** diff --git a/stream_compaction/efficient.cu b/stream_compaction/efficient.cu index 0990069..7271860 100644 --- a/stream_compaction/efficient.cu +++ b/stream_compaction/efficient.cu @@ -1,5 +1,10 @@ #include #include +#include +using namespace std::chrono; +#include +using std::cout; +using std::endl; #include "common.h" #include "efficient.h" @@ -78,9 +83,18 @@ void scan(int n, int *odata, const int *idata) { cudaMemcpy((void*)dev_data, (const void*)idata, sizeof(int) * n, cudaMemcpyHostToDevice); + // tic + high_resolution_clock::time_point t1 = high_resolution_clock::now(); + // do scan scanOnGPU(n, dev_data); + // toc + cudaDeviceSynchronize(); + high_resolution_clock::time_point t2 = high_resolution_clock::now(); + duration t12 = duration_cast>(t2 - t1); + cout << "----------Time consumed: " << t12.count() << " ms----------" << endl; + // copy result to host cudaMemcpy((void*)odata, (const void*)dev_data, sizeof(int) * n, cudaMemcpyDeviceToHost); diff --git a/stream_compaction/naive.cu b/stream_compaction/naive.cu index 735f6e2..929995b 100644 --- a/stream_compaction/naive.cu +++ b/stream_compaction/naive.cu @@ -1,5 +1,10 @@ #include #include +#include +using namespace std::chrono; +#include +using std::cout; +using std::endl; #include "common.h" #include "naive.h" @@ -62,6 +67,9 @@ void scan(int n, int *odata, const int *idata) { cudaMemcpy((void*)dev_data[input], (const void*)idata, sizeof(int) * n, cudaMemcpyHostToDevice); + // tic + high_resolution_clock::time_point t1 = high_resolution_clock::now(); + // do scan dim3 blockCount = (n - 1) / BLOCK_SIZE + 1; @@ -72,6 +80,12 @@ void scan(int n, int *odata, const int *idata) { accumulate<<>>(n, step, dev_data[input], dev_data[output]); } + // toc + cudaDeviceSynchronize(); + high_resolution_clock::time_point t2 = high_resolution_clock::now(); + duration t12 = duration_cast>(t2 - t1); + cout << "----------Time consumed: " << t12.count() << " ms----------" << endl; + // copy result to host cudaMemcpy((void*)odata, (const void*)dev_data[output], sizeof(int) * n, cudaMemcpyDeviceToHost); From e3186822f2ad69a1df38f8b6ec688bca323ff33b Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Tue, 27 Sep 2016 23:37:08 -0400 Subject: [PATCH 12/15] add image --- img/Capture3.PNG | Bin 0 -> 18559 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/Capture3.PNG diff --git a/img/Capture3.PNG b/img/Capture3.PNG new file mode 100644 index 0000000000000000000000000000000000000000..497edb3453c1c7933cecfd386919648130b15d33 GIT binary patch literal 18559 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 MHT$jbSC?!53$P=yBLDyZ literal 0 HcmV?d00001 From 76dfac17514f4d56b47fe27d9e1d76efc6784267 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Tue, 27 Sep 2016 23:41:24 -0400 Subject: [PATCH 13/15] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b827944..1310ac6 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## Screenshots * Result -
![](http://i.imgur.com/fDr2pRK.jpg) +
## Analysis * Time measurement with std::chrono @@ -14,12 +14,12 @@ high_resolution_clock::time_point t1;
kernel<<<..., ...>>>(...);
cudaDeviceSynchronize();
high_resolution_clock::time_point t2;
-duration t = t1 = t2;
+duration t = t2 - t1;
print t.count();
* Array size -
![](http://i.imgur.com/fDr2pRK.jpg) +
* Block size -
![](http://i.imgur.com/fDr2pRK.jpg) +
From cf65a82d3831154d1bc4c4b812cf644ae0238284 Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Tue, 27 Sep 2016 23:52:36 -0400 Subject: [PATCH 14/15] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1310ac6..a65e66b 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ print t.count();
* Array size
- + * _Observation_ CPU implementation is always faster than GPU implementation, the reason might be there is considerable overhead in the GPU implementation. My speculation is that as the scan process goes to next level, number of idling threads increases, which can be optimized by removing idle threads before launching kernel for next level. With this approach, index for threads to access elements in array must be recalculated properly. + * Block size
+ * __Observation__ As block size increases, time consumed to perform scan decreases and at some point stablizes. The reason is the analyzed in last project. From ac2339b46287031448d8f196fbaf2a942d16c7fe Mon Sep 17 00:00:00 2001 From: Liang Peng Date: Tue, 27 Sep 2016 23:52:54 -0400 Subject: [PATCH 15/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a65e66b..e37c172 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,4 @@ print t.count();
* Block size
- * __Observation__ As block size increases, time consumed to perform scan decreases and at some point stablizes. The reason is the analyzed in last project. + * _Observation_ As block size increases, time consumed to perform scan decreases and at some point stablizes. The reason is the analyzed in last project.