From da48185c89c81eb8a16f5b541965fa05d198a222 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Sun, 15 Sep 2019 15:33:18 -0400 Subject: [PATCH 01/13] efficeint scan done --- Project2-Stream-Compaction/src/main.cpp | 2 +- .../stream_compaction/CMakeLists.txt | 2 +- .../stream_compaction/cpu.cu | 38 ++++++++- .../stream_compaction/efficient.cu | 57 +++++++++++++ .../stream_compaction/naive.cu | 83 +++++++++++++++---- 5 files changed, 159 insertions(+), 23 deletions(-) diff --git a/Project2-Stream-Compaction/src/main.cpp b/Project2-Stream-Compaction/src/main.cpp index d016553..3569b2e 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 << 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]; diff --git a/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt b/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt index cdbef77..272a7e8 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_70 ) diff --git a/Project2-Stream-Compaction/stream_compaction/cpu.cu b/Project2-Stream-Compaction/stream_compaction/cpu.cu index a2d3e6c..fc03b6d 100644 --- a/Project2-Stream-Compaction/stream_compaction/cpu.cu +++ b/Project2-Stream-Compaction/stream_compaction/cpu.cu @@ -1,6 +1,5 @@ #include #include "cpu.h" - #include "common.h" namespace StreamCompaction { @@ -20,6 +19,17 @@ namespace StreamCompaction { void scan(int n, int *odata, const int *idata) { timer().startCpuTimer(); // TODO + + if (n == 0) { + timer().endCpuTimer(); + return; + } + // odata[0] = idata[0]; // Inclusive Scan + odata[0] = 0; // Exclusive Scan + for (int i = 1; i < n; i++) { + odata[i] = odata[i - 1] + idata[i-1]; + } + timer().endCpuTimer(); } @@ -31,8 +41,13 @@ namespace StreamCompaction { int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); // TODO + int num = 0; + for (int i = 0; i < n; i++) { + if (idata[i] == 0) continue; + odata[num++] = idata[i]; + } timer().endCpuTimer(); - return -1; + return num; } /** @@ -43,8 +58,25 @@ namespace StreamCompaction { int compactWithScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); // TODO + int* scanResult = (int*)malloc(n * sizeof(int)); + + // Scan + scanResult[0] = 0; + for (int i = 1; i < n; i++) { + scanResult[i] = scanResult[i - 1] + (idata[i-1]?1:0); + } + + int num = 0; + for (int i = 0; i < n; i++) { + // Only write on element if idata has a 1 + if (idata[i]) { + odata[scanResult[i]] = idata[i]; + num++; + } + } + free(scanResult); timer().endCpuTimer(); - return -1; + return num; } } } diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index 2db346e..c1cd8f6 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -12,12 +12,69 @@ namespace StreamCompaction { return timer; } + __global__ + void kernReduction(int n, unsigned int d, int *idata) + { + int k = blockIdx.x * blockDim.x + threadIdx.x; + unsigned int offset = 1 << d; + + if (k >= n || k % (offset << 1) !=0 ) return; + + idata[k + (offset << 1) - 1] += idata[k + offset - 1]; + } + + __global__ + void kernDownSweep(int n, unsigned int d, int* idata) + { + int k = blockIdx.x * blockDim.x + threadIdx.x; + + unsigned int offset = 1 << d; + if (k >= n || k % (offset << 1) != 0) return; + + int tmp = idata[k + offset - 1]; // Save left child + idata[k + offset - 1] = idata[k + (offset << 1) - 1]; // Set left child to this node's value + idata[k + (offset << 1) - 1] += tmp; // Set right child to old left value + this node's value + } + + __global__ void kernSetZero(int n, int* idata) + { + idata[n - 1] = 0; + } + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { timer().startGpuTimer(); // TODO + int* d_idata; + int maxD = ilog2ceil(n); + int nCeil = 1 << maxD; + + cudaMalloc(&d_idata, nCeil * sizeof(int)); + cudaMemset(d_idata, 0, nCeil * sizeof(int)); + cudaMemcpy(d_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + + int threadsPerBlock = 512; + int blockSize = (nCeil + threadsPerBlock - 1) / threadsPerBlock; + + // Parallel Reduction + for (int d = 0; d < maxD; d++) { + kernReduction << > > (n, d, d_idata); + cudaDeviceSynchronize(); + } + + kernSetZero << <1, 1 >> > (nCeil, d_idata); + cudaDeviceSynchronize(); + // Down Sweep + for (int d = maxD-1; d >= 0; d--) { + kernDownSweep << > > (n, d, d_idata); + cudaDeviceSynchronize(); + } + + cudaMemcpy(odata, d_idata, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaFree(d_idata); + timer().endGpuTimer(); } diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index 4308876..e1740a2 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -2,24 +2,71 @@ #include #include "common.h" #include "naive.h" +#include namespace StreamCompaction { - namespace Naive { - using StreamCompaction::Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } - // TODO: __global__ - - /** - * Performs prefix-sum (aka scan) on idata, storing the result into odata. - */ - void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - } - } + namespace Naive { + using StreamCompaction::Common::PerformanceTimer; + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } + + // TODO: __global__ + __global__ + void kernScan(unsigned int n, int offset, int* odata, int* idata) { + + int k = blockIdx.x * blockDim.x + threadIdx.x; + if (k >= n) return; + + if (k >= offset) + odata[k] = idata[k - offset] + idata[k]; + else + odata[k] = idata[k]; + } + + __global__ + void kernRightShift(unsigned int n, int* odata, int* idata) { + // Shift right by one -> get exclusive scan + int k = blockIdx.x * blockDim.x + threadIdx.x; + if (k >= n) return; + + odata[k] = k > 0 ? idata[k - 1] : 0; + } + + /** + * Performs prefix-sum (aka scan) on idata, storing the result into odata. + */ + void scan(int n, int* odata, const int* idata) { + timer().startGpuTimer(); + + int* d_odata; + int* d_idata; + cudaMalloc(&d_odata, n * sizeof(int)); + cudaMalloc(&d_idata, n * sizeof(int)); + cudaMemcpy(d_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + + int threadsPerBlock = 512; + int blockSize = (n + threadsPerBlock - 1) / threadsPerBlock; + + for (int offset = 1; offset < (n << 1); offset *= 2) { + kernScan << > > (n, offset, d_odata, d_idata); + cudaDeviceSynchronize(); + // swap in and out + int* tmp = d_odata; + d_odata = d_idata; + d_idata = tmp; + } + + cudaMemcpy(d_idata, d_odata, n * sizeof(int), cudaMemcpyDeviceToDevice); + kernRightShift << > > (n, d_odata, d_idata); + + cudaMemcpy(odata, d_odata, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaFree(d_idata); + cudaFree(d_odata); + + timer().endGpuTimer(); + } + } } From 6be1148d6133a93cdc09f74972c998607315f0f8 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Sun, 15 Sep 2019 19:18:45 -0400 Subject: [PATCH 02/13] part 1 done --- .../stream_compaction/common.cu | 12 ++++- .../stream_compaction/efficient.cu | 45 +++++++++++++++++-- .../stream_compaction/thrust.cu | 10 ++++- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/Project2-Stream-Compaction/stream_compaction/common.cu b/Project2-Stream-Compaction/stream_compaction/common.cu index 2ed6d63..6d24029 100644 --- a/Project2-Stream-Compaction/stream_compaction/common.cu +++ b/Project2-Stream-Compaction/stream_compaction/common.cu @@ -23,7 +23,10 @@ namespace StreamCompaction { * which map to 0 will be removed, and elements which map to 1 will be kept. */ __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { - // TODO + // DONE + int k = blockIdx.x * blockDim.x + threadIdx.x; + if (k >= n) return; + bools[k] = idata[k] > 0 ? 1 : 0; } /** @@ -32,7 +35,12 @@ namespace StreamCompaction { */ __global__ void kernScatter(int n, int *odata, const int *idata, const int *bools, const int *indices) { - // TODO + // DONE + int k = blockIdx.x * blockDim.x + threadIdx.x; + if (k >= n) return; + if (bools[k]) { + odata[indices[k]] = idata[k]; + } } } diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index c1cd8f6..f8ca8fa 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -6,6 +6,8 @@ namespace StreamCompaction { namespace Efficient { using StreamCompaction::Common::PerformanceTimer; + using namespace StreamCompaction::Common; + PerformanceTimer& timer() { static PerformanceTimer timer; @@ -45,7 +47,7 @@ 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(); + // timer().startGpuTimer(); // TODO int* d_idata; int maxD = ilog2ceil(n); @@ -75,7 +77,7 @@ namespace StreamCompaction { cudaMemcpy(odata, d_idata, n * sizeof(int), cudaMemcpyDeviceToHost); cudaFree(d_idata); - timer().endGpuTimer(); + // timer().endGpuTimer(); } /** @@ -90,8 +92,45 @@ namespace StreamCompaction { int compact(int n, int *odata, const int *idata) { timer().startGpuTimer(); // TODO + int numOfCompacted = 0; + int* d_idata; + int* d_odata; + int* d_bools; + int* d_indices; + + cudaMalloc(&d_idata, n * sizeof(int)); + cudaMalloc(&d_odata, n * sizeof(int)); + cudaMalloc(&d_bools, n * sizeof(int)); + cudaMalloc(&d_indices, n * sizeof(int)); + + cudaMemcpy(d_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + + int threadsPerBlock = 512; + int blockSize = (n + threadsPerBlock - 1) / threadsPerBlock; + kernMapToBoolean<<>>(n, d_bools, d_idata); + cudaDeviceSynchronize(); + + scan(n, d_indices, d_bools); + + cudaDeviceSynchronize(); + + int* lastIndex = d_indices + n - 1; + cudaMemcpy(&numOfCompacted, lastIndex, sizeof(int), cudaMemcpyDeviceToHost); + + kernScatter << > > (n, d_odata, d_idata, d_bools, d_indices); + + cudaDeviceSynchronize(); + + cudaMemcpy(odata, d_odata, n * sizeof(int), cudaMemcpyDeviceToHost); + + cudaFree(d_idata); + cudaFree(d_odata); + cudaFree(d_bools); + cudaFree(d_indices); + timer().endGpuTimer(); - return -1; + + return (idata[n-1] > 0 ) ? ( numOfCompacted + 1 ) : numOfCompacted; } } } diff --git a/Project2-Stream-Compaction/stream_compaction/thrust.cu b/Project2-Stream-Compaction/stream_compaction/thrust.cu index 1def45e..58772ee 100644 --- a/Project2-Stream-Compaction/stream_compaction/thrust.cu +++ b/Project2-Stream-Compaction/stream_compaction/thrust.cu @@ -18,11 +18,17 @@ 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(); // TODO use `thrust::exclusive_scan` // example: for device_vectors dv_in and dv_out: - // thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); + + thrust::device_vector dv_in(idata, idata + n); + thrust::device_vector dv_out(n); + + timer().startGpuTimer(); + thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); timer().endGpuTimer(); + + thrust::copy(dv_out.begin(), dv_out.end(), odata); } } } From d783f735cd6d3d99b38eb928498bb7232c5105dd Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Wed, 18 Sep 2019 19:32:43 -0400 Subject: [PATCH 03/13] clear main --- Project2-Character-Recognition/src/main.cpp | 119 -------------------- 1 file changed, 119 deletions(-) diff --git a/Project2-Character-Recognition/src/main.cpp b/Project2-Character-Recognition/src/main.cpp index 11dd534..c718857 100644 --- a/Project2-Character-Recognition/src/main.cpp +++ b/Project2-Character-Recognition/src/main.cpp @@ -25,125 +25,6 @@ int main(int argc, char* argv[]) { printf("** SCAN TESTS **\n"); printf("****************\n"); - genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case - a[SIZE - 1] = 0; - printArray(SIZE, a, true); - - // initialize b using StreamCompaction::CPU::scan you implement - // We use b for further comparison. Make sure your StreamCompaction::CPU::scan is correct. - // At first all cases passed because b && c are all zeroes. - zeroArray(SIZE, b); - printDesc("cpu scan, power-of-two"); - StreamCompaction::CPU::scan(SIZE, b, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(SIZE, b, true); - - zeroArray(SIZE, c); - printDesc("cpu scan, non-power-of-two"); - StreamCompaction::CPU::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(NPOT, b, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("naive scan, power-of-two"); - StreamCompaction::Naive::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan - onesArray(SIZE, c); - printDesc("1s array for finding bugs"); - StreamCompaction::Naive::scan(SIZE, c, a); - printArray(SIZE, c, true); */ - - zeroArray(SIZE, c); - printDesc("naive scan, non-power-of-two"); - StreamCompaction::Naive::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient scan, power-of-two"); - StreamCompaction::Efficient::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient scan, non-power-of-two"); - StreamCompaction::Efficient::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(NPOT, c, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("thrust scan, power-of-two"); - StreamCompaction::Thrust::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - zeroArray(SIZE, c); - printDesc("thrust scan, non-power-of-two"); - StreamCompaction::Thrust::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(NPOT, c, true); - printCmpResult(NPOT, b, c); - - printf("\n"); - printf("*****************************\n"); - printf("** STREAM COMPACTION TESTS **\n"); - printf("*****************************\n"); - - // Compaction tests - - genArray(SIZE - 1, a, 4); // Leave a 0 at the end to test that edge case - a[SIZE - 1] = 0; - printArray(SIZE, a, true); - - int count, expectedCount, expectedNPOT; - - // initialize b using StreamCompaction::CPU::compactWithoutScan you implement - // We use b for further comparison. Make sure your StreamCompaction::CPU::compactWithoutScan is correct. - zeroArray(SIZE, b); - printDesc("cpu compact without scan, power-of-two"); - count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - expectedCount = count; - printArray(count, b, true); - printCmpLenResult(count, expectedCount, b, b); - - zeroArray(SIZE, c); - printDesc("cpu compact without scan, non-power-of-two"); - count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - expectedNPOT = count; - printArray(count, c, true); - printCmpLenResult(count, expectedNPOT, b, c); - - zeroArray(SIZE, c); - printDesc("cpu compact with scan"); - count = StreamCompaction::CPU::compactWithScan(SIZE, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(count, c, true); - printCmpLenResult(count, expectedCount, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient compact, power-of-two"); - count = StreamCompaction::Efficient::compact(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); - printCmpLenResult(count, expectedCount, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient compact, non-power-of-two"); - count = StreamCompaction::Efficient::compact(NPOT, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); - printCmpLenResult(count, expectedNPOT, b, c); system("pause"); // stop Win32 console from closing on exit delete[] a; From 0775d34fb682d4b98044a84ed4b8a43dab90fc54 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Wed, 18 Sep 2019 21:39:51 -0400 Subject: [PATCH 04/13] main --- Project2-Character-Recognition/src/main.cpp | 54 +++++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/Project2-Character-Recognition/src/main.cpp b/Project2-Character-Recognition/src/main.cpp index c718857..57659f7 100644 --- a/Project2-Character-Recognition/src/main.cpp +++ b/Project2-Character-Recognition/src/main.cpp @@ -11,19 +11,63 @@ #include #include "testing_helpers.hpp" +#include +#include +#include + + const int SIZE = 1 << 8; // feel free to change the size of array const int NPOT = SIZE - 3; // Non-Power-Of-Two int *a = new int[SIZE]; int *b = new int[SIZE]; int *c = new int[SIZE]; +using namespace std; + +void loadTrainingData(const string& dir, vector >& input, vector >& output) +{ + const int trainingSize = 52; // How many samples to train + const int numVals = 10201; + + input.resize(trainingSize); // 52 x 10201 + output.resize(trainingSize); // 52 x 52 + + for (size_t i = 1; i <= trainingSize; i++) { + string filename = to_string(i) + "info.txt"; + if (i < 10) { + filename = "0" + filename; + } + string filePath = dir + filename; + + ifstream file(filePath); + + if (file.is_open()) { + int tmp; + for (size_t c = 0; c < 2; c++) file >> tmp; + input[i-1].resize(numVals); + for (size_t c = 0; c < numVals; c++) { + file >> input[i-1][c]; + } + file.close(); + } + + output[i - 1].resize(trainingSize, 0); + output[i - 1][i - 1] = 1; + } + +} + int main(int argc, char* argv[]) { - // Scan tests - printf("\n"); - printf("****************\n"); - printf("** SCAN TESTS **\n"); - printf("****************\n"); + const string dir = "..\\data-set\\"; + vector> input; + vector> output; + +// loadTrainingData(dir, input, output); + + // compute output + + CharacterRecognition::init(32, 8, 1, 0.5); system("pause"); // stop Win32 console from closing on exit From 1d8d17d11b529948b8360fb8c418098d6c69c17e Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Wed, 18 Sep 2019 21:40:05 -0400 Subject: [PATCH 05/13] cmake add cuda lib --- Project2-Character-Recognition/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Project2-Character-Recognition/CMakeLists.txt b/Project2-Character-Recognition/CMakeLists.txt index 09e9198..f30cae9 100644 --- a/Project2-Character-Recognition/CMakeLists.txt +++ b/Project2-Character-Recognition/CMakeLists.txt @@ -22,6 +22,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") endif() include_directories(.) +link_directories(${CUDA_TOOLKIT_ROOT_DIR}/lib/x64) + add_subdirectory(character_recognition) cuda_add_executable(${CMAKE_PROJECT_NAME} @@ -30,6 +32,8 @@ cuda_add_executable(${CMAKE_PROJECT_NAME} ) target_link_libraries(${CMAKE_PROJECT_NAME} + curand + cublas character_recognition ${CORELIBS} ) From bdb676ec46b0cbe22f5c887378d1a1eb155643e5 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Wed, 18 Sep 2019 21:40:25 -0400 Subject: [PATCH 06/13] cmake update sm --- .../character_recognition/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project2-Character-Recognition/character_recognition/CMakeLists.txt b/Project2-Character-Recognition/character_recognition/CMakeLists.txt index 7446175..c5e28b0 100644 --- a/Project2-Character-Recognition/character_recognition/CMakeLists.txt +++ b/Project2-Character-Recognition/character_recognition/CMakeLists.txt @@ -7,5 +7,5 @@ set(SOURCE_FILES cuda_add_library(character_recognition ${SOURCE_FILES} - OPTIONS -arch=sm_20 + OPTIONS -arch=sm_75 ) From 2f29c92258606b62c4f37fd3a221a13038af47cb Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Thu, 19 Sep 2019 19:48:11 -0400 Subject: [PATCH 07/13] Training done --- .../character_recognition/mlp.cu | 377 +++++++++++++++++- .../character_recognition/mlp.h | 82 ++++ Project2-Character-Recognition/src/main.cpp | 80 +++- 3 files changed, 500 insertions(+), 39 deletions(-) diff --git a/Project2-Character-Recognition/character_recognition/mlp.cu b/Project2-Character-Recognition/character_recognition/mlp.cu index 5a3ed7f..d1c9568 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.cu +++ b/Project2-Character-Recognition/character_recognition/mlp.cu @@ -1,27 +1,364 @@ #include #include +#include +#include +#include +#include +#include #include "common.h" #include "mlp.h" +#include + +#define THREADS_PER_BLOCK 256 + namespace CharacterRecognition { - using Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } - - // TODO: __global__ - - /** - * Example of use case (follow how you did it in stream compaction) - */ - /*void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - } - */ - - // TODO: implement required elements for MLP sections 1 and 2 here + using namespace std; + using Common::PerformanceTimer; + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } + + double learningRate; +// Matrix* W1, * W2, * B1, * B2, *IN, *H, *Y, *X; + shared_ptr W1, W2, B1, B2, IN, H, Y, X;; + + int inputN, hiddenN, outputN; + + // Fill the array A(nr_rows_A, nr_cols_A) with random numbers on GPU + void GPU_fill_rand(float* A, int nr_rows_A, int nr_cols_A) { + curandGenerator_t prng; + curandCreateGenerator(&prng, CURAND_RNG_PSEUDO_XORWOW); + curandSetPseudoRandomGeneratorSeed(prng, (unsigned long long) clock()); + // Fill the array with random numbers on the device + curandGenerateUniform(prng, A, nr_rows_A * nr_cols_A); + cudaDeviceSynchronize(); + checkCUDAError("GPU_fill_rand FAILED"); + } + + void GPU_fill_rand(Matrix* p_matrix) { + GPU_fill_rand(p_matrix->dev_data, p_matrix->numRow, p_matrix->numCol); + } + + __global__ void kernAdd(float* A, float* B, int n) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx >= n) return; + A[idx] += B[idx]; + } + + __global__ void kernSubtract(float* A, const float* B, int n) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx >= n) return; + A[idx] -= B[idx]; + } + + __global__ void kernSubtract(const float* A, const float* B, float*C, int n) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx >= n) return; + C[idx] = A[idx] - B[idx]; + } + + __global__ void kernDiffSquare(const float* A, const float* B, float* C, int n) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx >= n) return; + const float tmp = A[idx] - B[idx]; + C[idx] = tmp * tmp; + } + + __global__ void generate_in_a_b(float* A, float a, float b, int N) { + + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx >= N) return; + A[idx] = (b - a) * A[idx] + a; + } + + __global__ void generate_random_numbers(float* numbers, int N) { + + int i = threadIdx.x + blockIdx.x * blockDim.x; + if (i >= N) return; + curandState state; + curand_init(clock64(), i, 0, &state); + numbers[i] = curand_uniform(&state); + } + + __global__ void kernSigmoid(float* numbers, int N) { + int i = threadIdx.x + blockIdx.x * blockDim.x; + if (i >= N) return; + numbers[i] = 1.0 / (1.0 + std::exp(-numbers[i])); + } + + __global__ void kernSigmoidPrime(float* numbers, int N) { + int i = threadIdx.x + blockIdx.x * blockDim.x; + if (i >= N) return; + float tmp = std::exp(-numbers[i]); + numbers[i] = tmp / ( (1.f + tmp) * (1.f + tmp) ); + } + + __global__ void kernMultiply(float* numbers, float constant, int N) { + int i = threadIdx.x + blockIdx.x * blockDim.x; + if (i >= N) return; + numbers[i] *= constant; + } + + __global__ void kernMultiplyMatrix(float* numbers, const float* other, int N) { + int i = threadIdx.x + blockIdx.x * blockDim.x; + if (i >= N) return; + numbers[i] *= other[i]; + } + + + void Matrix::initWithRandom() { + GPU_fill_rand(dev_data, numRow, numCol); + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + float scale = 10.0f/std::sqrtf(n); // TODO: find a better initialization value!! + generate_in_a_b << > > (dev_data, -scale, scale, n); + } + + void Matrix::initWithZero() { + memset(data, 0, dataSize); + cudaMemset(dev_data, 0, dataSize); + } + + void Matrix::initWithTest() { + for (size_t row = 0; row < numRow; row++) { + for (size_t col = 0; col < numCol; col++) { + data[row * numCol + col] = (float)(row * numCol + col + 1.0f) / 10.f; + } + } + copyToDevice(); + } + + Matrix* Matrix::dot(const Matrix* other) const { + // C(m, n) = A(m, k) * B(k, n) + int m = numRow; + int k = numCol; + if (k != other->numRow) { + throw "Matrices not match"; + } + int n = other->numCol; + + Matrix* product = new Matrix(m, n); + // IMPORTANT!! + // cuBLAS uses column-major order, so reverse the order to get the correct result + // C: A*B, cuBLAS: B*A + gpu_blas_mmul(other->dev_data, dev_data, product->dev_data, n, k, m); + return product; + } + + void Matrix::add(const Matrix* other) { + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernAdd<<>>(dev_data, other->dev_data, n); + } + + Matrix* Matrix::subtract(const Matrix* other) const{ + Matrix* output = new Matrix(numRow, numCol); + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernSubtract << > > (dev_data, other->dev_data, output->dev_data, n); + + return output; + } + + + Matrix* Matrix::diffSquare(const Matrix* other) const { + Matrix* output = new Matrix(numRow, numCol); + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernDiffSquare << > > (dev_data, other->dev_data, output->dev_data, n); + + return output; + } + + void Matrix::subtract_inplace(const Matrix* other) { + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernSubtract << > > (dev_data, other->dev_data, n); + } + + void Matrix::sigmoid() { + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernSigmoid << > > (dev_data, n); + } + + void Matrix::sigmoidePrime() { + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernSigmoidPrime << > > (dev_data, n); + } + + Matrix* Matrix::multiply(const float constant) { + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernMultiply<< > > (dev_data, constant, n); + return this; + } + + Matrix* Matrix::multiply(const Matrix* other) { + int n = numRow * numCol; + int blockSize = (n + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + kernMultiplyMatrix << > > (dev_data, other->dev_data, n); + return this; + } + + Matrix* Matrix::transpose() const { + Matrix* trans = new Matrix(numCol , numRow); + int const m = numRow; + int const n = numCol; + float const alpha(1.0); + float const beta(0.0); + cublasHandle_t handle; + cublasCreate(&handle); + cublasSgeam(handle, CUBLAS_OP_T, CUBLAS_OP_N, m, n, &alpha, dev_data, n, &beta, trans->dev_data, m, trans->dev_data, m); + cublasDestroy(handle); + + return trans; + } + + + void init(int inputNeuron, int hiddenNeuron, int outputNeuron, double rate) + { + inputN = inputNeuron, hiddenN = hiddenNeuron, outputN = outputNeuron; + learningRate = rate; + + W1 = make_shared(inputNeuron, hiddenNeuron); + W2 = make_shared(hiddenNeuron, outputNeuron); + B1 = make_shared(1, hiddenNeuron); + B2 = make_shared(1, outputNeuron); + + W1->initWithRandom(); + W2->initWithRandom(); + + B1->initWithZero(); + B2->initWithZero(); + + W1->copyToHost(); + W2->copyToHost(); + B1->copyToHost(); + B2->copyToHost(); + } + + Matrix* computeOutput(const vector & input) { + vector> wrapper = { input }; + X = make_shared(wrapper); + X->copyToDevice(); + + H = shared_ptr( X->dot(W1.get()) ); + H->copyToHost(); + + H->add(B1.get()); + H->sigmoid(); + + Y = shared_ptr( H->dot(W2.get()) ); + Y->add(B2.get()); + Y->sigmoid(); + + return Y.get(); + } + + float learn(const vector expectedOutput) { + // compute gradients + + //dJdB2 = Y.subtract(Y2).multiply( H.dot(W2).add(B2).applyFunction(sigmoidePrime) ); + vector> wrapper = { expectedOutput }; + auto Y2 = std::make_unique(wrapper); // 1 x numOutput matrix + + auto dJdB2 = unique_ptr( Y->subtract(Y2.get()) ); + auto tmpH_W2 = unique_ptr( H->dot(W2.get()) ); + tmpH_W2->add(B2.get()); + tmpH_W2->sigmoidePrime(); + dJdB2->multiply(tmpH_W2.get()); + dJdB2->copyToHost(); + + // dJdB1 = dJdB2.dot(W2.transpose()).multiply(X.dot(W1).add(B1).applyFunction(sigmoidePrime)); + auto W2_trans = unique_ptr( W2->transpose() ); + auto dJdB1 = unique_ptr( dJdB2->dot(W2_trans.get()) ); + + auto tmpX_W1 = unique_ptr( X->dot(W1.get()) ); + tmpX_W1->add(B1.get()); + tmpX_W1->sigmoidePrime(); // X.dot(W1).add(B1).applyFunction(sigmoidePrime) + dJdB1->multiply(tmpX_W1.get()); + + // dJdW2 = H.transpose().dot(dJdB2); + auto dJdW2_tmp = unique_ptr( H->transpose() ); + auto dJdW2 = unique_ptr( dJdW2_tmp->dot(dJdB2.get()) ); + + // dJdW1 = X.transpose().dot(dJdB1); + auto dJdW1_tmp = unique_ptr( X->transpose() ); + auto dJdW1 = unique_ptr( dJdW1_tmp->dot(dJdB1.get()) ); + + // update weights + W1->subtract_inplace(dJdW1->multiply(learningRate)); + W2->subtract_inplace(dJdW2->multiply(learningRate)); + B1->subtract_inplace(dJdB1->multiply(learningRate)); + B2->subtract_inplace(dJdB2->multiply(learningRate)); + + // Calculate cost + auto diffSqr = unique_ptr(Y2->diffSquare(Y.get())); + thrust::device_ptr thrust_diffSqr(diffSqr->dev_data); + int n = diffSqr->numCol * diffSqr->numCol; + float cost = thrust::reduce(thrust_diffSqr, thrust_diffSqr + n, 0.f, thrust::plus()); + cost = std::sqrtf(cost / n); + + return cost; + } + + void unitTest() + { + // Test transpose + Matrix m(3, 2); + Matrix n(2, 2); + + m.initWithTest(); + n.initWithTest(); + + m.print(); + n.print(); + + //Matrix* pt = m.transpose(); + //pt->copyToHost(); + //pt->print(); + + // Test multiply + //m.multiply(3.0f); + //m.copyToHost(); + //m.print(); + + // Test sigmoid + //m.sigmoid(); + //m.copyToHost(); + //m.print(); + + // Test Dot + Matrix* p = m.dot(&n); + p->copyToHost(); + p->print(); + + } + + // Took from + // https://solarianprogrammer.com/2012/05/31/matrix-multiplication-cuda-cublas-curand-thrust/ + // Multiply the arrays A and B on GPU and save the result in C + // C(m,n) = A(m,k) * B(k,n) + void gpu_blas_mmul(const float* A, const float* B, float* C, const int m, const int k, const int n) { + int lda = m, ldb = k, ldc = m; + const float alf = 1; + const float bet = 0; + const float* alpha = &alf; + const float* beta = &bet; + + // Create a handle for CUBLAS + cublasHandle_t handle; + cublasCreate(&handle); + + // Do the actual multiplication + cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc); + + // Destroy the handle + cublasDestroy(handle); + } } diff --git a/Project2-Character-Recognition/character_recognition/mlp.h b/Project2-Character-Recognition/character_recognition/mlp.h index 2096228..1d422ed 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.h +++ b/Project2-Character-Recognition/character_recognition/mlp.h @@ -1,9 +1,91 @@ #pragma once #include "common.h" +#include +#include namespace CharacterRecognition { + using namespace std; Common::PerformanceTimer& timer(); + struct Matrix { + float* data; + float* dev_data; + int numRow; + int numCol; + size_t dataSize; + Matrix(int rows, int cols) : + numRow(rows), numCol(cols) + { + dataSize = rows * cols * sizeof(float); + data = (float*)malloc(dataSize); + cudaMalloc(&dev_data, dataSize); + } + + Matrix(const vector >& dataArr ) { + numRow = dataArr.size(); + if (!numRow) return; + numCol = dataArr[0].size(); + dataSize = numRow * numCol * sizeof(float); + data = (float*)malloc(dataSize); + cudaMalloc(&dev_data, dataSize); + + for (size_t row = 0; row < numRow; row++) { + for (size_t col = 0; col < numCol; col++) { + data[row * numCol + col] = dataArr[row][col]; + } + } + } + + void copyToHost() { + cudaMemcpy(data, dev_data, dataSize, cudaMemcpyDeviceToHost); + } + + void copyToDevice() { + cudaMemcpy(dev_data, data, dataSize, cudaMemcpyHostToDevice); + } + + void initWithRandom(); + void initWithTest(); + void initWithZero(); + + Matrix* dot(const Matrix* other) const; + Matrix* transpose() const; + Matrix* subtract(const Matrix* other) const; + Matrix* diffSquare(const Matrix* other) const; + + void add(const Matrix* other); + void sigmoid(); + void sigmoidePrime(); + void subtract_inplace(const Matrix* other); + Matrix* multiply(const float constant); + Matrix* multiply(const Matrix* other); + + + void print() { + std::cout << "-------- Matrix " << numRow << " X " << numCol << "-------- \n"; + for (int row = 0; row < numRow; row++) { + for (int col = 0; col < numCol; col++) { + printf("%f ", *(data + row*numCol + col)); + } + std::cout << std::endl; + } + } + + + ~Matrix() { + free(data); + cudaFree(dev_data); + } + }; // TODO: implement required elements for MLP sections 1 and 2 here + void init(int inputNeuron, int hiddenNeuron, int outputNeuron, double rate); + void GPU_fill_rand(float* A, int nr_rows_A, int nr_cols_A); + void GPU_fill_rand(Matrix* p_matrix); + void gpu_blas_mmul(const float* A, const float* B, float* C, const int m, const int k, const int n); + Matrix* computeOutput(const vector& input); + float learn(const vector expectedOutput); + + void unitTest(); + } diff --git a/Project2-Character-Recognition/src/main.cpp b/Project2-Character-Recognition/src/main.cpp index 57659f7..7874988 100644 --- a/Project2-Character-Recognition/src/main.cpp +++ b/Project2-Character-Recognition/src/main.cpp @@ -16,18 +16,13 @@ #include -const int SIZE = 1 << 8; // feel free to change the size of array -const int NPOT = SIZE - 3; // Non-Power-Of-Two -int *a = new int[SIZE]; -int *b = new int[SIZE]; -int *c = new int[SIZE]; +const int INPUT_N = 10201; +const int trainingSize = 52; // How many samples to train using namespace std; -void loadTrainingData(const string& dir, vector >& input, vector >& output) +void loadTrainingData(const string& dir, vector >& input, vector >& output) { - const int trainingSize = 52; // How many samples to train - const int numVals = 10201; input.resize(trainingSize); // 52 x 10201 output.resize(trainingSize); // 52 x 52 @@ -44,34 +39,81 @@ void loadTrainingData(const string& dir, vector >& input, vector< if (file.is_open()) { int tmp; for (size_t c = 0; c < 2; c++) file >> tmp; - input[i-1].resize(numVals); - for (size_t c = 0; c < numVals; c++) { + input[i-1].resize(INPUT_N); + for (size_t c = 0; c < INPUT_N; c++) { file >> input[i-1][c]; } file.close(); } - output[i - 1].resize(trainingSize, 0); output[i - 1][i - 1] = 1; } + // Normalization + for (size_t i = 0; i < trainingSize; i++) { + float mean = 0.f; + float variance = 0; + for (int j = 0; j < INPUT_N; j++) { + mean += input[i][j]; + } + mean /= INPUT_N; + for (int j = 0; j < INPUT_N; j++) { + variance += (input[i][j] - mean) * (input[i][j] - mean); + } + float stdv = std::sqrt(variance / INPUT_N); + for (int j = 0; j < INPUT_N; j++) { + input[i][j] = (input[i][j]) / (stdv + 0.00001f); + } + } } int main(int argc, char* argv[]) { + + //CharacterRecognition::unitTest(); + //system("pause"); // stop Win32 console from closing on exit + //return 1; + + const string dir = "..\\data-set\\"; - vector> input; - vector> output; + vector> input; + vector> output; -// loadTrainingData(dir, input, output); + const int hidden_N = 64; + loadTrainingData(dir, input, output); + CharacterRecognition::init(INPUT_N, hidden_N, trainingSize, 0.1f); // compute output - - CharacterRecognition::init(32, 8, 1, 0.5); + std::vector inputArr = { 1, 2 }; + + // train on 10 iterations + for (int i = 0; i < 40; i++) + { + float cost; + for (int j = 0; j < input.size(); j++) // train all 52 samples + { + CharacterRecognition::Matrix* m = CharacterRecognition::computeOutput(input[j]); + cost = CharacterRecognition::learn(output[j]); + } + cout << "#" << i + 1 << "/10 Cost: " << cost << endl; + } + + + // test + cout << "expected output : actual output" << endl; + for (int i = 0; i < input.size(); i++) // testing on last 10 examples + { + for (int j = 0; j < trainingSize; j++) + { + cout << output[i][j] << " "; + } + cout << endl; + + CharacterRecognition::Matrix* result = CharacterRecognition::computeOutput(input[i]); + result->copyToHost(); + result->print(); + } system("pause"); // stop Win32 console from closing on exit - delete[] a; - delete[] b; - delete[] c; } From 5759d07b76b7c3c556f1e89ecf53b4ea683704b8 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Thu, 19 Sep 2019 20:34:14 -0400 Subject: [PATCH 08/13] Update README --- Project2-Character-Recognition/README.md | 23 +++++++++++++----- Project2-Character-Recognition/img/output.png | Bin 0 -> 117507 bytes .../img/time_neurons.PNG | Bin 0 -> 19163 bytes Project2-Character-Recognition/src/main.cpp | 16 ++++++------ 4 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 Project2-Character-Recognition/img/output.png create mode 100644 Project2-Character-Recognition/img/time_neurons.PNG diff --git a/Project2-Character-Recognition/README.md b/Project2-Character-Recognition/README.md index 4503fac..8042e2a 100644 --- a/Project2-Character-Recognition/README.md +++ b/Project2-Character-Recognition/README.md @@ -3,12 +3,23 @@ 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) +* Gangzheng Tong + * www.gtong.me +* Tested on: Windows 10, i7-8th Gen @ 2.2GHz 16GB, RTX 2070 8GB (Personal Laptop) -### (TODO: Your README) +![Screenshot](img/output.png) +![Screenshot](img/time_neurons.PNG) -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +### Features Implemented +In this project I implemented the following features: +1. Loading data from files +2. Forward and backward propagation implemented on GPU +3. Wrap cuBLAS, thrust and my custom kernel into a Matrix struct and make it easy to use; could also be useful for future projects +4. Use C++ smart pointers to manage memory and avoid memory leak all at once +5. Test the time on different number of neurons +However, I'm not able to predict the character given training samples. The cost fluctuates between 0.2 and 0.3 and seems not dropping within 40 iterations. I did unit tests on every kernel and didn't find anything wrong. Maybe it's due to the limited number of training samples or inappropriate initial weights and bias. + +### A Few Observations +1. GPU is capable of handling large throughput. With the increasing # of hidden neurons, the data becomes huge (10212 * 2048 floats for a weight matrix) but my RTX 2070 was able to complete on iteration under 2 seconds. That's 52 samples and a dozen of big matrix operations. +2. C-Style matrix is typically row-major, but CUDA matrix is colmn-major. I spent a lot of time debugging the matrix dot production being unware of this. diff --git a/Project2-Character-Recognition/img/output.png b/Project2-Character-Recognition/img/output.png new file mode 100644 index 0000000000000000000000000000000000000000..0cef2dcb5b6e154696f53e321164d5d80714b87b GIT binary patch literal 117507 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

(t+sqBrVG;P)!bB?`~t(y!rZ?S$pM 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 literal 0 HcmV?d00001 diff --git a/Project2-Character-Recognition/img/time_neurons.PNG b/Project2-Character-Recognition/img/time_neurons.PNG new file mode 100644 index 0000000000000000000000000000000000000000..d62b13bf77a94a985b2b297645682af0ec6c539c GIT binary patch literal 19163 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 z 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 literal 0 HcmV?d00001 diff --git a/Project2-Character-Recognition/src/main.cpp b/Project2-Character-Recognition/src/main.cpp index 7874988..2830b07 100644 --- a/Project2-Character-Recognition/src/main.cpp +++ b/Project2-Character-Recognition/src/main.cpp @@ -17,6 +17,8 @@ const int INPUT_N = 10201; +const int HIDDEN_N = 64; + const int trainingSize = 52; // How many samples to train using namespace std; @@ -62,26 +64,22 @@ void loadTrainingData(const string& dir, vector >& input, vector> input; vector> output; - const int hidden_N = 64; loadTrainingData(dir, input, output); - CharacterRecognition::init(INPUT_N, hidden_N, trainingSize, 0.1f); + CharacterRecognition::init(INPUT_N, HIDDEN_N, trainingSize, 0.01f); // compute output std::vector inputArr = { 1, 2 }; @@ -89,16 +87,18 @@ int main(int argc, char* argv[]) { // train on 10 iterations for (int i = 0; i < 40; i++) { + CharacterRecognition::timer().startCpuTimer(); float cost; for (int j = 0; j < input.size(); j++) // train all 52 samples { CharacterRecognition::Matrix* m = CharacterRecognition::computeOutput(input[j]); cost = CharacterRecognition::learn(output[j]); } - cout << "#" << i + 1 << "/10 Cost: " << cost << endl; + CharacterRecognition::timer().endCpuTimer(); + float time = CharacterRecognition::timer().getCpuElapsedTimeForPreviousOperation(); + cout << "#" << i + 1 << "/40 Cost: " << cost << " Took time: " << time << endl; } - // test cout << "expected output : actual output" << endl; for (int i = 0; i < input.size(); i++) // testing on last 10 examples From 9a66923442c0388f27ef5b1551e25500139bbfa3 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Thu, 19 Sep 2019 20:34:30 -0400 Subject: [PATCH 09/13] Clean code --- .../character_recognition/mlp.cu | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Project2-Character-Recognition/character_recognition/mlp.cu b/Project2-Character-Recognition/character_recognition/mlp.cu index d1c9568..806142d 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.cu +++ b/Project2-Character-Recognition/character_recognition/mlp.cu @@ -22,9 +22,7 @@ namespace CharacterRecognition { } double learningRate; -// Matrix* W1, * W2, * B1, * B2, *IN, *H, *Y, *X; shared_ptr W1, W2, B1, B2, IN, H, Y, X;; - int inputN, hiddenN, outputN; // Fill the array A(nr_rows_A, nr_cols_A) with random numbers on GPU @@ -232,14 +230,8 @@ namespace CharacterRecognition { W1->initWithRandom(); W2->initWithRandom(); - B1->initWithZero(); B2->initWithZero(); - - W1->copyToHost(); - W2->copyToHost(); - B1->copyToHost(); - B2->copyToHost(); } Matrix* computeOutput(const vector & input) { @@ -248,7 +240,6 @@ namespace CharacterRecognition { X->copyToDevice(); H = shared_ptr( X->dot(W1.get()) ); - H->copyToHost(); H->add(B1.get()); H->sigmoid(); @@ -261,8 +252,7 @@ namespace CharacterRecognition { } float learn(const vector expectedOutput) { - // compute gradients - + // Compute gradients //dJdB2 = Y.subtract(Y2).multiply( H.dot(W2).add(B2).applyFunction(sigmoidePrime) ); vector> wrapper = { expectedOutput }; auto Y2 = std::make_unique(wrapper); // 1 x numOutput matrix From 97c62cf6658887fb01e2cbae9527cecac61b3c2f Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Thu, 19 Sep 2019 21:11:31 -0400 Subject: [PATCH 10/13] Scan done --- Project2-Stream-Compaction/README.md | 10 +++++---- .../stream_compaction/cpu.cu | 4 ++-- .../stream_compaction/efficient.cu | 22 ++++++++----------- .../stream_compaction/efficient.h | 2 +- .../stream_compaction/naive.cu | 4 ++-- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Project2-Stream-Compaction/README.md b/Project2-Stream-Compaction/README.md index 0e38ddb..503cfb6 100644 --- a/Project2-Stream-Compaction/README.md +++ b/Project2-Stream-Compaction/README.md @@ -3,11 +3,13 @@ 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) +* Gangzheng Tong + * www.gtong.me +* Tested on: Windows 10, i7-8th Gen @ 2.2GHz 16GB, RTX 2070 8GB (Personal Laptop) + +![Screenshot](img/output.png) +![Screenshot](img/time_neurons.PNG) -### (TODO: Your README) Include analysis, etc. (Remember, this is public, so don't put anything here that you don't want to share with the world.) diff --git a/Project2-Stream-Compaction/stream_compaction/cpu.cu b/Project2-Stream-Compaction/stream_compaction/cpu.cu index fc03b6d..93c5e8d 100644 --- a/Project2-Stream-Compaction/stream_compaction/cpu.cu +++ b/Project2-Stream-Compaction/stream_compaction/cpu.cu @@ -40,7 +40,7 @@ namespace StreamCompaction { */ int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + // DONE int num = 0; for (int i = 0; i < n; i++) { if (idata[i] == 0) continue; @@ -57,7 +57,7 @@ namespace StreamCompaction { */ int compactWithScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); - // TODO + // DONE int* scanResult = (int*)malloc(n * sizeof(int)); // Scan diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index f8ca8fa..c524dea 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -46,9 +46,8 @@ 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(); - // TODO + void scan(int n, int *odata, const int *idata, bool useTimer) { + // DONE int* d_idata; int maxD = ilog2ceil(n); int nCeil = 1 << maxD; @@ -60,24 +59,22 @@ namespace StreamCompaction { int threadsPerBlock = 512; int blockSize = (nCeil + threadsPerBlock - 1) / threadsPerBlock; + if (useTimer) timer().startGpuTimer(); // Parallel Reduction for (int d = 0; d < maxD; d++) { kernReduction << > > (n, d, d_idata); - cudaDeviceSynchronize(); } kernSetZero << <1, 1 >> > (nCeil, d_idata); - cudaDeviceSynchronize(); // Down Sweep for (int d = maxD-1; d >= 0; d--) { kernDownSweep << > > (n, d, d_idata); - cudaDeviceSynchronize(); } + if (useTimer) timer().endGpuTimer(); cudaMemcpy(odata, d_idata, n * sizeof(int), cudaMemcpyDeviceToHost); cudaFree(d_idata); - // timer().endGpuTimer(); } /** @@ -90,8 +87,7 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO + // DONE int numOfCompacted = 0; int* d_idata; int* d_odata; @@ -105,14 +101,15 @@ namespace StreamCompaction { cudaMemcpy(d_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + timer().startGpuTimer(); int threadsPerBlock = 512; int blockSize = (n + threadsPerBlock - 1) / threadsPerBlock; kernMapToBoolean<<>>(n, d_bools, d_idata); - cudaDeviceSynchronize(); - scan(n, d_indices, d_bools); + // false: Not using the scan's timer + scan(n, d_indices, d_bools, false); + timer().endGpuTimer(); - cudaDeviceSynchronize(); int* lastIndex = d_indices + n - 1; cudaMemcpy(&numOfCompacted, lastIndex, sizeof(int), cudaMemcpyDeviceToHost); @@ -128,7 +125,6 @@ namespace StreamCompaction { cudaFree(d_bools); cudaFree(d_indices); - timer().endGpuTimer(); return (idata[n-1] > 0 ) ? ( numOfCompacted + 1 ) : numOfCompacted; } diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.h b/Project2-Stream-Compaction/stream_compaction/efficient.h index 803cb4f..5ba93b0 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.h +++ b/Project2-Stream-Compaction/stream_compaction/efficient.h @@ -6,7 +6,7 @@ namespace StreamCompaction { namespace Efficient { StreamCompaction::Common::PerformanceTimer& timer(); - void scan(int n, int *odata, const int *idata); + void scan(int n, int *odata, const int *idata, bool useTimer = true); int compact(int n, int *odata, const int *idata); } diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index e1740a2..674fd36 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -39,7 +39,6 @@ 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(); int* d_odata; int* d_idata; @@ -50,6 +49,7 @@ namespace StreamCompaction { int threadsPerBlock = 512; int blockSize = (n + threadsPerBlock - 1) / threadsPerBlock; + timer().startGpuTimer(); for (int offset = 1; offset < (n << 1); offset *= 2) { kernScan << > > (n, offset, d_odata, d_idata); cudaDeviceSynchronize(); @@ -58,6 +58,7 @@ namespace StreamCompaction { d_odata = d_idata; d_idata = tmp; } + timer().endGpuTimer(); cudaMemcpy(d_idata, d_odata, n * sizeof(int), cudaMemcpyDeviceToDevice); kernRightShift << > > (n, d_odata, d_idata); @@ -66,7 +67,6 @@ namespace StreamCompaction { cudaFree(d_idata); cudaFree(d_odata); - timer().endGpuTimer(); } } } From c02b0f3060390ceac9b37c955328bfba820b1aec Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Thu, 19 Sep 2019 22:49:30 -0400 Subject: [PATCH 11/13] Updata README --- Project2-Stream-Compaction/README.md | 72 +- Project2-Stream-Compaction/img/N.PNG | Bin 0 -> 45304 bytes Project2-Stream-Compaction/img/block_size.PNG | Bin 0 -> 41530 bytes .../output_data/BLOCK_SIZE.csv | 0 Project2-Stream-Compaction/src/cxxopts.hpp | 2207 +++++++++++++++++ Project2-Stream-Compaction/src/main.cpp | 89 +- .../stream_compaction/common.cu | 1 - .../stream_compaction/common.h | 3 + .../stream_compaction/efficient.cu | 4 +- .../stream_compaction/naive.cu | 2 +- Project2-Stream-Compaction/test_blockSize.bat | 6 + README.md | 11 +- 12 files changed, 2376 insertions(+), 19 deletions(-) create mode 100644 Project2-Stream-Compaction/img/N.PNG create mode 100644 Project2-Stream-Compaction/img/block_size.PNG create mode 100644 Project2-Stream-Compaction/output_data/BLOCK_SIZE.csv create mode 100644 Project2-Stream-Compaction/src/cxxopts.hpp create mode 100644 Project2-Stream-Compaction/test_blockSize.bat diff --git a/Project2-Stream-Compaction/README.md b/Project2-Stream-Compaction/README.md index 503cfb6..f83b5e2 100644 --- a/Project2-Stream-Compaction/README.md +++ b/Project2-Stream-Compaction/README.md @@ -7,10 +7,74 @@ CUDA Stream Compaction * www.gtong.me * Tested on: Windows 10, i7-8th Gen @ 2.2GHz 16GB, RTX 2070 8GB (Personal Laptop) -![Screenshot](img/output.png) -![Screenshot](img/time_neurons.PNG) +![Screenshot](img/block_size.PNG) +![Screenshot](img/N.png) -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +### Features Implemented +In this project I implemented all features required. Tested with up to `2^26` elements and all passed. +The project will run different scan and stream compaction algorithms and report the timing. +To make it easy to dump the testing, I added some automation code so it can be run with a batch file. + +### Questions +1. By trying different block size, I concluded that it performs the best when each block contains 256 threads. While theoretically my GPU can run up to 1024 threads concurrently, the number of threads is limited by other factors such as the number of registers. For this particular algorithm, it's possbile that the GPU cannot schudule all 1024 threads to run at once. +2. For the detailed compairson see the chart above. It's obvious to see that with effcient scan outperforms naive as the array size gets larger. The thrust implementation is the fastest when the array size is huge. +3. The memeory latency is clearly the bottleneck when the array size is small, which explains why even the trust implementation failed to compete with CPU one when the number of elements is smaller than `2^16`. +4. As array size grows, the memory bandwidth becomes the bottleneck, especially for Naive implementation, which suffers greatly from the data incoherency. Thrust is probalbly utilizes the shared memeory and cahce to overcome the limitation. + +Raw Output +``` +**************** +** SCAN TESTS ** +**************** + [ 17 29 47 28 31 5 24 33 0 16 12 15 20 ... 33 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 4.6704ms (std::chrono Measured) + [ 0 17 46 93 121 152 157 181 214 214 230 242 257 ... 25687915 25687948 ] +==== cpu scan, non-power-of-two ==== + elapsed time: 1.6061ms (std::chrono Measured) + [ 0 17 46 93 121 152 157 181 214 214 230 242 257 ... 25687815 25687841 ] + passed +==== naive scan, power-of-two ==== + elapsed time: 1.48669ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 1.37837ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.649216ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.658624ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 0.182272ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 0.218432ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 1 1 3 2 3 1 2 1 0 2 2 3 0 ... 1 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 2.5317ms (std::chrono Measured) + [ 1 1 3 2 3 1 2 1 2 2 3 3 2 ... 2 1 ] + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 2.4355ms (std::chrono Measured) + [ 1 1 3 2 3 1 2 1 2 2 3 3 2 ... 2 2 ] + passed +==== cpu compact with scan ==== + elapsed time: 6.1908ms (std::chrono Measured) + [ 1 1 3 2 3 1 2 1 2 2 3 3 2 ... 2 1 ] + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 1.02813ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 1.06282ms (CUDA Measured) + passed +``` \ No newline at end of file diff --git a/Project2-Stream-Compaction/img/N.PNG b/Project2-Stream-Compaction/img/N.PNG new file mode 100644 index 0000000000000000000000000000000000000000..4b2e166571a2bafc067a7c505e590454977d12bb GIT binary patch literal 45304 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 SJ)PgE4_IAKty;xC{67Hc4ScNt literal 0 HcmV?d00001 diff --git a/Project2-Stream-Compaction/img/block_size.PNG b/Project2-Stream-Compaction/img/block_size.PNG new file mode 100644 index 0000000000000000000000000000000000000000..4f8e6c2ebccb89cccd095b0ce43f0052b0c87940 GIT binary patch literal 41530 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 =XJ$iwL+FnjbYtFJ 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 KTZ?+6C;kuRwPnEo literal 0 HcmV?d00001 diff --git a/Project2-Stream-Compaction/output_data/BLOCK_SIZE.csv b/Project2-Stream-Compaction/output_data/BLOCK_SIZE.csv new file mode 100644 index 0000000..e69de29 diff --git a/Project2-Stream-Compaction/src/cxxopts.hpp b/Project2-Stream-Compaction/src/cxxopts.hpp new file mode 100644 index 0000000..ed3c6a2 --- /dev/null +++ b/Project2-Stream-Compaction/src/cxxopts.hpp @@ -0,0 +1,2207 @@ +/* + +Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +#ifndef CXXOPTS_HPP_INCLUDED +#define CXXOPTS_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cpp_lib_optional +#include +#define CXXOPTS_HAS_OPTIONAL +#endif + +#ifndef CXXOPTS_VECTOR_DELIMITER +#define CXXOPTS_VECTOR_DELIMITER ',' +#endif + +#define CXXOPTS__VERSION_MAJOR 2 +#define CXXOPTS__VERSION_MINOR 2 +#define CXXOPTS__VERSION_PATCH 0 + +namespace cxxopts +{ + static constexpr struct { + uint8_t major, minor, patch; + } version = { + CXXOPTS__VERSION_MAJOR, + CXXOPTS__VERSION_MINOR, + CXXOPTS__VERSION_PATCH + }; +} + +//when we ask cxxopts to use Unicode, help strings are processed using ICU, +//which results in the correct lengths being computed for strings when they +//are formatted for the help output +//it is necessary to make sure that can be found by the +//compiler, and that icu-uc is linked in to the binary. + +#ifdef CXXOPTS_USE_UNICODE +#include + +namespace cxxopts +{ + typedef icu::UnicodeString String; + + inline + String + toLocalString(std::string s) + { + return icu::UnicodeString::fromUTF8(std::move(s)); + } + + class UnicodeStringIterator : public + std::iterator + { + public: + + UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos) + : s(string) + , i(pos) + { + } + + value_type + operator*() const + { + return s->char32At(i); + } + + bool + operator==(const UnicodeStringIterator& rhs) const + { + return s == rhs.s && i == rhs.i; + } + + bool + operator!=(const UnicodeStringIterator& rhs) const + { + return !(*this == rhs); + } + + UnicodeStringIterator& + operator++() + { + ++i; + return *this; + } + + UnicodeStringIterator + operator+(int32_t v) + { + return UnicodeStringIterator(s, i + v); + } + + private: + const icu::UnicodeString* s; + int32_t i; + }; + + inline + String& + stringAppend(String&s, String a) + { + return s.append(std::move(a)); + } + + inline + String& + stringAppend(String& s, int n, UChar32 c) + { + for (int i = 0; i != n; ++i) + { + s.append(c); + } + + return s; + } + + template + String& + stringAppend(String& s, Iterator begin, Iterator end) + { + while (begin != end) + { + s.append(*begin); + ++begin; + } + + return s; + } + + inline + size_t + stringLength(const String& s) + { + return s.length(); + } + + inline + std::string + toUTF8String(const String& s) + { + std::string result; + s.toUTF8String(result); + + return result; + } + + inline + bool + empty(const String& s) + { + return s.isEmpty(); + } +} + +namespace std +{ + inline + cxxopts::UnicodeStringIterator + begin(const icu::UnicodeString& s) + { + return cxxopts::UnicodeStringIterator(&s, 0); + } + + inline + cxxopts::UnicodeStringIterator + end(const icu::UnicodeString& s) + { + return cxxopts::UnicodeStringIterator(&s, s.length()); + } +} + +//ifdef CXXOPTS_USE_UNICODE +#else + +namespace cxxopts +{ + typedef std::string String; + + template + T + toLocalString(T&& t) + { + return std::forward(t); + } + + inline + size_t + stringLength(const String& s) + { + return s.length(); + } + + inline + String& + stringAppend(String&s, String a) + { + return s.append(std::move(a)); + } + + inline + String& + stringAppend(String& s, size_t n, char c) + { + return s.append(n, c); + } + + template + String& + stringAppend(String& s, Iterator begin, Iterator end) + { + return s.append(begin, end); + } + + template + std::string + toUTF8String(T&& t) + { + return std::forward(t); + } + + inline + bool + empty(const std::string& s) + { + return s.empty(); + } +} + +//ifdef CXXOPTS_USE_UNICODE +#endif + +namespace cxxopts +{ + namespace + { +#ifdef _WIN32 + const std::string LQUOTE("\'"); + const std::string RQUOTE("\'"); +#else + const std::string LQUOTE("‘"); + const std::string RQUOTE("’"); +#endif + } + + class Value : public std::enable_shared_from_this + { + public: + + virtual ~Value() = default; + + virtual + std::shared_ptr + clone() const = 0; + + virtual void + parse(const std::string& text) const = 0; + + virtual void + parse() const = 0; + + virtual bool + has_default() const = 0; + + virtual bool + is_container() const = 0; + + virtual bool + has_implicit() const = 0; + + virtual std::string + get_default_value() const = 0; + + virtual std::string + get_implicit_value() const = 0; + + virtual std::shared_ptr + default_value(const std::string& value) = 0; + + virtual std::shared_ptr + implicit_value(const std::string& value) = 0; + + virtual std::shared_ptr + no_implicit_value() = 0; + + virtual bool + is_boolean() const = 0; + }; + + class OptionException : public std::exception + { + public: + OptionException(const std::string& message) + : m_message(message) + { + } + + virtual const char* + what() const noexcept + { + return m_message.c_str(); + } + + private: + std::string m_message; + }; + + class OptionSpecException : public OptionException + { + public: + + OptionSpecException(const std::string& message) + : OptionException(message) + { + } + }; + + class OptionParseException : public OptionException + { + public: + OptionParseException(const std::string& message) + : OptionException(message) + { + } + }; + + class option_exists_error : public OptionSpecException + { + public: + option_exists_error(const std::string& option) + : OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists") + { + } + }; + + class invalid_option_format_error : public OptionSpecException + { + public: + invalid_option_format_error(const std::string& format) + : OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE) + { + } + }; + + class option_syntax_exception : public OptionParseException { + public: + option_syntax_exception(const std::string& text) + : OptionParseException("Argument " + LQUOTE + text + RQUOTE + + " starts with a - but has incorrect syntax") + { + } + }; + + class option_not_exists_exception : public OptionParseException + { + public: + option_not_exists_exception(const std::string& option) + : OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist") + { + } + }; + + class missing_argument_exception : public OptionParseException + { + public: + missing_argument_exception(const std::string& option) + : OptionParseException( + "Option " + LQUOTE + option + RQUOTE + " is missing an argument" + ) + { + } + }; + + class option_requires_argument_exception : public OptionParseException + { + public: + option_requires_argument_exception(const std::string& option) + : OptionParseException( + "Option " + LQUOTE + option + RQUOTE + " requires an argument" + ) + { + } + }; + + class option_not_has_argument_exception : public OptionParseException + { + public: + option_not_has_argument_exception + ( + const std::string& option, + const std::string& arg + ) + : OptionParseException( + "Option " + LQUOTE + option + RQUOTE + + " does not take an argument, but argument " + + LQUOTE + arg + RQUOTE + " given" + ) + { + } + }; + + class option_not_present_exception : public OptionParseException + { + public: + option_not_present_exception(const std::string& option) + : OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present") + { + } + }; + + class argument_incorrect_type : public OptionParseException + { + public: + argument_incorrect_type + ( + const std::string& arg + ) + : OptionParseException( + "Argument " + LQUOTE + arg + RQUOTE + " failed to parse" + ) + { + } + }; + + class option_required_exception : public OptionParseException + { + public: + option_required_exception(const std::string& option) + : OptionParseException( + "Option " + LQUOTE + option + RQUOTE + " is required but not present" + ) + { + } + }; + + template + void throw_or_mimic(const std::string& text) + { + static_assert(std::is_base_of::value, + "throw_or_mimic only works on std::exception and " + "deriving classes"); + +#ifndef CXXOPTS_NO_EXCEPTIONS + // If CXXOPTS_NO_EXCEPTIONS is not defined, just throw + throw T{text}; +#else + // Otherwise manually instantiate the exception, print what() to stderr, + // and abort + T exception{text}; + std::cerr << exception.what() << std::endl; + std::cerr << "Aborting (exceptions disabled)..." << std::endl; + std::abort(); +#endif + } + + namespace values + { + namespace + { + std::basic_regex integer_pattern + ("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)"); + std::basic_regex truthy_pattern + ("(t|T)(rue)?|1"); + std::basic_regex falsy_pattern + ("(f|F)(alse)?|0"); + } + + namespace detail + { + template + struct SignedCheck; + + template + struct SignedCheck + { + template + void + operator()(bool negative, U u, const std::string& text) + { + if (negative) + { + if (u > static_cast((std::numeric_limits::min)())) + { + throw_or_mimic(text); + } + } + else + { + if (u > static_cast((std::numeric_limits::max)())) + { + throw_or_mimic(text); + } + } + } + }; + + template + struct SignedCheck + { + template + void + operator()(bool, U, const std::string&) {} + }; + + template + void + check_signed_range(bool negative, U value, const std::string& text) + { + SignedCheck::is_signed>()(negative, value, text); + } + } + + template + R + checked_negate(T&& t, const std::string&, std::true_type) + { + // if we got to here, then `t` is a positive number that fits into + // `R`. So to avoid MSVC C4146, we first cast it to `R`. + // See https://github.com/jarro2783/cxxopts/issues/62 for more details. + return -static_cast(t-1)-1; + } + + template + T + checked_negate(T&& t, const std::string& text, std::false_type) + { + throw_or_mimic(text); + return t; + } + + template + void + integer_parser(const std::string& text, T& value) + { + std::smatch match; + std::regex_match(text, match, integer_pattern); + + if (match.length() == 0) + { + throw_or_mimic(text); + } + + if (match.length(4) > 0) + { + value = 0; + return; + } + + using US = typename std::make_unsigned::type; + + constexpr bool is_signed = std::numeric_limits::is_signed; + const bool negative = match.length(1) > 0; + const uint8_t base = match.length(2) > 0 ? 16 : 10; + + auto value_match = match[3]; + + US result = 0; + + for (auto iter = value_match.first; iter != value_match.second; ++iter) + { + US digit = 0; + + if (*iter >= '0' && *iter <= '9') + { + digit = static_cast(*iter - '0'); + } + else if (base == 16 && *iter >= 'a' && *iter <= 'f') + { + digit = static_cast(*iter - 'a' + 10); + } + else if (base == 16 && *iter >= 'A' && *iter <= 'F') + { + digit = static_cast(*iter - 'A' + 10); + } + else + { + throw_or_mimic(text); + } + + US next = result * base + digit; + if (result > next) + { + throw_or_mimic(text); + } + + result = next; + } + + detail::check_signed_range(negative, result, text); + + if (negative) + { + value = checked_negate(result, + text, + std::integral_constant()); + } + else + { + value = static_cast(result); + } + } + + template + void stringstream_parser(const std::string& text, T& value) + { + std::stringstream in(text); + in >> value; + if (!in) { + throw_or_mimic(text); + } + } + + inline + void + parse_value(const std::string& text, uint8_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, int8_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, uint16_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, int16_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, uint32_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, int32_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, uint64_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, int64_t& value) + { + integer_parser(text, value); + } + + inline + void + parse_value(const std::string& text, bool& value) + { + std::smatch result; + std::regex_match(text, result, truthy_pattern); + + if (!result.empty()) + { + value = true; + return; + } + + std::regex_match(text, result, falsy_pattern); + if (!result.empty()) + { + value = false; + return; + } + + throw_or_mimic(text); + } + + inline + void + parse_value(const std::string& text, std::string& value) + { + value = text; + } + + // The fallback parser. It uses the stringstream parser to parse all types + // that have not been overloaded explicitly. It has to be placed in the + // source code before all other more specialized templates. + template + void + parse_value(const std::string& text, T& value) { + stringstream_parser(text, value); + } + + template + void + parse_value(const std::string& text, std::vector& value) + { + std::stringstream in(text); + std::string token; + while(in.eof() == false && std::getline(in, token, CXXOPTS_VECTOR_DELIMITER)) { + T v; + parse_value(token, v); + value.emplace_back(std::move(v)); + } + } + +#ifdef CXXOPTS_HAS_OPTIONAL + template + void + parse_value(const std::string& text, std::optional& value) + { + T result; + parse_value(text, result); + value = std::move(result); + } +#endif + + inline + void parse_value(const std::string& text, char& c) + { + if (text.length() != 1) + { + throw_or_mimic(text); + } + + c = text[0]; + } + + template + struct type_is_container + { + static constexpr bool value = false; + }; + + template + struct type_is_container> + { + static constexpr bool value = true; + }; + + template + class abstract_value : public Value + { + using Self = abstract_value; + + public: + abstract_value() + : m_result(std::make_shared()) + , m_store(m_result.get()) + { + } + + abstract_value(T* t) + : m_store(t) + { + } + + virtual ~abstract_value() = default; + + abstract_value(const abstract_value& rhs) + { + if (rhs.m_result) + { + m_result = std::make_shared(); + m_store = m_result.get(); + } + else + { + m_store = rhs.m_store; + } + + m_default = rhs.m_default; + m_implicit = rhs.m_implicit; + m_default_value = rhs.m_default_value; + m_implicit_value = rhs.m_implicit_value; + } + + void + parse(const std::string& text) const + { + parse_value(text, *m_store); + } + + bool + is_container() const + { + return type_is_container::value; + } + + void + parse() const + { + parse_value(m_default_value, *m_store); + } + + bool + has_default() const + { + return m_default; + } + + bool + has_implicit() const + { + return m_implicit; + } + + std::shared_ptr + default_value(const std::string& value) + { + m_default = true; + m_default_value = value; + return shared_from_this(); + } + + std::shared_ptr + implicit_value(const std::string& value) + { + m_implicit = true; + m_implicit_value = value; + return shared_from_this(); + } + + std::shared_ptr + no_implicit_value() + { + m_implicit = false; + return shared_from_this(); + } + + std::string + get_default_value() const + { + return m_default_value; + } + + std::string + get_implicit_value() const + { + return m_implicit_value; + } + + bool + is_boolean() const + { + return std::is_same::value; + } + + const T& + get() const + { + if (m_store == nullptr) + { + return *m_result; + } + else + { + return *m_store; + } + } + + protected: + std::shared_ptr m_result; + T* m_store; + + bool m_default = false; + bool m_implicit = false; + + std::string m_default_value; + std::string m_implicit_value; + }; + + template + class standard_value : public abstract_value + { + public: + using abstract_value::abstract_value; + + std::shared_ptr + clone() const + { + return std::make_shared>(*this); + } + }; + + template <> + class standard_value : public abstract_value + { + public: + ~standard_value() = default; + + standard_value() + { + set_default_and_implicit(); + } + + standard_value(bool* b) + : abstract_value(b) + { + set_default_and_implicit(); + } + + std::shared_ptr + clone() const + { + return std::make_shared>(*this); + } + + private: + + void + set_default_and_implicit() + { + m_default = true; + m_default_value = "false"; + m_implicit = true; + m_implicit_value = "true"; + } + }; + } + + template + std::shared_ptr + value() + { + return std::make_shared>(); + } + + template + std::shared_ptr + value(T& t) + { + return std::make_shared>(&t); + } + + class OptionAdder; + + class OptionDetails + { + public: + OptionDetails + ( + const std::string& short_, + const std::string& long_, + const String& desc, + std::shared_ptr val + ) + : m_short(short_) + , m_long(long_) + , m_desc(desc) + , m_value(val) + , m_count(0) + { + } + + OptionDetails(const OptionDetails& rhs) + : m_desc(rhs.m_desc) + , m_count(rhs.m_count) + { + m_value = rhs.m_value->clone(); + } + + OptionDetails(OptionDetails&& rhs) = default; + + const String& + description() const + { + return m_desc; + } + + const Value& value() const { + return *m_value; + } + + std::shared_ptr + make_storage() const + { + return m_value->clone(); + } + + const std::string& + short_name() const + { + return m_short; + } + + const std::string& + long_name() const + { + return m_long; + } + + private: + std::string m_short; + std::string m_long; + String m_desc; + std::shared_ptr m_value; + int m_count; + }; + + struct HelpOptionDetails + { + std::string s; + std::string l; + String desc; + bool has_default; + std::string default_value; + bool has_implicit; + std::string implicit_value; + std::string arg_help; + bool is_container; + bool is_boolean; + }; + + struct HelpGroupDetails + { + std::string name; + std::string description; + std::vector options; + }; + + class OptionValue + { + public: + void + parse + ( + std::shared_ptr details, + const std::string& text + ) + { + ensure_value(details); + ++m_count; + m_value->parse(text); + } + + void + parse_default(std::shared_ptr details) + { + ensure_value(details); + m_default = true; + m_value->parse(); + } + + size_t + count() const noexcept + { + return m_count; + } + + // TODO: maybe default options should count towards the number of arguments + bool + has_default() const noexcept + { + return m_default; + } + + template + const T& + as() const + { + if (m_value == nullptr) { + throw_or_mimic("No value"); + } + +#ifdef CXXOPTS_NO_RTTI + return static_cast&>(*m_value).get(); +#else + return dynamic_cast&>(*m_value).get(); +#endif + } + + private: + void + ensure_value(std::shared_ptr details) + { + if (m_value == nullptr) + { + m_value = details->make_storage(); + } + } + + std::shared_ptr m_value; + size_t m_count = 0; + bool m_default = false; + }; + + class KeyValue + { + public: + KeyValue(std::string key_, std::string value_) + : m_key(std::move(key_)) + , m_value(std::move(value_)) + { + } + + const + std::string& + key() const + { + return m_key; + } + + const + std::string& + value() const + { + return m_value; + } + + template + T + as() const + { + T result; + values::parse_value(m_value, result); + return result; + } + + private: + std::string m_key; + std::string m_value; + }; + + class ParseResult + { + public: + + ParseResult( + const std::shared_ptr< + std::unordered_map> + >, + std::vector, + bool allow_unrecognised, + int&, char**&); + + size_t + count(const std::string& o) const + { + auto iter = m_options->find(o); + if (iter == m_options->end()) + { + return 0; + } + + auto riter = m_results.find(iter->second); + + return riter->second.count(); + } + + const OptionValue& + operator[](const std::string& option) const + { + auto iter = m_options->find(option); + + if (iter == m_options->end()) + { + throw_or_mimic(option); + } + + auto riter = m_results.find(iter->second); + + return riter->second; + } + + const std::vector& + arguments() const + { + return m_sequential; + } + + private: + + void + parse(int& argc, char**& argv); + + void + add_to_option(const std::string& option, const std::string& arg); + + bool + consume_positional(std::string a); + + void + parse_option + ( + std::shared_ptr value, + const std::string& name, + const std::string& arg = "" + ); + + void + parse_default(std::shared_ptr details); + + void + checked_parse_arg + ( + int argc, + char* argv[], + int& current, + std::shared_ptr value, + const std::string& name + ); + + const std::shared_ptr< + std::unordered_map> + > m_options; + std::vector m_positional; + std::vector::iterator m_next_positional; + std::unordered_set m_positional_set; + std::unordered_map, OptionValue> m_results; + + bool m_allow_unrecognised; + + std::vector m_sequential; + }; + + struct Option + { + Option + ( + const std::string& opts, + const std::string& desc, + const std::shared_ptr& value = ::cxxopts::value(), + const std::string& arg_help = "" + ) + : opts_(opts) + , desc_(desc) + , value_(value) + , arg_help_(arg_help) + { + } + + std::string opts_; + std::string desc_; + std::shared_ptr value_; + std::string arg_help_; + }; + + class Options + { + typedef std::unordered_map> + OptionMap; + public: + + Options(std::string program, std::string help_string = "") + : m_program(std::move(program)) + , m_help_string(toLocalString(std::move(help_string))) + , m_custom_help("[OPTION...]") + , m_positional_help("positional parameters") + , m_show_positional(false) + , m_allow_unrecognised(false) + , m_options(std::make_shared()) + , m_next_positional(m_positional.end()) + { + } + + Options& + positional_help(std::string help_text) + { + m_positional_help = std::move(help_text); + return *this; + } + + Options& + custom_help(std::string help_text) + { + m_custom_help = std::move(help_text); + return *this; + } + + Options& + show_positional_help() + { + m_show_positional = true; + return *this; + } + + Options& + allow_unrecognised_options() + { + m_allow_unrecognised = true; + return *this; + } + + ParseResult + parse(int& argc, char**& argv); + + OptionAdder + add_options(std::string group = ""); + + void + add_options + ( + const std::string& group, + std::initializer_list