summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--expt_0510.cu7
-rw-r--r--expt_0516.cu304
-rw-r--r--normal_distribution.cpp2
-rw-r--r--sortlib.cuh90
5 files changed, 348 insertions, 67 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4f66661..7ad8949 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -194,4 +194,14 @@ target_link_libraries(expt_0510 m stdc++)
set_target_properties(expt_0510 PROPERTIES
CUDA_SEPARABLE_COMPILATION ON)
set_target_properties(expt_0510 PROPERTIES CUDA_ARCHITECTURES "75")
-set_target_properties(expt_0510 PROPERTIES LINKER_LANGUAGE CUDA) \ No newline at end of file
+set_target_properties(expt_0510 PROPERTIES LINKER_LANGUAGE CUDA)
+
+
+add_executable(expt_0516 expt_0516.cu)
+target_link_libraries(expt_0516 m stdc++)
+
+set_target_properties(expt_0516 PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON)
+set_target_properties(expt_0516 PROPERTIES CUDA_ARCHITECTURES "75")
+set_target_properties(expt_0516 PROPERTIES LINKER_LANGUAGE CUDA)
+
diff --git a/expt_0510.cu b/expt_0510.cu
index 7616c13..3efad47 100644
--- a/expt_0510.cu
+++ b/expt_0510.cu
@@ -183,8 +183,7 @@ void readFile(char const *filename, long sample_length,
read_number = randomRow(total_row - sample_length - max_number - 256);
total_row = read_number;
// fprintf(stderr, "Skip %lu\n", read_number);
- for (long long i; read_number > 0 && fscanf(file, "%lld ", &i) != EOF;
- store_into_vector(i))
+ for (long long i; read_number > 0 && fscanf(file, "%lld ", &i) != EOF;)
read_number--;
}
@@ -225,7 +224,9 @@ int main(int argc, char const *argv[]) {
total_row = strtol(argv[3], nullptr, 10);
}
- readFile("normal_distribution.txt", test_size, total_row);
+ CustomSort::testSelf(sample_length);
+
+ readFile("normal_distribution.txt", sample_length, total_row, test_size);
printf("population: %zu, skip: %lu, test size: %zu, sample length: %zu | ",
population_vector.size(), total_row, test_size, sample_length);
diff --git a/expt_0516.cu b/expt_0516.cu
new file mode 100644
index 0000000..4d9be45
--- /dev/null
+++ b/expt_0516.cu
@@ -0,0 +1,304 @@
+// Experimental content: Test branch performance (optimized memory and output)
+#include "sortlib.cuh"
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <random>
+#include <vector>
+
+#ifndef NDEBUG
+#define P_ERR(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define P_ERR(...)
+#endif
+
+std::vector<unsigned long long> population_vector, sample_vector,
+ le_sample_vector;
+
+constexpr long DEFAULT_SAMPLE_LENGTH = 65535;
+constexpr size_t TEST_LENGTH = 32'768;
+// constexpr size_t TEST_LENGTH = 4096;
+// constexpr size_t RESERVED_BLOCK = 100;
+
+unsigned long long max_value = 0, min_value = 0xfffffffff;
+typedef std::pair<int, int> dim_pair_type;
+
+inline void store_into_vector(unsigned long long value) {
+ if (max_value < value) {
+ max_value = value;
+ }
+ if (min_value > value) {
+ min_value = value;
+ }
+ population_vector.push_back(value);
+}
+// #define TEST_BOUNDS
+
+__device__ long cuda_sample_length;
+__device__ key_type *cudaSampleItem, *cudaNormalSampleItem, *cudaPopulationItem;
+//__device__ bool *cdf_result;
+#ifdef TEST_BOUNDS
+__device__ unsigned insert_value;
+__device__ unsigned int index_max, index_min;
+#endif
+
+__global__ void initSample(key_type *sample, key_type *population) {
+ cudaSampleItem = sample;
+ cudaPopulationItem = population;
+ // cudaMalloc(&cdf_result, sizeof(bool) * TEST_LENGTH);
+ // cdf_result = nullptr;
+ // cdf_normal_result = nullptr;
+}
+
+__global__ void initNormalSample(key_type *normal_sample) {
+ cudaNormalSampleItem = normal_sample;
+}
+
+__global__ void kernel(unsigned long step, const double slice_size) {
+ auto custom_sort = CustomSort(cuda_sample_length, sizeof(key_type) * 8);
+ // printf("kernel1 step: %ld\n", step);
+ for (int i = 0; i < step; i++) {
+ auto tid = step * (blockIdx.x * blockDim.x + threadIdx.x) + i;
+
+ // printf("%d\n", tid);
+ auto _index = (int)(custom_sort.sample_cdf_custom_version(
+ cudaSampleItem, cudaPopulationItem[tid]) /
+ slice_size) -
+ 1;
+ // cdf_result[index] = true;
+ }
+}
+
+__global__ void kernel2(unsigned long step, const double slice_size) {
+
+ for (int i = 0; i < step; i++) {
+ auto tid = step * (blockIdx.x * blockDim.x + threadIdx.x) + i;
+ auto _index =
+ (int)(FactorySort::sample_cdf(cudaNormalSampleItem, cuda_sample_length,
+ cudaPopulationItem[tid]) /
+ slice_size) -
+ 1;
+ // cdf_result[index] = true;
+ }
+}
+
+__global__ void print2() {
+ /*for (int i = 0; i< SAMPLE_LENGTH; i++) {
+ printf("%llu ", cudaSampleItem[i]);
+ }
+ printf("\n");*/
+ printf("%lu\n", CustomSort::fast_log(cuda_sample_length));
+}
+
+__global__ void printFunction() {}
+
+__global__ void checkItems() {
+ for (int i = 0; i < cuda_sample_length; i++) {
+ printf("%lld ", cudaSampleItem[i]);
+ }
+ printf("\n");
+}
+
+void initCustomSampleCPU() {
+ auto sample_length = sample_vector.size();
+ auto tmp = new key_type[sample_length];
+
+ auto custom_sort = CustomSort(sample_length, 0);
+
+ for (size_t i = 0; i < sample_length; i++) {
+ tmp[i] = sample_vector[custom_sort.calculate_index(i) - 1];
+ }
+
+ memcpy(sample_vector.data(), tmp, sizeof(key_type) * sample_length);
+
+ delete[] tmp;
+}
+
+constexpr dim3 grid_dim = 32, block_dim = 32;
+
+bool checkTestSize() {}
+
+void run_kernel(size_t test_size, bool custom = true) {
+ // need description
+ unsigned long step = test_size / (grid_dim.x * block_dim.x);
+
+ // Only scale mode will use
+ auto scale = 2;
+ const unsigned long split_size = test_size * scale;
+ const auto slice_size = 1.0 / (double)split_size;
+
+ cudaEvent_t start, stop;
+ cudaEventCreate(&start);
+ cudaEventCreate(&stop);
+ cudaEventRecord(start, nullptr);
+ if (custom) {
+ kernel<<<grid_dim, block_dim>>>(step, slice_size);
+ } else {
+ kernel2<<<grid_dim, block_dim>>>(step, slice_size);
+ }
+
+ cudaDeviceSynchronize();
+ cudaEventRecord(stop, nullptr);
+ cudaEventSynchronize(stop);
+ float time;
+ cudaEventElapsedTime(&time, start, stop);
+ cudaEventDestroy(start);
+ cudaEventDestroy(stop);
+ if (time == 0) {
+ // printf("last error: %u\n", cudaGetLastError());
+ }
+ printf("%stime: %lf ", custom ? "custom " : "", time);
+ cudaDeviceSynchronize();
+
+ printFunction<<<1, 1>>>();
+ cudaDeviceSynchronize();
+}
+
+__global__ void freeStorageStage1() { cudaFree(cudaSampleItem); }
+
+__global__ void freeStorageStage2() {
+ cudaFree(cudaNormalSampleItem);
+ cudaFree(cudaPopulationItem);
+ // cudaFree(cdf_result);
+}
+
+unsigned long randomRow(unsigned long max_value_) {
+ std::random_device randomDevice;
+ std::mt19937 mt19937(randomDevice());
+ std::uniform_int_distribution<std::mt19937::result_type> dst(0, max_value_);
+ return dst(mt19937);
+}
+
+void readFile(char const *filename, long sample_length,
+ unsigned long &total_row,
+ unsigned long max_number = TEST_LENGTH) {
+ auto read_number = 0UL;
+ FILE *file = fopen(filename, "r");
+ assert(file);
+ P_ERR("Reading sample");
+ for (long long i;
+ read_number < max_number && fscanf(file, "%lld ", &i) != EOF;
+ store_into_vector(i))
+ read_number++;
+
+ if (total_row > 0) {
+ P_ERR("\rReading skip");
+ read_number = randomRow(total_row - sample_length - max_number - 256);
+ total_row = read_number;
+ // fprintf(stderr, "Skip %lu\n", read_number);
+ for (long long i; read_number > 0 && fscanf(file, "%lld ", &i) != EOF;)
+ read_number--;
+ }
+
+ P_ERR("\rReading population");
+ read_number = 0;
+
+ auto remain = sample_length + 256;
+ for (long long i; read_number < remain && fscanf(file, "%lld ", &i) != EOF;
+ store_into_vector(i))
+ read_number++;
+ fclose(file);
+ P_ERR("\r");
+}
+
+long pow_for_sample(long n) {
+ auto x = 2;
+ for (int i = 0; i < n; i++) {
+ x *= 2;
+ }
+ return x - 1;
+}
+
+__global__ void applyCudaSampleLength(long length) {
+ cuda_sample_length = length;
+}
+
+int main(int argc, char const *argv[]) {
+
+ auto test_size = TEST_LENGTH;
+ auto sample_length = DEFAULT_SAMPLE_LENGTH;
+ auto total_row = 0UL;
+
+ if (argc >= 2) {
+ test_size = strtol(argv[1], nullptr, 10);
+ }
+ if (argc >= 3) {
+ sample_length = pow_for_sample(strtol(argv[2], nullptr, 10));
+ }
+ if (argc >= 4) {
+ total_row = strtol(argv[3], nullptr, 10);
+ }
+
+ readFile("normal_distribution.txt", sample_length, total_row, test_size);
+
+ printf("population: %zu, skip: %lu, test size: %zu, sample length: %zu\n",
+ population_vector.size(), total_row, test_size, sample_length);
+
+ sample_vector = std::vector<key_type>(
+ population_vector.begin(), population_vector.begin() + sample_length - 2);
+ sample_vector.push_back(min_value);
+ sample_vector.push_back(max_value);
+ std::sort(sample_vector.begin(), sample_vector.end());
+ le_sample_vector = sample_vector;
+ initCustomSampleCPU();
+
+ key_type *cudaSample = nullptr, *cudaPopulation;
+
+ P_ERR("Coping sample");
+ cudaMalloc(&cudaSample, sizeof(key_type) * sample_length);
+ assert(sample_length == sample_vector.size());
+ cudaMemcpy(cudaSample, sample_vector.data(), sizeof(key_type) * sample_length,
+ cudaMemcpyHostToDevice);
+ cudaMalloc(&cudaPopulation, sizeof(key_type) * test_size);
+
+ P_ERR("\rCoping population");
+ cudaMemcpy(cudaPopulation, population_vector.data() + sample_length,
+ sizeof(key_type) * test_size, cudaMemcpyHostToDevice);
+
+ // auto custom_sort = CustomSort(SAMPLE_LENGTH, sizeof(long) * 8);
+ // custom_sort.testCalculation();
+ P_ERR("\rApply custom length and test calculation");
+ applyCudaSampleLength<<<1, 1>>>(sample_length);
+ testCustomCalculation<<<1, 1>>>(sample_length, sizeof(key_type) * 8);
+ cudaDeviceSynchronize();
+ P_ERR("\rApply custom length and test calculation completed");
+
+ // Can remove this function if pass
+ CustomSort::testSelf(sample_length, sizeof(key_type) * 8);
+
+ initSample<<<1, 1>>>(cudaSample, cudaPopulation);
+ cudaDeviceSynchronize();
+
+ // check_items<<<1, 1>>>();
+ // cudaDeviceSynchronize();
+ P_ERR("\r \rRunning "
+ "kernel\n");
+ run_kernel(test_size);
+
+ freeStorageStage1<<<1, 1>>>();
+ cudaDeviceSynchronize();
+
+ key_type *cudaNormalSample = nullptr;
+
+ P_ERR("\nCoping new sample");
+ cudaMalloc(&cudaNormalSample, sizeof(key_type) * sample_length);
+ cudaMemcpy(cudaNormalSample, le_sample_vector.data(),
+ sizeof(key_type) * sample_length, cudaMemcpyHostToDevice);
+
+ /*cudaMemcpy(sample_vector.data(), cudaSample, sizeof(key_type) *
+ sample_length, cudaMemcpyDeviceToHost);*/
+
+ initNormalSample<<<1, 1>>>(cudaNormalSample);
+ cudaDeviceSynchronize();
+
+ P_ERR("\r ");
+ P_ERR("\rRunning kernel2\n");
+ run_kernel(test_size, false);
+ // check_items<<<1, 1>>>();
+ // cudaDeviceSynchronize();
+ puts("");
+
+ freeStorageStage2<<<1, 1>>>();
+ cudaDeviceSynchronize();
+}
diff --git a/normal_distribution.cpp b/normal_distribution.cpp
index 211721a..55ffe33 100644
--- a/normal_distribution.cpp
+++ b/normal_distribution.cpp
@@ -69,7 +69,7 @@ int main(int argc, char const *argv[]) {
length = 1048576;
} else {
try {
- length = std::stol(argv[1]);
+ length = std::strtol(argv[1], nullptr, 10);
} catch (...) {
fprintf(stderr, "Wrong arguments\n");
return 1;
diff --git a/sortlib.cuh b/sortlib.cuh
index ca5525b..58aa7c1 100644
--- a/sortlib.cuh
+++ b/sortlib.cuh
@@ -15,8 +15,9 @@ public:
/// MOVE_OFFSET means bit to select branch
const int MOVE_OFFSET;
- const int STEP_LIMIT;
+ const unsigned int STEP_LIMIT;
+ // IEEE 754
__device__ __host__ static size_t fast_log(size_t a) {
float t = a;
return (((*(int *)&t) >> 23) + 1) & 127;
@@ -35,20 +36,20 @@ public:
__device__ __host__ __attribute__((unused)) void testCalculation() const {
for (size_t i = 0; i < LENGTH; i++) {
- auto l = calculate_index(i);
- auto l2 = calculate_rank(l - 1);
+ auto left = calculate_index(i);
+ auto right = calculate_rank(left - 1);
// printf("%lu %lu\n", l, l2);
- assert(i + 1 == l2);
+ assert(i + 1 == right);
}
}
__device__ __host__ const key_type *binary_search(key_type *const start,
- const key_type *end,
- const key_type val) {
+ // const key_type *end,
+ const key_type val) const {
// int step_limit = (int)fast_log(LENGTH);
key_type *last_known_point = start;
- auto son = 0;
+ auto son = 0UL;
for (int i = 0; i < STEP_LIMIT; i++) {
const auto next_level_start = start + (1 << (i + 1)) - 1;
@@ -56,59 +57,16 @@ public:
// printf("start: %ld, last: %ld\n", next_level_start - start,
// last_known_point - start);
- if (last_known_point > end) {
+ /*if (last_known_point > end) {
printf("%ld\n", last_known_point - start);
- }
- if (*last_known_point == val) {
- return last_known_point;
- }
-
- if (next_level_start > end) {
- printf("%ld\n", next_level_start - start);
- }
-
- // son = get_son_from_step(son, (*last_known_point > val));
- auto branch_selector = ((*last_known_point - val) >> MOVE_OFFSET);
- // printf("tmp: %llu\n", tmp);
- // printf("%llu %llu ", val, *last_known_point);
- son = son * 2 + branch_selector;
- // printf("%d\n", son);
- // puts(tmp == 0 ? "1:left" : "1:right");
- // if (son < 0) son = 0;
- /*printf("%d %d %d\n", (1 << (i + 1)), son,
- -(int)((*last_known_point - val) >> brenchSelector));*/
- last_known_point = next_level_start + son;
- if (last_known_point > end) {
- printf("%p %ld\n", end, next_level_start - start);
- }
- }
- return last_known_point;
- }
-
- __device__ __host__ const key_type *binary_search2(key_type *const start,
- const key_type *end,
- const key_type val) {
-
- // int step_limit = (int)fast_log(LENGTH);
- key_type *last_known_point = start;
- auto son = 0;
-
- for (int i = 0; i < STEP_LIMIT; i++) {
- const auto next_level_start = start + (1 << (i + 1)) - 1;
-
- // printf("start: %ld, last: %ld\n", next_level_start - start,
- // last_known_point - start);
-
- if (last_known_point > end) {
- printf("%ld\n", last_known_point - start);
- }
+ }*/
if (*last_known_point == val) {
return last_known_point;
}
- if (next_level_start > end) {
+ /*if (next_level_start > end) {
printf("%ld\n", next_level_start - start);
- }
+ }*/
// son = get_son_from_step(son, (*last_known_point > val));
auto branch_selector = ((*last_known_point - val) >> MOVE_OFFSET);
@@ -121,18 +79,19 @@ public:
/*printf("%d %d %d\n", (1 << (i + 1)), son,
-(int)((*last_known_point - val) >> brenchSelector));*/
last_known_point = next_level_start + son;
- if (last_known_point > end) {
+ /*if (last_known_point > end) {
printf("%p %ld\n", end, next_level_start - start);
- }
+ }*/
}
return last_known_point;
}
/// Should be correct version
- __device__ __host__ double
- sample_cdf_custom_version(key_type *start, const key_type *end, key_type x) {
+ __device__ __host__ double sample_cdf_custom_version(key_type *start,
+ // const key_type *end,
+ key_type x) const {
// printf("custom version:\n");
- auto it = this->binary_search(start, end, x);
+ auto it = this->binary_search(start, x);
// printf("search result: %ld\n", it - start);
// assert(it <= start + this->LENGTH);
/*if (it < start) {
@@ -145,6 +104,7 @@ public:
if (prev_real_location == this->LENGTH) {
return 1;
}
+
if (prev_real_location == 0) {
return 0;
}
@@ -160,8 +120,9 @@ public:
}
/// First version
- __device__ __host__ key_type *
- original_binary_search(key_type *start, const key_type *end, key_type &val) {
+ __device__ __host__ key_type *original_binary_search(key_type *start,
+ const key_type *end,
+ key_type &val) const {
auto begin = start;
key_type *last_known_point = nullptr;
while (begin < end) {
@@ -188,7 +149,7 @@ public:
/// CDF original version (should only work on default data layout)
__device__ __host__ double sample_cdf(key_type *start, key_type *end,
- key_type x) {
+ key_type x) const {
auto it = this->original_binary_search(start, end, x);
if (it == end) {
return 1;
@@ -202,6 +163,11 @@ public:
(double)(x - *it_prev) / (double)(*it - *it_prev)) /
(double)((end - start) - 1);
}
+
+ static void testSelf(size_t length) {
+ CustomSort(length, sizeof(long) * 8).testCalculation();
+ puts("You can remove this function if passed already");
+ }
};
__global__ void testCustomCalculation(size_t length) {