From ebbaf3d9ac31ceefd0cfe2039aa84e0d8a2a7948 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Thu, 12 Sep 2019 21:21:42 -0400 Subject: [PATCH 01/16] Implemented CPU part --- .../stream_compaction/CMakeLists.txt | 2 +- .../stream_compaction/cpu.cu | 52 +++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt b/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt index cdbef77..4bb0dc2 100644 --- a/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt +++ b/Project2-Stream-Compaction/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_61 ) diff --git a/Project2-Stream-Compaction/stream_compaction/cpu.cu b/Project2-Stream-Compaction/stream_compaction/cpu.cu index a2d3e6c..85e1dbe 100644 --- a/Project2-Stream-Compaction/stream_compaction/cpu.cu +++ b/Project2-Stream-Compaction/stream_compaction/cpu.cu @@ -6,11 +6,11 @@ namespace StreamCompaction { namespace CPU { using StreamCompaction::Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } /** * CPU scan (prefix sum). @@ -18,9 +18,20 @@ namespace StreamCompaction { * (Optional) For better understanding before starting moving to GPU, you can simulate your GPU scan in this function first. */ void scan(int n, int *odata, const int *idata) { - timer().startCpuTimer(); - // TODO - timer().endCpuTimer(); + bool timer_started = false; + try { + timer().startCpuTimer(); + } + catch (const std::exception& e) { + timer_started = true; + } + odata[0] = 0; + for (int i = 1; i < n; i++) { + odata[i] = odata[i - 1] + idata[i-1]; + } + if (timer_started == false) { + timer().endCpuTimer(); + } } /** @@ -30,9 +41,16 @@ namespace StreamCompaction { */ int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); + int count = 0; + for (int i = 0; i < n; i++) { + if (idata[i] != 0) { + odata[count] = idata[i]; + count++; + } + } // TODO timer().endCpuTimer(); - return -1; + return count; } /** @@ -42,9 +60,21 @@ namespace StreamCompaction { */ int compactWithScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + int *scanned = new int[n]; + int *mask = new int[n]; + for (int i = 0; i < n; i++) { + mask[i] = idata[i] == 0 ? 0: 1; + } + scan(n, scanned, mask); + int length = 0; + for (int i = 0; i < n; i++) { + if (idata[i] != 0) { + odata[scanned[i]] = idata[i]; + length = scanned[i]; + } + } timer().endCpuTimer(); - return -1; + return length+1; } } } From e3e5a47adc64330912afb99245b2d00e3d067181 Mon Sep 17 00:00:00 2001 From: PEYMAN NOROUZI Date: Fri, 13 Sep 2019 16:49:46 -0400 Subject: [PATCH 02/16] Small Changes --- .../stream_compaction/naive.cu | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index 4308876..4fc5a3c 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -11,13 +11,30 @@ namespace StreamCompaction { static PerformanceTimer timer; return timer; } + int *dev_idata; + int *dev_odata; + // TODO: __global__ + __global__ void scan_GPU(int N, int *Dev_idata, int *Dev_odata) { + + } + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { timer().startGpuTimer(); + int blockSize = 32; + cudaMalloc((void**)&dev_idata, n * sizeof(int)); + cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + + cudaMalloc((void**)&dev_odata, n * sizeof(int)); + cudaMemcpy(dev_odata, odata, sizeof(int) * n, cudaMemcpyHostToDevice); + + dim3 fullBlocksPerGrid((n + blockSize - 1) / blockSize); + + scan_GPU << > > (n, dev_idata, dev_odata); // TODO timer().endGpuTimer(); } From 36b1c9f172964384c8f31e8c3b46f647bc470c28 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Fri, 13 Sep 2019 20:59:11 -0400 Subject: [PATCH 03/16] completed Naive Scan --- .../stream_compaction/naive.cu | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index 4fc5a3c..1c8b35b 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -1,8 +1,10 @@ #include #include +#include "device_launch_parameters.h" #include "common.h" #include "naive.h" + namespace StreamCompaction { namespace Naive { using StreamCompaction::Common::PerformanceTimer; @@ -14,18 +16,44 @@ namespace StreamCompaction { int *dev_idata; int *dev_odata; + void printArray(int n, int *a, bool abridged = false) { + printf(" [ "); + for (int i = 0; i < n; i++) { + if (abridged && i + 2 == 15 && n > 16) { + i = n - 2; + printf("... "); + } + printf("%3d ", a[i]); + } + printf("]\n"); + } + // TODO: __global__ - __global__ void scan_GPU(int N, int *Dev_idata, int *Dev_odata) { + __global__ void scan_GPU(int N, int *Dev_idata, int *Dev_odata, int d) { - } + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= N) { + return; + } + + + + if (index >= (1 << (d - 1))) { + Dev_odata[index] = Dev_idata[index - (1 << (d - 1))] + Dev_idata[index]; + } + else { + Dev_odata[index] = Dev_idata[index]; + } + } /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { timer().startGpuTimer(); int blockSize = 32; + //printArray(n, idata); cudaMalloc((void**)&dev_idata, n * sizeof(int)); cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); @@ -33,10 +61,16 @@ namespace StreamCompaction { cudaMemcpy(dev_odata, odata, sizeof(int) * n, cudaMemcpyHostToDevice); dim3 fullBlocksPerGrid((n + blockSize - 1) / blockSize); - - scan_GPU << > > (n, dev_idata, dev_odata); - // TODO + for (int d = 1; d <= ilog2ceil(n); d++) { + scan_GPU << > > (n, dev_idata, dev_odata, d); + cudaMemcpy(dev_idata, dev_odata, sizeof(int) * n, cudaMemcpyDeviceToDevice); + } + cudaMemcpy(odata+1, dev_odata, sizeof(int) * (n-1), cudaMemcpyDeviceToHost); + odata[0] = 0; + //printArray(n, odata); timer().endGpuTimer(); + cudaFree(dev_odata); + cudaFree(dev_odata); } } } From 9561d9367cc6b4fcd6045f64da96d8d654bd6220 Mon Sep 17 00:00:00 2001 From: PEYMAN NOROUZI Date: Sun, 15 Sep 2019 18:32:52 -0400 Subject: [PATCH 04/16] Implemented Efficient Scan --- Project2-Stream-Compaction/src/main.cpp | 2 +- .../stream_compaction/efficient.cu | 113 ++++++++++++++++-- .../stream_compaction/naive.cu | 14 ++- 3 files changed, 118 insertions(+), 11 deletions(-) diff --git a/Project2-Stream-Compaction/src/main.cpp b/Project2-Stream-Compaction/src/main.cpp index d016553..f64d9e4 100644 --- a/Project2-Stream-Compaction/src/main.cpp +++ b/Project2-Stream-Compaction/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 << 9; // 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/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index 2db346e..6df5e3b 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -11,15 +11,114 @@ namespace StreamCompaction { static PerformanceTimer timer; return timer; } - + int *dev_odata; /** * 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 printArray(int n, int *a, bool abridged = false) { + printf(" [ "); + for (int i = 0; i < n; i++) { + if (abridged && i + 2 == 15 && n > 16) { + i = n - 2; + printf("... "); + } + printf("%3d ", a[i]); + } + printf("]\n"); + } + + __global__ void up_sweep(int N, int *Dev_odata, int d) { + + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + index = index * (1 << (d + 1)); + + if (index > N-1) { + return; + } + + if (((index + (1 << (d)) - 1) < N) && ((index + (1 << (d + 1)) - 1) < N)) { + + Dev_odata[index + (1 << (d + 1)) - 1] += Dev_odata[index + (1 << (d)) - 1]; + } + + + + } + + + __global__ void down_sweep(int N, int *Dev_odata, int d) { + + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + + index = index * (1 << (d + 1)); + + + if (index > N-1) { + return; + } + + + if (((index + (1 << (d)) - 1) < N) && ((index + (1 << (d + 1)) - 1) < N)) { + + int t = Dev_odata[index + (1 << (d)) - 1]; + Dev_odata[index + (1 << (d)) - 1] = Dev_odata[index + (1 << (d + 1)) - 1]; + Dev_odata[index + (1 << (d + 1)) - 1] += t; + } + + + } + /** + * Performs prefix-sum (aka scan) on idata, storing the result into odata. + */ + void scan(int n, int *odata, const int *idata) { + + + bool timer_started = false; + try { + timer().startGpuTimer(); + } + catch (const std::exception& e) { + timer_started = true; + } + + int blockSize = 32; + //printArray(n, idata); + //int new_n = n; + n = 1 << ilog2ceil(n); // make n something that is power of 2 + + cudaMalloc((void**)&dev_odata, n * sizeof(int)); + cudaMemcpy(dev_odata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + + + + for (int d = 0; d <= ((ilog2ceil(n)) - 1); d++) { + int count_thread = 1 << ((ilog2ceil(n) - d - 1)); // i need ceil(n/d) threads total + dim3 fullBlocksPerGrid(((count_thread)+blockSize -1)/ blockSize); + up_sweep << > > (n, dev_odata, d); + } + + cudaMemset(n + dev_odata - 1, 0, sizeof(int)); + + for (int d = ilog2ceil(n) - 1; d >= 0; d--) { + int count_thread = 1 << ((ilog2ceil(n) - d - 1)); // i need ceil(n/d) threads total + dim3 fullBlocksPerGrid(((count_thread)+blockSize - 1) / blockSize); + down_sweep << > > (n, dev_odata, d); + } + + + cudaMemcpy(odata, dev_odata, sizeof(int) * (n), cudaMemcpyDeviceToHost); + //cudaMemcpy(dev_odata, dev_idata, sizeof(int) * n, cudaMemcpyDeviceToDevice); + //odata[0] = 0; + //printArray(n, odata); + if (timer_started == false) { + timer().endGpuTimer(); + } + cudaFree(dev_odata); + + } /** * Performs stream compaction on idata, storing the result into odata. @@ -27,7 +126,7 @@ namespace StreamCompaction { * * @param n The number of elements in idata. * @param odata The array into which to store elements. - * @param idata The array of elements to compact. + * @param idata The array of elements to compact. * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index 1c8b35b..a78b783 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -51,7 +51,13 @@ namespace StreamCompaction { * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); + bool timer_started = false; + try { + timer().startGpuTimer(); + } + catch (const std::exception& e) { + timer_started = true; + } int blockSize = 32; //printArray(n, idata); cudaMalloc((void**)&dev_idata, n * sizeof(int)); @@ -68,9 +74,11 @@ namespace StreamCompaction { cudaMemcpy(odata+1, dev_odata, sizeof(int) * (n-1), cudaMemcpyDeviceToHost); odata[0] = 0; //printArray(n, odata); - timer().endGpuTimer(); - cudaFree(dev_odata); + if (timer_started == false) { + timer().endGpuTimer(); + } cudaFree(dev_odata); + cudaFree(dev_idata); } } } From c0f1f5289e646cfd1ea66ab42a5f4e68c86a7cdd Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Sun, 15 Sep 2019 20:04:04 -0400 Subject: [PATCH 05/16] Completed Efficient StreamCompaction --- .../stream_compaction/common.cu | 24 +++++++- .../stream_compaction/efficient.cu | 55 +++++++++++++++++-- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/Project2-Stream-Compaction/stream_compaction/common.cu b/Project2-Stream-Compaction/stream_compaction/common.cu index 2ed6d63..f8adceb 100644 --- a/Project2-Stream-Compaction/stream_compaction/common.cu +++ b/Project2-Stream-Compaction/stream_compaction/common.cu @@ -22,7 +22,19 @@ namespace StreamCompaction { * Maps an array to an array of 0s and 1s for stream compaction. Elements * which map to 0 will be removed, and elements which map to 1 will be kept. */ - __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { + __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + if (index >= n) { + return; + } + + if (idata[index] == 0) { + bools[index] = 0; + } + else { + bools[index] = 1; + } // TODO } @@ -32,6 +44,16 @@ namespace StreamCompaction { */ __global__ void kernScatter(int n, int *odata, const int *idata, const int *bools, const int *indices) { + + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + if (index >= n) { + return; + } + + if (bools[index] == 1) { + odata[indices[index]] = idata[index]; + } // TODO } diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index 6df5e3b..8186c5a 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -2,7 +2,7 @@ #include #include "common.h" #include "efficient.h" - +#define blockSize 32 namespace StreamCompaction { namespace Efficient { using StreamCompaction::Common::PerformanceTimer; @@ -11,7 +11,10 @@ namespace StreamCompaction { static PerformanceTimer timer; return timer; } + + int *dev_odata; + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ @@ -74,7 +77,7 @@ namespace StreamCompaction { * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { - + bool timer_started = false; try { @@ -84,7 +87,6 @@ namespace StreamCompaction { timer_started = true; } - int blockSize = 32; //printArray(n, idata); //int new_n = n; n = 1 << ilog2ceil(n); // make n something that is power of 2 @@ -131,9 +133,54 @@ namespace StreamCompaction { */ int compact(int n, int *odata, const int *idata) { timer().startGpuTimer(); + int *dev_mask; + int *dev_idata; + int *temp_dev_odata; + + int count; + + cudaMalloc((void**)&dev_mask, n * sizeof(int)); + cudaMalloc((void**)&dev_idata, n * sizeof(int)); + cudaMalloc((void**)&temp_dev_odata, n * sizeof(int)); + + cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); + + dim3 fullBlocksPerGrid((n+blockSize - 1) / blockSize); + + StreamCompaction::Common::kernMapToBoolean << > > (n, dev_mask, dev_idata); + + int *temp_idata = new int[n]; + + + + cudaMemcpy(temp_idata, dev_mask, n * sizeof(int), cudaMemcpyDeviceToHost); + + //printArray(n, temp_idata); + + scan(n, odata, temp_idata); + + + if (temp_idata[n - 1] == 0) { + count = odata[n - 1]; + } + else { + count = odata[n - 1] + 1; + } + + //cudaMemcpy(mask_scan, temp_odata, n * sizeof(int), cudaMemcpyHostToDevice); + + StreamCompaction::Common::kernScatter << > > (n, temp_dev_odata, dev_idata, dev_mask, dev_odata); + + cudaMemcpy(odata, temp_dev_odata, n * sizeof(int), cudaMemcpyDeviceToHost); + // TODO timer().endGpuTimer(); - return -1; + + cudaFree(dev_mask); + cudaFree(dev_idata); + cudaFree(temp_dev_odata); + + return count; } } } From 339fb8d28ed676b2f83399779cb8836466f58619 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Sun, 15 Sep 2019 20:22:13 -0400 Subject: [PATCH 06/16] Finished First Half of Assignment --- .../stream_compaction/thrust.cu | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Project2-Stream-Compaction/stream_compaction/thrust.cu b/Project2-Stream-Compaction/stream_compaction/thrust.cu index 1def45e..0a25ed0 100644 --- a/Project2-Stream-Compaction/stream_compaction/thrust.cu +++ b/Project2-Stream-Compaction/stream_compaction/thrust.cu @@ -19,6 +19,17 @@ namespace StreamCompaction { */ void scan(int n, int *odata, const int *idata) { timer().startGpuTimer(); + + thrust::host_vectorh_idata(idata, idata + n); + thrust::device_vectordev_idata(n); + thrust::device_vectordev_odata(n); + + + thrust::copy(h_idata.begin(), h_idata.end(), dev_idata.begin()); + + thrust::exclusive_scan(dev_idata.begin(), dev_idata.end(), dev_odata.begin()); + + thrust::copy(dev_odata.begin(), dev_odata.end(), odata); // 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()); From e68b429d0b0f0ffe457d2e58bd8777a111422edc Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Tue, 17 Sep 2019 18:38:48 -0400 Subject: [PATCH 07/16] Did some MLP --- .../character_recognition/mlp.cu | 198 +++++++++++++++++- Project2-Stream-Compaction/src/main.cpp | 6 +- .../stream_compaction/efficient.cu | 35 ++-- .../stream_compaction/naive.cu | 26 ++- .../stream_compaction/thrust.cu | 8 +- 5 files changed, 241 insertions(+), 32 deletions(-) diff --git a/Project2-Character-Recognition/character_recognition/mlp.cu b/Project2-Character-Recognition/character_recognition/mlp.cu index 5a3ed7f..3ca3120 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.cu +++ b/Project2-Character-Recognition/character_recognition/mlp.cu @@ -2,6 +2,14 @@ #include #include "common.h" #include "mlp.h" +#include + +#define num_examples 4 +#define num_input_chanels 2 +#define num_hidden_channels 2 +#define num_out_channels 2 +#define batch_size 1 + namespace CharacterRecognition { using Common::PerformanceTimer; @@ -10,7 +18,195 @@ namespace CharacterRecognition { static PerformanceTimer timer; return timer; } - + + + float *inp = new float[batch_size*num_input_chanels]; + float *dev_inp; + + float *target = new float[batch_size*num_out_channels]; + float *dev_target; + + + float *w1 = new float[num_input_chanels*num_hidden_channels]; + float *dev_w1; + + float *dev_a1_B_relu; + float *dev_a1_A_relu; + + float *w2 = new float[num_hidden_channels * num_out_channels]; + float *dev_w2; + + float *dev_out_B_soft; + float *dev_out_A_soft; + + float *dev_dw1; + float *dev_dw2; + + + float initweight(int n, float *w) { + + for (int i = 0; i < n; i++) { + w[i] = ((2* rand()/RAND_MAX)-1) * 0.002; + } + + return *w; + } + + //int in = num_hidden_channels + w1 = initweight(num_input_chanels * num_hidden_channels, w1); + w2 = initweight(num_hidden_channels * num_out_channels, w2); + + //cudaMemset(dataGPU, 0, 1000 * sizeof(float)); + + //cudaMalloc((void**)&dev_odata, n * sizeof(int)); + //cudaMemcpy(dev_odata, odata, sizeof(int) * n, cudaMemcpyHostToDevice); + + void initialize() { + + cudaMalloc((void**)&dev_inp, batch_size * num_input_chanels * sizeof(float)); + cudaMemcpy(dev_inp, inp, batch_size * num_input_chanels * sizeof(float), cudaMemcpyHostToDevice); + + cudaMalloc((void**)&dev_target, batch_size * num_out_channels * sizeof(float)); + cudaMemcpy(dev_target, target, batch_size * num_out_channels * sizeof(float), cudaMemcpyHostToDevice); + + cudaMalloc((void**)&dev_w1, num_input_chanels*num_hidden_channels * sizeof(float)); + cudaMemcpy(dev_w1, w1, num_input_chanels*num_hidden_channels * sizeof(float), cudaMemcpyHostToDevice); + + cudaMalloc((void**)&dev_w2, num_hidden_channels * num_out_channels * sizeof(float)); + cudaMemcpy(dev_w2, w2, num_hidden_channels * num_out_channels * sizeof(float), cudaMemcpyHostToDevice); + + cudaMalloc((void**)&dev_a1_B_relu, batch_size * num_hidden_channels * sizeof(float)); + cudaMalloc((void**)&dev_a1_A_relu, batch_size * num_hidden_channels * sizeof(float)); + + cudaMalloc((void**)&dev_out_B_soft, batch_size * num_out_channels * sizeof(float)); + cudaMalloc((void**)&dev_out_A_soft, batch_size * num_out_channels * sizeof(float)); + + cudaMalloc((void**)&dev_dw1, num_input_chanels * num_hidden_channels * sizeof(float)); + cudaMalloc((void**)&dev_dw2, num_hidden_channels * num_out_channels * sizeof(float)); + // random initializes w1,w2 and the rest to zeros + } + + + + __global__ void addVectors(float *vec1, float *vec2, float *result) { + + int index = blockIdx.x * blockDim.x + threadIdx.x; + result[index] = vec1[index] + vec2[index]; + } + + + __global__ void linearForward(float* W, float* A, float* Z, float* b, + int W_x_dim, int W_y_dim, + int A_x_dim, int A_y_dim) { + int row = blockIdx.y * blockDim.y + threadIdx.y; + int col = blockIdx.x * blockDim.x + threadIdx.x; + + int Z_x_dim = A_x_dim; + int Z_y_dim = W_y_dim; + + float Z_value = 0; + + if (row < Z_y_dim && col < Z_x_dim) { + for (int i = 0; i < W_x_dim; i++) { + Z_value += W[row * W_x_dim + i] * A[i * A_x_dim + col]; + } + Z[row * Z_x_dim + col] = Z_value + b[row]; + } + } + + __global__ void linearBackprop(float* W, float* dZ, float *dA, + int W_x_dim, int W_y_dim, + int dZ_x_dim, int dZ_y_dim) { + + int col = blockIdx.x * blockDim.x + threadIdx.x; + int row = blockIdx.y * blockDim.y + threadIdx.y; + + // W is treated as transposed + int dA_x_dim = dZ_x_dim; + int dA_y_dim = W_x_dim; + + float dA_value = 0.0f; + + if (row < dA_y_dim && col < dA_x_dim) { + for (int i = 0; i < W_y_dim; i++) { + dA_value += W[i * W_x_dim + row] * dZ[i * dZ_x_dim + col]; + } + dA[row * dA_x_dim + col] = dA_value; + } + } + + + __global__ void reluActivationForward(float *Z, float *A, int n) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index < n) { + A[index] = fmaxf(Z[index], 0); + } + } + + __global__ void reluActivationBackprop(int n ,float *Z, float *dA, float *dZ) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index < n) { + if (Z[index] > 0) { + dZ[index] = dA[index]; + } + else { + dZ[index] = 0; + } + } + } + + __device__ float sigmoid(float x) { + return 1.0f / (1 + exp(-x)); + } + + __global__ void sigmoidActivationForward(int n, float* Z, float* A) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index < n) { + A[index] = sigmoid(Z[index]); + } + } + + __global__ void sigmoidActivationBackprop(int n, float *Z, float *dA, float *dZ) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index < n) { + dZ[index] = dA[index] * sigmoid(Z[index]) * (1 - sigmoid(Z[index])); + } + } + + + __global__ void BCELoss(int n,float *preds, float *target, float *loss) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index < n) { + float partial_cost = target[index] * logf(preds[index]) + + (1.0f - target[index]) * logf(1.0f - preds[index]); + atomicAdd(loss, -partial_cost / n); + } + } + + __global__ void dBCELoss(int n ,float *preds, float *target, float* dY) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + + if (index < n) { + dY[index] = -1.0 * (target[index] / preds[index] - (1 - target[index]) / (1 - preds[index])); + } + } + + __global__ void ElementWiseMultiplication(int n, float *input1, float *input2, float *output) { + int index = blockIdx.x * blockDim.x + threadIdx.x; + if (index #include "testing_helpers.hpp" -const int SIZE = 1 << 9; // 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]; @@ -137,14 +137,14 @@ int main(int argc, char* argv[]) { printDesc("work-efficient compact, power-of-two"); count = StreamCompaction::Efficient::compact(SIZE, c, a); printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); + printArray(count, c, true); printCmpLenResult(count, expectedCount, b, c); zeroArray(SIZE, c); printDesc("work-efficient compact, non-power-of-two"); count = StreamCompaction::Efficient::compact(NPOT, c, a); printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); + printArray(count, c, true); printCmpLenResult(count, expectedNPOT, b, c); system("pause"); // stop Win32 console from closing on exit diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index 8186c5a..b48b8b9 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -2,7 +2,7 @@ #include #include "common.h" #include "efficient.h" -#define blockSize 32 +#define blockSize 256 namespace StreamCompaction { namespace Efficient { using StreamCompaction::Common::PerformanceTimer; @@ -79,13 +79,7 @@ namespace StreamCompaction { void scan(int n, int *odata, const int *idata) { - bool timer_started = false; - try { - timer().startGpuTimer(); - } - catch (const std::exception& e) { - timer_started = true; - } + //printArray(n, idata); //int new_n = n; @@ -94,7 +88,13 @@ namespace StreamCompaction { cudaMalloc((void**)&dev_odata, n * sizeof(int)); cudaMemcpy(dev_odata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); - + bool timer_started = false; + try { + timer().startGpuTimer(); + } + catch (const std::exception& e) { + timer_started = true; + } for (int d = 0; d <= ((ilog2ceil(n)) - 1); d++) { int count_thread = 1 << ((ilog2ceil(n) - d - 1)); // i need ceil(n/d) threads total @@ -110,14 +110,15 @@ namespace StreamCompaction { down_sweep << > > (n, dev_odata, d); } - + if (timer_started == false) { + timer().endGpuTimer(); + } + cudaMemcpy(odata, dev_odata, sizeof(int) * (n), cudaMemcpyDeviceToHost); //cudaMemcpy(dev_odata, dev_idata, sizeof(int) * n, cudaMemcpyDeviceToDevice); //odata[0] = 0; //printArray(n, odata); - if (timer_started == false) { - timer().endGpuTimer(); - } + cudaFree(dev_odata); } @@ -132,7 +133,7 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { - timer().startGpuTimer(); + int *dev_mask; int *dev_idata; int *temp_dev_odata; @@ -144,7 +145,8 @@ namespace StreamCompaction { cudaMalloc((void**)&temp_dev_odata, n * sizeof(int)); cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); - + + timer().startGpuTimer(); dim3 fullBlocksPerGrid((n+blockSize - 1) / blockSize); StreamCompaction::Common::kernMapToBoolean << > > (n, dev_mask, dev_idata); @@ -171,10 +173,11 @@ namespace StreamCompaction { StreamCompaction::Common::kernScatter << > > (n, temp_dev_odata, dev_idata, dev_mask, dev_odata); + timer().endGpuTimer(); + cudaMemcpy(odata, temp_dev_odata, n * sizeof(int), cudaMemcpyDeviceToHost); // TODO - timer().endGpuTimer(); cudaFree(dev_mask); cudaFree(dev_idata); diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index a78b783..a04a2cc 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -4,6 +4,8 @@ #include "common.h" #include "naive.h" +#define blockSize 512 + namespace StreamCompaction { namespace Naive { @@ -52,13 +54,7 @@ namespace StreamCompaction { */ void scan(int n, int *odata, const int *idata) { bool timer_started = false; - try { - timer().startGpuTimer(); - } - catch (const std::exception& e) { - timer_started = true; - } - int blockSize = 32; + //printArray(n, idata); cudaMalloc((void**)&dev_idata, n * sizeof(int)); cudaMemcpy(dev_idata, idata, sizeof(int) * n, cudaMemcpyHostToDevice); @@ -66,17 +62,27 @@ namespace StreamCompaction { cudaMalloc((void**)&dev_odata, n * sizeof(int)); cudaMemcpy(dev_odata, odata, sizeof(int) * n, cudaMemcpyHostToDevice); + try { + timer().startGpuTimer(); + } + catch (const std::exception& e) { + timer_started = true; + } + dim3 fullBlocksPerGrid((n + blockSize - 1) / blockSize); + + for (int d = 1; d <= ilog2ceil(n); d++) { scan_GPU << > > (n, dev_idata, dev_odata, d); cudaMemcpy(dev_idata, dev_odata, sizeof(int) * n, cudaMemcpyDeviceToDevice); } - cudaMemcpy(odata+1, dev_odata, sizeof(int) * (n-1), cudaMemcpyDeviceToHost); - odata[0] = 0; - //printArray(n, odata); + if (timer_started == false) { timer().endGpuTimer(); } + cudaMemcpy(odata+1, dev_odata, sizeof(int) * (n-1), cudaMemcpyDeviceToHost); + odata[0] = 0; + //printArray(n, odata); cudaFree(dev_odata); cudaFree(dev_idata); } diff --git a/Project2-Stream-Compaction/stream_compaction/thrust.cu b/Project2-Stream-Compaction/stream_compaction/thrust.cu index 0a25ed0..74efd41 100644 --- a/Project2-Stream-Compaction/stream_compaction/thrust.cu +++ b/Project2-Stream-Compaction/stream_compaction/thrust.cu @@ -18,22 +18,26 @@ namespace StreamCompaction { * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); + thrust::host_vectorh_idata(idata, idata + n); thrust::device_vectordev_idata(n); thrust::device_vectordev_odata(n); + timer().startGpuTimer(); thrust::copy(h_idata.begin(), h_idata.end(), dev_idata.begin()); thrust::exclusive_scan(dev_idata.begin(), dev_idata.end(), dev_odata.begin()); + thrust::copy(dev_odata.begin(), dev_odata.end(), odata); + + timer().endGpuTimer(); // TODO use `thrust::exclusive_scan` // example: for device_vectors dv_in and dv_out: // thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); - timer().endGpuTimer(); + } } } From 2e30148ee26474a3402e2f62b4d8db0f88402724 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Tue, 17 Sep 2019 19:06:46 -0400 Subject: [PATCH 08/16] Performance Analysis --- .../Performance Plots.xlsx | Bin 0 -> 10152 bytes .../stream_compaction/thrust.cu | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 Project2-Stream-Compaction/Performance Plots.xlsx diff --git a/Project2-Stream-Compaction/Performance Plots.xlsx b/Project2-Stream-Compaction/Performance Plots.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..14c9254c4a7e9c825aebb30a5528f88eab0e0f7c GIT binary patch literal 10152 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 thrust::device_vectordev_odata(n); - timer().startGpuTimer(); + thrust::copy(h_idata.begin(), h_idata.end(), dev_idata.begin()); - + timer().startGpuTimer(); thrust::exclusive_scan(dev_idata.begin(), dev_idata.end(), dev_odata.begin()); - + timer().endGpuTimer(); thrust::copy(dev_odata.begin(), dev_odata.end(), odata); - timer().endGpuTimer(); + // 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()); From 99590b266c3ada793bf416e63c52fb9cb4c1c980 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Tue, 17 Sep 2019 22:37:50 -0400 Subject: [PATCH 09/16] pictures --- .../Performance Plots.xlsx | Bin 10152 -> 25392 bytes Project2-Stream-Compaction/img/Compaction.PNG | Bin 0 -> 22542 bytes Project2-Stream-Compaction/img/Scan_2.PNG | Bin 0 -> 22303 bytes Project2-Stream-Compaction/img/Scan_N2.PNG | Bin 0 -> 20199 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Project2-Stream-Compaction/img/Compaction.PNG create mode 100644 Project2-Stream-Compaction/img/Scan_2.PNG create mode 100644 Project2-Stream-Compaction/img/Scan_N2.PNG diff --git a/Project2-Stream-Compaction/Performance Plots.xlsx b/Project2-Stream-Compaction/Performance Plots.xlsx index 14c9254c4a7e9c825aebb30a5528f88eab0e0f7c..5c399c1486697599193f9c96d8ec3aab97516f53 100644 GIT binary patch delta 18375 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 aqlsKW8vLWt8VCscGs(QYSM2 delta 3530 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 Z8tjcRGh+S2IRF61pVRioaYFK6^*^z?Z6*K! diff --git a/Project2-Stream-Compaction/img/Compaction.PNG b/Project2-Stream-Compaction/img/Compaction.PNG new file mode 100644 index 0000000000000000000000000000000000000000..9c340e2700d196623152e4afeff446826446778e GIT binary patch literal 22542 zcmd>mby$?`)-T=Njg+9YNOuW>5`usdL#UwC5E9beASxg&poG*QHFSs6fFKM#LnGZW z44emj_q+H0_V-=qe1D(0E`^7g=ec9mZ~fN2CQ467gOrGg2m=Fy^uDIrBMb~ILJSPd zdjxpEUl5@rGr$i_w?`T(7-d5&>%aw$t@1-<42+5d;tMNW;F=Ju`NRzagRJBFA7+np z;WG>jj*#E%#at%LJ!czjFISt9-CrLU zx1(CNYNqv!jZ>y%p>T2Yo(*#M`bD%_Iag>eSyZSM8S#ppvX=3qNALDWOmke>iT70s z^70nt7jFFO>+5@@5EJ7L6QSn}${nk&+h9ltq9XE5rW49W>CI+SbcL$5i-d<&(B=w2 z35g9Z3%o>TRGNlw2@3kbHxTtQWg9e(L~nn;BS^7;K)D0BkhU+b5;HAn(0Jq39o!^To~ zde9dGy9<^Vi)q}@`8oevcO269MB2I>w^v=Lc{(o+*u2Th6en~Vowq9&-D3j|W&vuLLNdLZXNqy zoU`or7R%G`ZM~t>Am$o9plny?v|{K84#th3WfO474b#Xc3J>GBGR0hCbK@tS7%4aJ zATrIiL27O?t(zTAxsPB?SXw#yo9xj|smYW|KpEO|j>wCTkg1r?|!H;J1st|&j9vA}2kv01Ey zFj|-u@)<21@dJLAy7@Ve&B5rN)A_kH@8+|L;Nhn5uKrSrEv6Y*a02QFZQ!<_Nuw_m zX)4FiY?EaNo75P#JTn4+q+Mce-J3%(Qs7KXoq|QHh$mir$10&^sqnNs# z39lZlD$4FuFnzUdgM-k{)zJAmr#Plq1T>vo{25Y3b7 z6=1v#?clSxIewQGZoRS7A+8a>noL~~)y!%A=a`rnW}ST40$sAbeTOG&jGF|AD);Zv zK_}-oBYlx)?a^}yjy-<&dq0eaMXLU`r9|8)l=M$Qfzo$iVqQ82BfAFNJmQW@w9}U^ z^o4)}@*Y~G(N6utHd77kBGHcHR|k=f>;%!P?kHTz^40G7_5wvz-vV9V3QTZdi^(Zx zXD;GQJb(mtTn92{;60J6Oh?6T%GrO*5vg2N4KPxM)_gxC@gAu0qh-wO>R51=;B@k$ ztL1YtSqCq+`9QqjZr|?OSk=`?_)fT>!c8vhh*3{FAaR9?9iD^kCyo+#T5238kkwn0 zb$?a^Xr^4as_bM_{d$bY(nPEjrf?`nqDZU@e|n+Yyn+crErGh$GS(V58>Y_Bm|dwN zJS(1isaZvF)MlSfu_w*{K&)$C#)4{km2SlY^k@Eq?pGc{#7EqFulY$Po;?3BDCW-p zqtI|iib67ZS{4!#IeQ&z1#eRu>mex>ssOSjVKM8RCQKO6nZjn z3U@gfOdW2K=bB?iPuG>nZ)wMcb!=4TihT19r%@Skw}N#-q@W%Lv$h{T!=i?r@3NI? zRz{CjS0`@ER1rEl)F6am3EdNAjI%q}3Y(u@2s)A8^%uxGeh?`PEX3q#&F)8wbr|Ao z#AmrCT`06SR4tf7y8ZT~-7;+Q4vl8LBDes2;Y&It+!p>LJt-X6#4H@!>&dgJLvJEs0p{vskS%cW}G)j z)c9YvGqMi`)Y~_hoUZhk+Xuo)-nrkzFuSUmKhm(30B@<-ia5n8!j}C{*up46Vt_Sa zWAKaCF5J9HRdT0VYk1a!-}$5km7jT^TSVYMW5$LACNE3`t0tPDzv3g|X95)?O7|sa zY(`Mr+i1!L4O6eky>GjlA2&b*qIZFP5ygPgmRWJO-EMZDR`5;w+;(M@(}1Kj`s~!@ zOj}JZIn;cr;Zm->HhJyBby=zjV=p~4_f3*3w?EPF^^bkf6Z&Vf(4Dt^+>D;Qpu%l-G)i+~xUYs~)#bQa z*YhqKCnloKJxM-6w9)-?<}@ADvA|Frw*ezf7n=RYc>hmYa*gx;XC3-qznjuXN%-Z< z7Y0#lwY7Ym%(N*$msKLo66rZ}%F2Xj2#>Q>lz|Z`>Ueh2m;nGM;=0s3mVB+ruId&N zlDqc7zkk=B^ScjO!6U>4KFV3Ul&N{+;w!{!Z(+>n&eyMB!E3`D($}xLT(^f09~MnH z*?lKYR8mGnWBK2=oDX$?L#$MPWozP7r$uUbL~BTBg>TX%IDCjTo4n=R%xw~YQ}58i zNf8z5^?~s{hin%YGmq-;kKHTV{E#w8>Zi=f!S=lSS+CAs@4fGDGZzx$-X-$O-sdLa z`p+A<0pF8ALhV4GMG~ZuzCu*Vm`_tlx`gNtJoW^52T#?iyzhRv>5Fr2)?FMA)<+ zC7uu!;U1sZ%|C+rTb?g_)0z43xT#!2?%4db&3~lUo0J)D$o(NH$-67i&q~A=#P;pK zN_9OZPA6L-E>9!jIz2I|bz)tCWhV%l)_jhq zI7B$}h2id}GLqdKi4+M$C4Xz=1#}R%KSj7F7?-%w+H$<)36egTRo3HEO%2`F))v(F z%=PvMr20rSjz1+B#XPJpVxow1c@O;zMH{5a-I<5Q|CeHhH)NKX)dk1L#}AV&FE5+a zx$?Y#Wo^;oY#Kv6wx%H7$lgS*wO_xq!Z`ah@kgJ- zSAw^uYv&z=5EHocU%vc@mGHUCR;bu^4WTSsFpN%1PW^%d2XR^AHIZ*0x&{4sbjS5M zFOVjN{w;o*cbQTupX%zQ9k477Fw${+tpkN*>H{B=`l-LX^&ghGKcXY)G}BsSP%u0^ zOyNQG%(l(@V8y!&qlF1l$$=u>weTIpMgMnqx;hqQWwBLNSBJf)a-6Oq6qG=XnJdSr37WZ+ZlLf;?Qt9`7_6?)`0b_ar=I+*TgI=`DBWnylsn z!-(nMbYZZf=pYH0C?*y~f0h&>bFHvPUjNO#;V>ODpTImEsXD!x8Elrqufjd{^Jmz#598aFWWF|=-(fDX9>&}Pdzv9?)8p4voTX-ffTXx%tt-_IgpcS})5)wS^SR2M^eZvykXz?%WRe?~_ z-&t_&x=(k<`m8G_a=O-;T$VaZ%EekqhWhqDrWs93SW>l!NWt;XVkY3DcxNUS{kMd^ zOEOo8aqu5=6EnJuwbj4gP(gy1dK2|DN$CE$S^0~cNMmCE(lufl!n?T{8D=iB{^zSe z9xkUr_nG;XX3rDiv#`L2cxKxlACfeSEH4qYEeCgU2K7gL`yRAQjGfM~1`W9JNolRW z5Kk3EwebBhC;wd_?uNJDGmDJO#CkGkVyi-S>o5v)Ugh4p3^f_g-(yq7;7DLXIC(cA zy%KWGN0quN0aj8H7Zv3lH+cRbG?>zKWCyOa!&`0o%95y!2fbmjr|Ln(jL)Z2!F>8p zuQA3oc=(xub4>p!tu{Wa4BRXJcf=}Cl(1&UIL5V1ZEwaTrW3e!6rLP;H8m24hlih4 zZjt;`Ha~fT21%V-Frz}-|H2RV9Xg3-WvIWAE9ZyB=4KMsy`|LPrIGo2`ukrOtpna_ zMr!)Yiq;D^h*BLtv)So2sR~(6VehW zjr#i5{vRs(fz1Q&S%H#{;s7JQ^uZ0=8^Er4++0$*$MU%KTZrnHNk$i`oT}f5s*#>> z0KqZ{21vd8+%$Z@mGMm-5EG$qDJM7)D)-FNTY)J+^D$+qUE{FJUVjRUee>6T&BfsO zvwc?THU2YhH@J$L|8?1;-k(HuuQ*oeccU<6h90&GXTkLd`$Rbm$BA0)bw{=IXjc@Bo1PfY>vLZxkS^Q(Fe`V#RA-6W)9{_&s+19uKC4+dbx^*q|iq5jvAENgUjHj}6;0dPHkBe^Jb ztd<*aZViVwB9eMyLdW!fV2r+=drQa@` z?~jskfi{Rw$Ow-=Thk+TDH|X8S|820JDWSgi{y<`q{7fmcx4=A4Z=@4TWn6oj zTsQIzc^?T{t!@2(8S1a76&v*Jw@~c{aZ3*UtOMh%gK~owf;c(n|I5tsG%cyIQ^HpI z64oI_Y3sr%e+k54>zM&9?@J+szXbg-JGwHpZH0}G`$O_O0Jpy{jf>B&i;eDfGpV`a zwwN1>My0T|k6nS_T>v)n2?5mnpcMe#SU4_mDRv1c)8L@n8DBC^p5Ae zmM1?CzN_W7e(_x88ljkc?|oL#{NV9`FyTdRYkXu^@E?);O4NhTWXNhkYENbv2WEc; z6^!3S&Yc~duGl|5Jumj>O%#!O_H(9Hn0V95(T#^YlPf4m0oD)1DNYizYwZq7BB^{Y zP7nTSonH;1%mVVHP6_&K$*OR9IAmsv$%IiU4}Dz3PY{j~K+r@Ozs_ z0DzuBTn8P<3YO>B1!U;;DtHmUs+sL%eul7W3|S+y$QmIzxI8gT06Y}8pj7gl{_rZ+ z98TfSY65A%p8f^930r^?ptLV#lE;zkalkxU=(2$&dn=k0!U&uC_{znCv6& z;YimG*w69taI}rdcehzAp=Te;>MV~pC#~GD(n+LLIbe%4Jz*ZLW#gE<0{0IvZ2G z7R%>~0e&ugfz@g@>5M_kPJq)U*qT@o^wtYos*=ac$4(d5tZ}JHQ$!g-6!MwViVp~Q zyxGLZVzxtwwUIm|ShdXTqZ2fzVN4YFg@#5?V7d7xB9ZG{T=gXYnCDs5A$Gd>S)h5U zc#2b7AdiFMLX448UXI>9B`IzJ~wi#$5QI(=u3k5-tpHh$9r**4O$Fe~b zrwouS&>3!E-Czq7LC_VMp&t(gR$freLJBfLKa1lBCvlq9PmErL0(`| z6Q2bFLRHP|ExE#w#dC!sqiOjY0ss6mrh}B6MJjM*<%PSaXMqain?J(MQ}nRr8S0bE zu;VM7dGfvI;a#-~z4~7!H`sJ6ZEkSR=;QdU;(3Ge%ZR(OLtJaJSIqpk7t$HW+J z>A(aJt}t&alHa|+vh$-{d&*1@WK#t80RjeqnrP&{Z(2ok`BLJC15*k~?UgdGIAXUH zGt9rlK2wm*Au7FQPdX=~Ku4y!CzcZ!2o@Q$rPjH3coCiq zd6IL{`{b_YQRpBkdf`XnCn^xF+FG3w!3BxbuCX%Dm8^2umFJu=hEqMl-!Hxry6D~sjLVh~y0N2m9~s|ny0Z`~-sLcy5nc9Gc!y5;!sEi8t= zT5!nxDd9&Att(d@To^1p*8riloZuo2{7M>}BS8SUVr5K9zGj(TtTZ--Z1wOW2s;b)udC7+-ud?lYC{D(UiFx zR^Fy-`<(5O*F;7Ka#)p2dC4J+zKXAJ7m$FWixBykKneL^<_B`mJZ(0)mGd<)D{@p9AbG2 z23I1V;ux15RYcv$(Eh|?mrcgfL|%Bw1VM$gCI@WNW31Gm=^!V0N`tjQHtz%D>y%C` z5NYQa%d)r}R8T|r=Iexx=Z^pWYC!-Q$1?*AUhXt$w|rv?u!qXAXkkf-+BMic`2^R` zp@o4Vl>ECk1wvLn9g`4iTU=Q5<@l%e6GF^-_Qux)piR`1)>ew9I@kcVL>l9ZiO>)o^n724r-5{@O_0RQt7LJYU( zEqI0({>}zi=`>UMxq7^`kNmaoDMtc4ljVDC6vxL=Il{9LQt2vMvM1}PP7KxvE~ois zc^YyWN;%`hTowK-m8y~N+x$|)u5A3$pTXLuMwMhklaq6@8$iraI$&$nsR@1o&H4K487{hAYBHL&SP#-ezDar0XpC-oU}eu`UCy4_y2#k;#E+p}BwBo#$`=%b1JIoecA zQR7D2j`ESk_{McZ7Uvu%u&%TPck_%-&&PDt%WUb<#k%RfkxT)~) zgg^sYS%aAC`GPe!v5ByBwA7S`>Hn-)Y*^wK>mx6+{u4J%D}FYUH#myDBA<81CyGU1 zDa&U)nT|c9-9i$CmW0!MTTp0GEa~kaLcbMMI21+$;n;l%BMb)@H!KYQ%a^}cY~`=Q zWJK!RU>7b4X7IYrkR*Z{mxj2ej|1J~$DtYhhi5sr&RcuizB*oOIna*h>!WpkiA6(n zA}k+mjD=LfROT2-cGu)kTt0ZOptyBFt*CgkgHqcm2*}0|>B+~I;FvKB18X@`W2ZBH zQ+xRrsc!I=>rMw*jPHBaXkkJY!8U(#KMs&OmMz=TTNR;z&GZbrkz94F2o(uo5|09v zKRf>H+em{dQA4}#rEZA~o#JQk3syFZkw{7D&yZgt6c#(8^ZT zLxv=R#^U~sSm9c{B(JwU2`yBHzdW&%KqR-%=5ZyuN~L$%u}604TaoP8g1RSUs!QNb z4wZlINz9!N9d}i6E2=O}j_6SB6rnIbTk!9(_vtq;0MLAa zm(e&(E+Uzv+J|u}2=|_h4g{htWX^4QX}|5UAzS;`{ig$Py_f>yG0T~YSFst%{(@Nb z>@APOQ1ph2b)K(8d<;m(H%q$aLN0gLf4$-#F{x%LMP;k5W;M9HST%NWK}CRHyRC@h zmpPw{n@ycJNEu%~$tYons_{!enk=)7O?>bv=i-%|F%u$iwSB=ym1`i{;B*6UjT6Fz z8NHEcg4~CMo3Xtw!n3lnKEN(+8b_53^Wn)>XV%5e_6%7~UcUG8Hn88k9meuV>Wy+! zr4}+ZR+UJV*}Mc>r-`&m4wt1FTWa^EWlz8^QDC~$fg+9vnhm_$-QlkdPZ;)$IHx_{q><>q)MOdZ!$oo zg4&i+;; z#y;}IO1h$kpMe4&UNwMlLbrD?mRqPJ!(n)<7jjZ3XE$PhDu*WIW3ejm!G3d^f{F;@hqqol~e8yf6Bx8LNfX=1Cz89)j=a9kE1Ezl)T$2rF;P+7r7l!TW_Awo3< z2fHd4(g1@2iVHeaRjVeRr{Pyb=>$?6mb)uE)R^uU)*`Qzv9q2`#CkVObqEt(d>eNA zDfW5y*L}pM2cq*XVomDPxpUBL07WD2Mfh*qDG%}sU}9KqP#VosT2(>#^89*5{uzrd z^`D~pfYpV`|60QM8TRTec$1Ih%21|{0mClwz30!L4@K~k;Q_vc;eqUtSrhUurF-Zo zQ9>Fh!L;DBGbh-V)vTtRx`7!M=0`Ty^RrSpx6I3PN$KIMrPlGQQNVWgq|hS)Hefc` zDgjP-3LcOj|6L{vrplGF#Dyi|-nZ0Hi&qn|QtD~O(@3E6OfLd<0Iyx=q6+l-LT=nJ z+m-I-*Mn#bH#waEXWUC~i^s(UQGxbk?rwuYxNYfZE~Tw4z(5J-POp-HB`?y4L@TbL zgIll36tI)e&J2#95`ZNCltf*h7koP8BQqIsa|(U{S+|_6f4xJApRpFX!9{`(#I3}* z%y@j~Lt5auKMD}2F{qvh(B4{ir~Lg93#7fguu#*niC!mYbI1`u(v1)}IbX;L6E6}ZlZQuPhC7j!^`t$~l4vvZ?@zk;W{`T!qVDx_Hb0GV7Y@sCxO2Dd~$BTc6 zHAQT*mvi|kSpHg}*B#u^=cE}#YH$2DybW1o;;I{DMFMR2Er>%es4L0yma1=GoEG_= zo_Cs`ZZ=Jetd~xWrFH>DEJb8Vm0>g0~Q{ulq)typfoFEBkGUhrb8tCE;m1UdNhV&P0{ z=5meg;t0xm+HPLFHwY4FXZ6(WSo5)HRXvdlU)^R+kkmk9#q{{HZ*=>THgx;5MRZ?E zPiZN{vL?(X)@!+NCJyULRVAV+n3yAKQam{lcW~(B6_<)?Z zhomDq;zLGjvkB7a;4Zs|lS4`bn*_J_*Mlga!W38_^4q86__S!nBLI7wUfxISr~;w3 z&H})VZBK|$QYlKJd40l+T}}nX6HcGRdTS$0hir_uUX~Qu^)!+SdOe@imy;+avk8`y z+5e7kyb8)Zo%S(CPPb$vWY3}Tw6^`}66Ov>ELg0qHzAq$Njsh$01mF2|e$8(*A>ACZDH$|-#U);(M>u?Z zkD{owb@|wkxo_h{(NCuCXBW9 zgzZ+3BM-j|N_Z79)Bx)7JCTd~;lsO-`YxoJCWvM=iVg>AL| zrXPuI*16nJ^MznW`lVO~$X!vW%%6$AwlONJN!w*vkFl(prL($>ZU$<0(J{&Mr^2e5 z)LUlW5|mu#i6R2aSe410=8Q4$;^TDhUxD9 zk328;6^>Z{$}&lIegLOxdu_^L(LMl13?G&gXe~E z=(}m!m%XM%J@pZa@nSGv##M_J*4fH{r~~br3ky@LE)L%fpuPxJv!eNUd&g?1zXZkR zMA>I+;lB#PFeTn^LOSv@Z!T8|f_Z~$<3I!78)c9ub0vf=MBp`KZc`>)e-+4La>koO1F3_V zdBn^Z`zN1mz6{VMfsm6Iqx`a)%Nc^nO#W$*{nioGKdbm4AH-<*`#6Jv-V_}^K+GTV zB)ZfixH9Q01o>j6G+GZf(mT9y;W!ku7-bFo6vQkZz0FwmocS(lW1zkGYt|Q&*gX zfxZp6^iMY6+GV>~+p_gom&x#I%KB~ktPCrIIwdHa$d(g6L4El3mf#ySJ2yCp# zK-9W3ayThDIsdqs*x0#h(Va^p{sHU#cz`Her<#momUQx9GIIe~CZH;C-&t~jS4<4X z-@1aWBhM0lqtLFk>?^BXS$dc~DNhrvEImy$vpB^uC8Aw5=!%O5Yf_w)1n)PGw;(<1 zhs#`JY_)?FgF|YmV}gCfU#oLvr5eQbfM$auZVGpOjvCz^hTH1BfvGk29bb$ncFWo{ z#|hdr2V>h@QN{7F9~u7=-Chb!$T^6D!;MX$o$&i*C-X+fuT90eyR)Xpx zI_j`}feM6?kmlVM1+#L?p<@|`sanzqvZ2n&DJ23hM~?ZGpuY--zbO15XHJ*^D3A^X z+tvUitlI4tXJG(^8lD#?WZoQJW00aZ>P0q9men53$}1w)OJ6Qf*j{NMvH0DV&St;E zU~lP^cWo!06aRj5lDwj@!BJm^gDdX1;FZRj_xjxs=Z!9vAol%RBX3S9I``0;Mg_M`FZ7c=i0zPAVM0Dwm4mgbvMA?N@mW zS>+>2lX&-zYv=|7P#7-;W&(?Z1zYXElw0+Ee$*)K&+;Pv{8ns4gTBEQl*;10%v=7LmfJqghE`*M7_9f`8mp~2#!LLD z@Fgz^3i=d+?bB^!i14=ik^>Tmrxl||Wi>w8z?$r4ujH7DlXJ>mWJ_kbx`wR3diAQp z-kEgVvABKVb<)S`DlF$AvxEtddE`X4Kehpz51sRakD-i<8dhy^cAMporWK9@pgh-2 z(5Iq=tux1y0Gghg{&=Jb^TFq~%`xG|J1UCXAA9jmwA(8;o;K1JZb*IExvtb+7jA!aC-27jzW!MR zb_nq6QO}SG5Z`o>V=#L*y^`9G+zez92P~5XSFipn;dOTHXkgP!@SwQuRQ<7+)iRj? z971DSqY!hx#Wm8j*wMNYuvU8ETt9e406+3kTBZ*?ZwMS;4Ju1&>Zh1z$Uq6+bxmR< zj=F@ewSV!PKd#++**^8!2jYAAN+3-J{~+6s@PN&aA%?AyzP~4-b4qkx=?pHMTeI}u zPVh|iI_zWu8o?5jKtYYpya|$m4w6-u$TOC zwj}*x-;JAF59^2zer{Jdw7oF^RtI?JvN$R4@%uuZqpoZ|$E;n+M-7k{d$&tIN)T&< zyfFKbaD$hqs;cN+_EMdnAIQ!WeKl&Uv zeyPW8h!^(Z@wcR9a;}V+`BJ$_;(#9K2->ykzLtB_mm`HUXexE1VDgUe~thhc&!-ywDa#>-FO7USste(d1G;O4*6|ux`@q&aT%j$8%m9 zvnv6^)2X|ywpgljn0HgKGGl<|C*`Qj=0St&LqgOAD^1}mHI;=5@Ido)PwRspv?i!= z_Y(gz>5@0DSaYenVh&!22DrkuGbCWs7F?BJuv0U8qG6Y@OJ5jpNXO#8f?pW0Wx`a;(gie`7*%zd_*aIX zz2o{6i0_uRN!|9X64MikzVU>P_)kB|O|G~$L01nA%TZMEKN33{JZ+k%~uDIQM&Onl!Vd+ct&8mCJ=4>CPs^ zCCo($lKbP+E?zPHX++e3m~~cMQTtDUfB9KVW^>c7zrdKNMOU z6=k>cEAzz4R-MNt^S@R2L6Ipk`U=Y-E|m(ZShi{WMuQ4Wigip}h*EZb-@2C)Xt2pl z!5zAhVnE4e0uUtne84%g<_WG5M#K(=5II=5^L8avn?@f*_LXJkVEmuQLE3Phu zbDU;)!HwhwJ09^U?7MR(wo-SI2Ze7A(+hon^+@gZNg2X2Vx!k}bG|s-s{dMpe2TI% z+u0`hu~lt25SsH3YSn-L^dd7y$?MJd`=+G5M)Y;DnZ`4Jk#8glu0~uLID$tg+I`+>O|&402jSfZ21}bjOyr)yYMJ zY2!bnAQ64)aQRj7&5V7izHH{0%!K(MdFqy+uPB8Gu0?oOHu_OL5T9eiQ3^r72tn=5 z8ZB}1x@Zy~i#m4v7jkiFUq)S?9S~Kq&qQhS#v{(V#EQJm{`EXkk)2wwpL*e&)efaC z$D*cob-)m?tqbgp+kbA>|02)zUcEO~`XsXNtlV6r@V-OV`tV zQYzo_e1<*8=>lYV6#`Q4>Zr}T_ztpM?WfigU6kGg-NBBKC{sHKnw6TKx{J_Wzx^*q zy$lUGtu_Y`TbUrr(|f{m5dg2&2xLN{8LOA=BiK^<6=WI{1L|8BDSBt!s#3cbvr@aA zCwk~%K|AP`@Q6&a^VV71qC)uBy@0S;@|j=&oUohn&W8vJ>$KOr6tKZQ+XBZg7{Y35fTP1W1KD zjfBD#pG4E%of^T62>FfiycaP4yX^MrCt*RX*^2PLIWM57ub87LRef9==y-LfT0`yD z)PUFGJ?IN`b$mFO6y*ja=AHG7c25rleig_EstRASy#7*~i_8(uSr1aw=s8uWT21kl zGV^K4T_T3xxnwqxM3R;GJCGPDo=A;9@TO&65pF&H$y^a&%)=C)L9j}SxWMd+COZDd zX?e{xUK&Dk`z!AqZk2ZJwrAZN#x7_x4d_=^9hf;lbuA@Kwhmtg|>ZcW13o$-VgT7LEm!eqs#!OwM5tmnjF*2|k=aHuPF zUw^TlACxPDNVcX6jPBkIIzg<9A8IL6uXvg(V; zH!uEihqA7k5MKRRFR~t8i}tRp%a*O;;eYGJxi-m$*7v*bg@7ILqMOi>Sol@Z1T|}7 zlcyzic{#cv)wC(<{(wDfJf%5d{5z;??|!z*s^4UJ_PoS)2yzNVYoiFX*}}xnY?Cgq zoaIk%%=vCIKJeKV9PqM{UJ;xLf4=dm<2Aaj`Dz5;)a zM)R*iQRU3Zrm56~x-|1|)&(s03YjTDnNs>z5ew%jV5_qZDe=V=yMT3BDgASvjE{$_ zQqq^$bJ6ne-DLMl0Ul(4S)9t?-fRfH_D$qj6wo;GeROX@+j+4%RaV5W%SvE!Dtr*7 zYaM`QWRZ2jw1ttQr!OsmGXU3q;SUWD(6jeBqCz+5hY)X8_01ef<_^irlyyzkTOtqo z*}B&mJ@Xcqr$-dd`qw_5x@7!P{W5R3uWuNS)^=b<(U!3I@vp=;W0%J$0yCibQ14Iw9zF`XsNX4!fr$c;wm}?BPRDO=Q z*{wq(4^ql*i``WFFYRH%YAWXD=6qza!0Gzjk`jUHq*!H2LYDG?d_gnVrPk5;uGrP& zV_1&O5L)W8PqXSlGp^%%h0NDo^LMusIwaAhHqBH<=ao;^=VkE{=1~+kW4+0!Zw|DE ze&^rq<)0Sy9^z1-CshJ+h2H>b=_H~%irUgL(p3o}3i!7hI=>L_s9 zeG)i2h#>K^op!0%!;s-O%JUv{XGt}U?kJB_K^x4gFLHtI*(bk01ZP|}S7dkPi`H6x zU)!;oT5H(dY&uy?9QpF`wAE1V6iy{~Va>>vtsj??!q&BUGzjF`tg>Hqnx=Dh_7OVc ze|jALsUAR;259Ij<1=aWav6U}W^YuchDyX^nXILMoGxhz+gInymZzPz;8#Br%hTUm zJ8=QG17V|iDHA1S(NeYq(^oi-F%dr>2X<|PXK{BS3JZdRg&MNgXb>TFiXf{rE3?_uhc6`? z@J~JpE;|h|6r#_f?a3t*_RgmK6+CSqC#ziReV{L2P9F8XEJCOU%Z7=O{xDXhp=#8X z%wgO{A4pN(WGqC7VT@ugZqk_;ePT#{f#(y@+-}=%JFxnzTddv@tmvqm5>B3oJFZ7wLxJB+p}ZNZX*=?L|? z!0Ay1aI0_#$pY0woSB;WAUKFmWZS7el8$pmLh>W(fOUm-g^{cNp`G^0S-KEFNaUZ^jN-GPHjVu9a(709bueP zUqSg>f=%=jZ1-|L^F)PWMUc-rPz>@_;W`2vt)@jM;39O1}L?vXsL(tGG7IppXj@2}w zEGLTvvv5l_qMoh2CvN= zN?dD)f@(~$w6=EDLw9z@P4ro0*Jy^ku_yaZ4@3ORTTip@YdvqmA~vqx_VDF z3+eNR_R0fY-ZUJ(F}zM;4^6BLJQcw&sSi6alRjs=n)29_t}Hcf27Q5yZ9TFx~rskGhWZ%tZ?mSQ4`X)0!glxY)XD3#~5)68V%Ay0W|42&c- zPfRIzASHD)%Y?*3@4O)%L)6p}JXB_QXkJo5LrP>&q^!^s-OD|Df7qYi>)qGhAJ@9p zwXSEa=f3~*z7QE9(k7IdD8b@@TFh*Sa&2ml;uh`^ zwn!J3)+EKnLzZs2p3vvz2#|l{4BVN~-T*nwqWf5e+S%{tg>!7-i{6?6@X9t-dG}K* z0NV3{qdTpZS}D{9s8i6UY5MQ&Ay z&D8E4xEjqLpXy(3TsCZRvn=ZaNiPF&|Z~48sq<{G)}^^ zyJ?08Z81WiU*SsyPqC=2D}4D_{ndHV>p1?YB)XzSlP~$g+5hv8Mgms%ReRG%$PrO( zjQ1FS@AfG(D@9ybVsWuhx}zPUF2#JSmm1|#oy@=CM{a|t<4X`0cI2X|t$G+wEQrEN z$DdYQ88%8-9dj1oG*vM4U)LJ4`BiLx$L#SiAF>Bpd7B zObzhsZuiI!0DQr}WLBGVZRW@9;dugkq0T&4=T-Q0AoJ|CdM^3?KL=)~@4X&)gDV+Q zif;E`$hs)JO8lI{mE${)Pzqrf+C0S3y)`*u%>aeNt7K%4C_ygpdQcE~zTo|{u1Coe z(1#|f<#a{jj`Tyh6P@C*gMVf&2hO%E(%P18&?}Nf(Wb(v+0}&55;jKUq~!EWPHoRM zr(=S4*{(j@$|FdA-J`&njqThNR;3v_vN>+08Izz9)3! zb!+gjA-H%bbusVaVc%oMzMg{scO}Hamji_qFR8ke%y)NaXE=OCe{SJ2y)TvI)0%w7 z=nOc4-fr_Yb9(m!m=5SJb--KTUssEFJC8?dQ#wcA4rWc%ZX;h2L%m)bxTLS=54U?D z`qg`(G*Yo!I8T${JRBM$E+agd%Ij(+2fOeM0#Og^BM3Su9aRbs`EHRe2GgR}Mhxv` z3a22nmoW9)l&5gfwVW8dvPHGRwizzpROs)56C)7G`hWC$1)7`BCp_ zJb7ub>f$weX~*otnWYTAV7O_Sd6SlmC0`Mo%!ILnD5`fjm~6_-+9bGOkL_w?xQkU% z=Q*KW5R@jWc#Z^XxovfDbl6`O;j36U|Ffn;O_?MzML~^>j=bD#S4nIRY2dzjxPt-- z!J(1pFcLMn1BM~HU^4LaYoDbPwLM2g?T;ys^JUHz(gzrn^SQt^0^|Z}f~O^bd}S_T z44MkdB-O@>1UlWx991^h!nyJ?Z;1GYzJ%vlJxlwXLNO=K-FK(&ua!^K!eY~xgBTxG zJ!Nmx1c%%Y`d9_|jgAejxX%lEKIO|_K~|owSvGsZv%2kg9w2gu-B~f5B)AUxoI=)k zTzl5&Md*hqgWIF_z-@~kBOFclRH6fBfybH9tXD^Wjn%pnV{yKG1D@=zwNh`7fz;D zm9s6MgYVbCjfV1bKfbx`(*qc$^m!Wv$g_ZI&uQO^78iTLKR>ps(|$+-5nmjmZ0b#Z z#M_<@8ljg~Gk=J8+tA#2OZKGJ@VBZTty-N*{G1)4LH!h#Zb@&=ZL^b5RDbZw{B*?F zi_}O);$6?(VSY1<_PC$6xPl%LEN^KP8lE2FirOLk1keFm42d03$MGu<&l}g7WY77p zM7(8Vl8Es;&K*`BF-hsbSwl}n`2>8Oox2#|FFvGdljW|aUg7HY?R6%HE+?vI*f3V9 zri}08o&uoKkbwfsnuj{hoNpnFwY$0?Y1}Nvn^`rLC%>91-IE8Q`*1#n`+a@oinqu= z+g;iJ9=CxzNgz=|NgJpwMGd4_4T>T793a7c%#el?F96z+yj96L4<%%*&UK0*fegF4 zDDTCU*&_zkFmIz27Vbf$38PUB(QHPVqOh>yOS-6b_YrCvR{RO|pn0}Lts=!rN7aMW z(&<#eA))*udd%8nTjSnp} zEC0L3wt9)L9)hSX8b)}KVYAY%lYq0(*LCn;)TgA+QE4tvR!{zGRw({m3+}iZ1Hb*^ zS@riJ;b-AGY{?B%AJU!$hMNAwjo)B= z+=(+CCe44dh@T|S`;%eCK}XA+biP@CcIlkHI<8yz+Nh5Jd<4IMW}{8r*_YF`>w;w$ zk`Tzes}vuN6uTlq5Z7je65R2KvrH zCx0~+Nn>OKbqfsH?`$O2J)0~EyCS;Qj0~Jy`ma%p=49-a&4!lf4!D2z?prA69oo#3 zEbRjXlH_$a+^wFw@%aG9){ev1);9l3AwioFP-aNj+jAJ)@o0@A@wbS>iksa?=+dM% zdKDbp)s0mckw{fm$?-rf|IC#ts#YJ24T7f zVDKa)N+&q+KgWSJUyFkE0RXpsI@CVbk3jIeuX`5~dMxTbeVJj{00M0|+K2SyVEm79 zG>-5piHMo30Hr?4Io_=PM87E?FX_6*+&Q&B8xoDzc=$ZH1j67K@SPr<799*N`k|T- zB325lAM_$meMAdt+vdpf>hNCPdPFa;3>wGheE_M(g!8=i(@h1_E%8{cghhwr3H2*; zjuZ@Wu5~h!u}qt***9#6$ofs|9!~j|I{`&?F&EOVeRbuGAXKxT5f2%9(*t3 z!$~|_v%Mx@9_PT4aR&&@+PA67RpZSGUpz1IMXw>Ck@n8O-{t^&TJAY$}Yo2jHqqswpuS#$MJu$^^H0 zaMvJ{9a%0G-AdQ>juC-)0u^c_{Ef!~Y|6AY`0hhfm!V_?IFPsxcQ`{jdZ^Y|vLcpH|v3Qe&h8WYn6&EYzIQ-9K8 zlxWpbC9gdyEZ*oumd|>x$2{nFOK-Jds$P3=Z*clrO+h*4Nfr}q&%uiQ+@`q_->y%b zGFVL|V;sVQZR6#Q5`!0oXFL)+)HXvg_mQ(0^#X_VA!id=(&&BA#|TuY6zqLZ2-RPX z<@a#eoa?~=VQ}q!mh=8~Y}q=%#sxS}6`=fb;R(6>qrWC%!;?p|g1vT*%>{7?+pwZ7 z2#eRA`R~yd8F&9`sL29f~Qkr5>^Y~s=0Kr zKXe~ns%5bWnEC5|`SmC2vOJq%jQZmTVMHD-0diMu5^YBwzaK;bj9JCPgUCX49so#BKAtSwzQ1E#65RvkX0e zVtQQXsGnEE^&PCUzmz-&kYhlcWQBTFqm*HpDl>Hsu(IF`2d}4{7ZSJsJ;+y4P(r$nd# literal 0 HcmV?d00001 diff --git a/Project2-Stream-Compaction/img/Scan_2.PNG b/Project2-Stream-Compaction/img/Scan_2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1a1484de4b3b05b2313ef7f534ed6ce6aa5d85d3 GIT binary patch literal 22303 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 IF7%|o0{8}(y#N3J literal 0 HcmV?d00001 diff --git a/Project2-Stream-Compaction/img/Scan_N2.PNG b/Project2-Stream-Compaction/img/Scan_N2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..84d0e2e51cd7927fd948e3e7385729017f497314 GIT binary patch literal 20199 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 Date: Tue, 17 Sep 2019 22:57:27 -0400 Subject: [PATCH 10/16] update pics --- .../img/figure-39-4.jpg | Bin 53943 -> 55653 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Project2-Stream-Compaction/img/figure-39-4.jpg b/Project2-Stream-Compaction/img/figure-39-4.jpg index 5888f20d204ffb4f2987ff7cb5edc5b521659b91..8964589cb0fda8926687ba721f4621ab244def5c 100644 GIT binary patch literal 55653 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 Ee=z7?(EtDd literal 53943 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 Date: Tue, 17 Sep 2019 23:23:00 -0400 Subject: [PATCH 11/16] extra --- Project2-Stream-Compaction/img/extra.PNG | Bin 0 -> 6338 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Project2-Stream-Compaction/img/extra.PNG diff --git a/Project2-Stream-Compaction/img/extra.PNG b/Project2-Stream-Compaction/img/extra.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c4d91c9b76ec6874a18809a2271faa400baf5f10 GIT binary patch literal 6338 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 literal 0 HcmV?d00001 From c77f1c76e7a50627f09fcfb17b7f0fd8e64cea52 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Tue, 17 Sep 2019 23:57:56 -0400 Subject: [PATCH 12/16] Update Read me --- Project2-Stream-Compaction/README.md | 148 +++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 6 deletions(-) diff --git a/Project2-Stream-Compaction/README.md b/Project2-Stream-Compaction/README.md index 0e38ddb..e28b40a 100644 --- a/Project2-Stream-Compaction/README.md +++ b/Project2-Stream-Compaction/README.md @@ -3,12 +3,148 @@ 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) +Peyman Norouzi +* [LinkedIn](https://www.linkedin.com/in/peymannorouzi) +* Tested on: Windows 10, i7-6700 @ 3.40GHz 16GB, Quadro P1000 4096MB (Moore 100B Lab) -### (TODO: Your README) +## Scan and Stream Compaction: + +Enclusive scan, or simply scan of a sequence of numbers x0, x1, x2, ... is a second sequence of numbers y0, y1, y2, ..., the sums of prefixes (running totals) of the input sequence: + +y0 = 0 + +y1 = x0 + +y2 = x0 + x1 + +... + +Compaction, on the other hand, is a parallel computing primitive that produces output results consisting of only valid elements from an input array (invalid and valid elements). + + +## The implementations: + +The following implementations were implemted and their performance analyzed: + +* CPU scan and stream compaction +* GPU Naive scan +* GPU work efficient scan and stream compaction +* Scan using Thrust package + + +### 1. CPU scan and stream compaction: + +In the scan we compute an exclusive prefix sum using a simple For loop to calculate the sum for each index in the array using the following: array[index] = array[index-1] + array[index]. + +In the stream compaction, we sequentially alter the index values in the array that are 0 to 0 and >0 to 1. Then using that we complete steam compaction. + +### 2. GPU Naive scan: +In this method, instead of going sequentially through all the indices in the array, we go through all of the indices of the array in parallel log(n) times just as following: + +![](img/figure-39-2.jpg) + +This method would give an inclusive scan, after we move the whole array one to the right thus making the scan exclusive. + +### 3. GPU work efficient scan and stream compaction: + +Sum: In this method, instead of double counting sums as we did in the naive approach, we only sum each respective indices once. This approach can be done in a place which means it doesn't suffer from the race conditions of the naive method since there won't be a case where one thread writes to and another thread reads from the same location in the array (it is more memory efficient). The scan uses a balanced binary tree in concept to perform the scan in two phases below: + +* Parallel Reduction (Up-Sweep) +* Down-Sweep + +The apporch can be seen using the following figure: + +![](img/figure-39-4.jpg) + +Since this approach uses a binary tree structure, it only works with arrays with power-of-two length. If the array does not hold that condition, I round the array memory allocation to the nearest power of two. + +In compaction, I used the implemented work efficient scan to the array and compact the input array out of zeros (This would have not been possible without the scan since the GPU does not work sequentially). + +### 4. Scan using Thrust package: + +I have also implemented the exclsuive scan using the thurst package as a base line to see how the approaches earlier would stack up against each other. + + +## Why is My GPU Approach So Slow? (Extra Credit) (+5) + +I first implemented the work efficient method by launching n threads where n represents the number of elements in the array. This is very inefficient because in a lot of the times most of the used threads won't be doing any work. This is because of the efficient scan uses the following loops for both up sweep and down sweep: + +![](img/extra.PNG) + +In the inner loop, we are working in parallel on the GPU. The step size for this loop is not 1 and changes based on the outer loop (d). Thus as d increases, the step size in the inner loop increases. Increased step size would then take use less and less of the launched threads if we have them as n (fixed). To improve this, we would need to launch less and fewer threads as we progress in the other loop. You can have a look at my code in the efficient.cu to see how I am changing the number of laughed thread thus improving the GPU performance significantly. This is the approach I used for my work efficient method. + + +## Performance: + +1. The performance of each of the implemented algorithm changes based on how many blocks were used in launching their respective kernals. I ran multiple kernal values for each GPU implementation and 256 worked the best for the efficient approach and 512 worked the best for the naive approach. + +2. The followings are the performanace of the implemneted approaches for both scanning and compation: + +![](img/Scan_2.PNG) +![](img/Scan_N2.PNG) +![](img/Compaction.PNG) + +3. + +CPU performs the best when the array size is small which makes sense. This is because we are doing fewer mathematical operations in the CPU approach. But as the size of the array increases the performance of the CPU also decreases significantly. This is because we are operating each summation sequentially thus making the process a lot less efficient. The GPU work efficient approach shines as the number of elements in the array increases. this makes sense because we are doing not only less mathematical operations (compare to GPU naive) but we are also doing more and more of the operations in parallel on the warp on the GPU. The performance of the efficient approach is very similar to the thrust performance as the array size increases which kind of speak to the fact that the thrust package might be using the same (close approach) to the work efficient. Though I expect the thrust to perform better as the number of array size increases because the package probably does a better job with memory management. In compaction part, the CPU performs when we are not using scan when compacting which makes sense. But then GPU work efficient also performs reasonably considering many kernels that had to be run for the same easy implementation of compaction. + +## Tests output: + +``` +**************** +** SCAN TESTS ** +**************** + [ 21 15 25 19 28 10 5 34 4 33 35 23 44 ... 39 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.0019ms (std::chrono Measured) + [ 0 21 36 61 80 108 118 123 157 161 194 229 252 ... 24539 24578 ] +==== cpu scan, non-power-of-two ==== + elapsed time: 0.0016ms (std::chrono Measured) + [ 0 21 36 61 80 108 118 123 157 161 194 229 252 ... 24424 24464 ] + passed +==== naive scan, power-of-two ==== + elapsed time: 0.067008ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.063488ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.088416ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.089088ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.050432ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.05008ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 3 1 1 1 0 0 1 2 2 3 1 1 2 ... 1 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.0027ms (std::chrono Measured) + [ 3 1 1 1 1 2 2 3 1 1 2 3 1 ... 1 1 ] + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.0028ms (std::chrono Measured) + [ 3 1 1 1 1 2 2 3 1 1 2 3 1 ... 2 1 ] + passed +==== cpu compact with scan ==== + elapsed time: 1.6032ms (std::chrono Measured) + [ 3 1 1 1 1 2 2 3 1 1 2 3 1 ... 1 1 ] + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.283808ms (CUDA Measured) + [ 3 1 1 1 1 2 2 3 1 1 2 3 1 ... 1 1 ] + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.285792ms (CUDA Measured) + [ 3 1 1 1 1 2 2 3 1 1 2 3 1 ... 2 1 ] + passed +``` -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) From 0b2774f1cc0c89b39f4de8f12be684004602c3a0 Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Wed, 18 Sep 2019 00:09:23 -0400 Subject: [PATCH 13/16] updated overall readme --- README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3a0b2fe..050711d 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ -CUDA Number Algorithms +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) +Peyman Norouzi +* [LinkedIn](https://www.linkedin.com/in/peymannorouzi) +* Tested on: Windows 10, i7-6700 @ 3.40GHz 16GB, Quadro P1000 4096MB (Moore 100B Lab) -### (TODO: Your README) - -Link to the readmes of the other two subprojects. - -Add anything else you think is relevant up to this point. -(Remember, this is public, so don't put anything here that you don't want to share with the world.) +1) [Stream Compaction](./Project2-Stream-Compaction/README.md) +2) [Character Recognition](./Project2-Character-Recognition/README.md) From c61db09332bc744ac3d61664c633e9f30fcd2fef Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Wed, 18 Sep 2019 00:16:16 -0400 Subject: [PATCH 14/16] Updated to include explanation --- Project2-Character-Recognition/README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Project2-Character-Recognition/README.md b/Project2-Character-Recognition/README.md index 4503fac..9993386 100644 --- a/Project2-Character-Recognition/README.md +++ b/Project2-Character-Recognition/README.md @@ -3,12 +3,8 @@ CUDA Character Recognition **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** -* (TODO) YOUR NAME HERE - * (TODO) [LinkedIn](), [personal website](), [twitter](), etc. -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) - -### (TODO: Your README) - -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +Peyman Norouzi +* [LinkedIn](https://www.linkedin.com/in/peymannorouzi) +* Tested on: Windows 10, i7-6700 @ 3.40GHz 16GB, Quadro P1000 4096MB (Moore 100B Lab) +Implemented most of the kernels for MLP. But the code does not run. I had/have a lot of things in my basket for the past/current week. I worked a lot on this project but could not complete all of MLP to write the read me. I would appreciate some points based on my structure and functions. From e2d9f376491c2efbf8686120ca97853916690f5d Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Wed, 18 Sep 2019 00:26:58 -0400 Subject: [PATCH 15/16] updated --- .../character_recognition/mlp.cu | 46 +++++++++---------- Project2-Stream-Compaction/src/main.cpp | 2 +- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Project2-Character-Recognition/character_recognition/mlp.cu b/Project2-Character-Recognition/character_recognition/mlp.cu index 3ca3120..8ed4cd8 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.cu +++ b/Project2-Character-Recognition/character_recognition/mlp.cu @@ -88,55 +88,51 @@ namespace CharacterRecognition { - __global__ void addVectors(float *vec1, float *vec2, float *result) { + __global__ void SumVectors(float *vec1, float *vec2, float *out) { int index = blockIdx.x * blockDim.x + threadIdx.x; - result[index] = vec1[index] + vec2[index]; + out[index] = vec1[index] + vec2[index]; } + // help from http://luniak.io/cuda-neural-network-implementation-part + __global__ void ForwardLayer(float* W, float* activation, float* Z, float* b, int W_x_dim, int W_y_dim, int Acti_x_dim, int Acti_y_dim) { - __global__ void linearForward(float* W, float* A, float* Z, float* b, - int W_x_dim, int W_y_dim, - int A_x_dim, int A_y_dim) { int row = blockIdx.y * blockDim.y + threadIdx.y; int col = blockIdx.x * blockDim.x + threadIdx.x; - int Z_x_dim = A_x_dim; + int Z_x_dim = Acti_x_dim; int Z_y_dim = W_y_dim; float Z_value = 0; if (row < Z_y_dim && col < Z_x_dim) { for (int i = 0; i < W_x_dim; i++) { - Z_value += W[row * W_x_dim + i] * A[i * A_x_dim + col]; + Z_value += W[row * W_x_dim + i] * activation[i * Acti_x_dim + col]; } Z[row * Z_x_dim + col] = Z_value + b[row]; } } - __global__ void linearBackprop(float* W, float* dZ, float *dA, - int W_x_dim, int W_y_dim, - int dZ_x_dim, int dZ_y_dim) { + __global__ void BackpropLayer(float* W, float* dZ, float *dActi, int W_x_dim, int W_y_dim, int dZ_x_dim, int dZ_y_dim) { int col = blockIdx.x * blockDim.x + threadIdx.x; int row = blockIdx.y * blockDim.y + threadIdx.y; - // W is treated as transposed - int dA_x_dim = dZ_x_dim; - int dA_y_dim = W_x_dim; + int dActi_x_dim = dZ_x_dim; + int dActi_y_dim = W_x_dim; float dA_value = 0.0f; - if (row < dA_y_dim && col < dA_x_dim) { + if (row < dActi_y_dim && col < dActi_x_dim) { for (int i = 0; i < W_y_dim; i++) { dA_value += W[i * W_x_dim + row] * dZ[i * dZ_x_dim + col]; } - dA[row * dA_x_dim + col] = dA_value; + dActi[row * dActi_x_dim + col] = dA_value; } } - __global__ void reluActivationForward(float *Z, float *A, int n) { + __global__ void reluActivationForward(float *Z, float *activation, int n) { int index = blockIdx.x * blockDim.x + threadIdx.x; if (index < n) { @@ -144,12 +140,12 @@ namespace CharacterRecognition { } } - __global__ void reluActivationBackprop(int n ,float *Z, float *dA, float *dZ) { + __global__ void reluActivationBackprop(int n ,float *Z, float *dZ, float *dactivation) { int index = blockIdx.x * blockDim.x + threadIdx.x; if (index < n) { if (Z[index] > 0) { - dZ[index] = dA[index]; + dZ[index] = dactivation[index]; } else { dZ[index] = 0; @@ -161,19 +157,19 @@ namespace CharacterRecognition { return 1.0f / (1 + exp(-x)); } - __global__ void sigmoidActivationForward(int n, float* Z, float* A) { + __global__ void sigmoidActivationForward(int n, float* Z, float* activation) { int index = blockIdx.x * blockDim.x + threadIdx.x; if (index < n) { - A[index] = sigmoid(Z[index]); + activation[index] = sigmoid(Z[index]); } } - __global__ void sigmoidActivationBackprop(int n, float *Z, float *dA, float *dZ) { + __global__ void sigmoidActivationBackprop(int n, float *Z, float *dZ, float *dactivation) { int index = blockIdx.x * blockDim.x + threadIdx.x; if (index < n) { - dZ[index] = dA[index] * sigmoid(Z[index]) * (1 - sigmoid(Z[index])); + dZ[index] = dactivation[index] * sigmoid(Z[index]) * (1 - sigmoid(Z[index])); } } @@ -184,6 +180,7 @@ namespace CharacterRecognition { if (index < n) { float partial_cost = target[index] * logf(preds[index]) + (1.0f - target[index]) * logf(1.0f - preds[index]); + atomicAdd(loss, -partial_cost / n); } } @@ -196,10 +193,11 @@ namespace CharacterRecognition { } } - __global__ void ElementWiseMultiplication(int n, float *input1, float *input2, float *output) { + __global__ void ElementWiseMultiplication(int n, float *input1, float *input2, float *out) { int index = blockIdx.x * blockDim.x + threadIdx.x; + if (index #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]; From 72fbe767a136ec75b6f56bc43f94c83b7fd22b5a Mon Sep 17 00:00:00 2001 From: Peyman Norouzi <41491728+pnorouzi@users.noreply.github.com> Date: Wed, 18 Sep 2019 00:28:18 -0400 Subject: [PATCH 16/16] updated links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 050711d..1d5638e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,6 @@ Peyman Norouzi * [LinkedIn](https://www.linkedin.com/in/peymannorouzi) * Tested on: Windows 10, i7-6700 @ 3.40GHz 16GB, Quadro P1000 4096MB (Moore 100B Lab) -1) [Stream Compaction](./Project2-Stream-Compaction/README.md) -2) [Character Recognition](./Project2-Character-Recognition/README.md) +1) [Stream Compaction](./Project2-Stream-Compaction) +2) [Character Recognition](./Project2-Character-Recognition)