summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt10
-rw-r--r--expt_0821.cpp14
-rw-r--r--expt_0830.cu235
-rw-r--r--sortlib.cuh139
-rw-r--r--sortlib.h26
5 files changed, 406 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e05ef87..bdca176 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,4 +131,12 @@ add_executable(valid_sort valid_sort.cpp)
target_link_libraries(valid_sort m stdc++)
add_executable(expt_0821 expt_0821.cpp sortlib.h)
-target_link_libraries(expt_0821 m stdc++) \ No newline at end of file
+target_link_libraries(expt_0821 m stdc++)
+
+add_executable(expt_0830 expt_0830.cu sortlib.cuh)
+target_link_libraries(expt_0830 m stdc++)
+
+set_target_properties(expt_0830 PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON)
+set_target_properties(expt_0830 PROPERTIES CUDA_ARCHITECTURES "75")
+set_target_properties(expt_0830 PROPERTIES LINKER_LANGUAGE CUDA) \ No newline at end of file
diff --git a/expt_0821.cpp b/expt_0821.cpp
index 330cf40..cd0fd07 100644
--- a/expt_0821.cpp
+++ b/expt_0821.cpp
@@ -24,7 +24,7 @@ inline void store_into_vector(unsigned long long value) {
}
void valid_sort(std::vector<key_type> &tmp) {
- auto iter_end = population_vector.begin() + SAMPLE_LENGTH + 5;
+ auto iter_end = population_vector.begin() + SAMPLE_LENGTH + 1024;
for (auto it = population_vector.begin() + SAMPLE_LENGTH; it != iter_end;
it++) {
// long std_search =
@@ -33,15 +33,19 @@ void valid_sort(std::vector<key_type> &tmp) {
tmp.data(), tmp.data() + tmp.size(), *it) -
tmp.data();
- auto cuda_binary_search =
+ auto cuda_binary_search1 =
custom_sort.binary_search(sample_vector.data(), *it) -
sample_vector.data();
- cuda_binary_search = custom_sort.calculate_location(cuda_binary_search) - 1;
+ auto cuda_binary_search =
+ custom_sort.calculate_location(cuda_binary_search1) - 1;
/*printf("%ld:%ld %llu:%llu\n", std_search, cuda_binary_search,
*(tmp.begin() + std_search),
*(cuda_binary_search + sample_vector.begin()));*/
- printf("%ld:%ld \n", std_search, cuda_binary_search);
- // assert(std_search == cuda_binary_search);
+ printf("%ld:%ld %llu %llu %llu\n", std_search, cuda_binary_search, *it,
+ *(tmp.data() + std_search),
+ *(cuda_binary_search1 + sample_vector.data()));
+ // assert(*it > *(cuda_binary_search1 + sample_vector.data()));
+ // assert(std_search == cuda_binary_search);
}
}
diff --git a/expt_0830.cu b/expt_0830.cu
new file mode 100644
index 0000000..bbca9cf
--- /dev/null
+++ b/expt_0830.cu
@@ -0,0 +1,235 @@
+#include "sortlib.cuh"
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <vector>
+
+std::vector<unsigned long long> population_vector, sample_vector;
+
+constexpr size_t SAMPLE_LENGTH = 1023;
+// constexpr size_t TEST_LENGTH = 16'384;
+constexpr size_t TEST_LENGTH = 2048;
+
+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__ key_type *cudaSampleItem, *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;
+#ifdef TEST_BOUNDS
+ index_max = 0;
+ index_min = 0x7fffffff;
+#endif
+}
+
+__global__ void kernel(unsigned long step, const double slice_size,
+ const unsigned long split_size) {
+ auto custom_sort = CustomSort(SAMPLE_LENGTH, sizeof(key_type) * 8);
+ // printf("kernel1\n");
+ 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);
+ if (cdf_result[index]) {
+ while (cdf_result[++index]) {
+ assert(index < split_size);
+ }
+ }
+ cdf_result[index] = true;
+ }
+}
+
+__global__ void kernel2_real_binary(unsigned long step, const double slice_size,
+ const unsigned long split_size) {
+ auto custom_sort = CustomSort(SAMPLE_LENGTH, sizeof(key_type) * 8);
+ // printf("%d\n", custom_sort.MOVE_OFFSET);
+ // printf("kernel2\n");
+
+ for (int i = 0; i < step; i++) {
+ auto tid = step * (blockIdx.x * blockDim.x + threadIdx.x) + i;
+ // printf("%lu ", tid);
+
+ // assert(tid < TEST_LENGTH);
+ auto index = (int)(custom_sort.sample_cdf(cudaSampleItem,
+ cudaSampleItem + SAMPLE_LENGTH,
+ cudaPopulationItem[tid]) /
+ slice_size);
+ // printf("%llu %d\n", cudaPopulationItem[tid], index);
+ if (cdf_result[index]) {
+ while (cdf_result[++index]) {
+ assert(index < split_size);
+ }
+ }
+ cdf_result[index] = true;
+#ifdef TEST_BOUNDS
+ atomicAdd(&insert_value, 1);
+
+ while (true) {
+ unsigned tmp = index_min;
+ if (tmp < tid) {
+ break;
+ }
+ if (atomicCAS(&index_min, tmp, tid) == tmp) {
+ break;
+ }
+ }
+ while (true) {
+ unsigned tmp = index_max;
+ if (tmp > tid) {
+ break;
+ }
+ if (atomicCAS(&index_max, tmp, tid) == tmp) {
+ break;
+ }
+ }
+#endif
+ }
+}
+
+__global__ void print2() {
+ /*for (int i = 0; i< SAMPLE_LENGTH; i++) {
+ printf("%llu ", cudaSampleItem[i]);
+ }
+ printf("\n");*/
+ printf("%lu\n", CustomSort::fast_log(SAMPLE_LENGTH));
+}
+
+__global__ void print_function() {
+#ifdef TEST_BOUNDS
+ printf("%u\n", insert_value);
+ printf("%u %u\n", index_min, index_max);
+#endif
+}
+
+__global__ void initStorage(unsigned scale, unsigned test_size) {
+ cudaFree(cdf_result);
+ cudaMalloc(&cdf_result, scale * test_size * sizeof(bool));
+ memset(cdf_result, 0, scale * test_size * sizeof(bool));
+}
+
+__global__ void freeStorage() {
+ cudaFree(cudaSampleItem);
+ cudaFree(cudaPopulationItem);
+ cudaFree(cdf_result);
+}
+
+__global__ void initCustomSample() {
+ key_type *tmp = nullptr;
+ auto custom_sort = CustomSort(SAMPLE_LENGTH, 0);
+ cudaMalloc(&tmp, sizeof(key_type) * SAMPLE_LENGTH);
+ for (size_t i = 0; i < SAMPLE_LENGTH; i++) {
+ tmp[i] = cudaSampleItem[custom_sort.calculate_index(i) - 1];
+ }
+ memcpy(cudaSampleItem, tmp, sizeof(key_type) * SAMPLE_LENGTH);
+ cudaFree(tmp);
+ tmp = nullptr;
+ // memset(cdf_result, 0, sizeof(key_type) * TEST_LENGTH);
+ cudaFree(cdf_result);
+ cdf_result = nullptr;
+}
+
+const dim_pair_type DIM_PAIR[] = {
+ dim_pair_type(16, 64),
+ // dim_pair_type(32, 32)
+};
+
+void run_kernel(size_t test_size, bool custom = false) {
+ for (auto &pair : DIM_PAIR) {
+ dim3 grid_dim = pair.first, block_dim = pair.second;
+ unsigned long step = test_size / (grid_dim.x * block_dim.x);
+ printf("%scurrent dim: %d %d %lu\n", custom ? "custom " : "", pair.first,
+ pair.second, step);
+ for (int scale = 2; scale <= 16; scale += 2) {
+ const unsigned long split_size = test_size * scale;
+ const auto slice_size = 1.0 / (double)split_size;
+ printf("scale: %i ", scale);
+ initStorage<<<1, 1>>>(scale, test_size);
+ cudaDeviceSynchronize();
+ cudaEvent_t start, stop;
+ cudaEventCreate(&start);
+ cudaEventCreate(&stop);
+ cudaEventRecord(start, nullptr);
+ if (custom)
+ kernel<<<grid_dim, block_dim>>>(step, slice_size, split_size);
+ else
+ kernel2_real_binary<<<grid_dim, block_dim>>>(step, slice_size,
+ split_size);
+ cudaDeviceSynchronize();
+ cudaEventRecord(stop, nullptr);
+ cudaEventSynchronize(stop);
+ float time;
+ cudaEventElapsedTime(&time, start, stop);
+ cudaEventDestroy(start);
+ cudaEventDestroy(stop);
+ printf("time: %lf\n", time);
+
+ print_function<<<1, 1>>>();
+ cudaDeviceSynchronize();
+ }
+ }
+}
+
+int main() {
+
+ auto test_size = TEST_LENGTH;
+ FILE *file = fopen("normal_distribution.txt", "r");
+ assert(file);
+ for (long long i; fscanf(file, "%lld ", &i) != EOF; store_into_vector(i))
+ ;
+ fclose(file);
+
+ 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());
+
+ key_type *cudaSample = nullptr, *cudaPopulation;
+ 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);
+ 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();
+ testCustomCalculation<<<1, 1>>>(SAMPLE_LENGTH);
+ cudaDeviceSynchronize();
+
+ initSample<<<1, 1>>>(cudaSample, cudaPopulation);
+ cudaDeviceSynchronize();
+ run_kernel(test_size);
+
+ initCustomSample<<<1, 1>>>();
+ cudaDeviceSynchronize();
+
+ run_kernel(test_size, true);
+ freeStorage<<<1, 1>>>();
+ cudaDeviceSynchronize();
+} \ No newline at end of file
diff --git a/sortlib.cuh b/sortlib.cuh
new file mode 100644
index 0000000..c90e408
--- /dev/null
+++ b/sortlib.cuh
@@ -0,0 +1,139 @@
+#ifndef LOCKFREE_SORTLIB_CUH
+#define LOCKFREE_SORTLIB_CUH
+
+#include <cassert>
+#include <cstdio>
+
+typedef unsigned long long key_type;
+
+class CustomSort {
+public:
+ explicit __device__ __host__ CustomSort(size_t length, int move_offset)
+ : LENGTH(length), MOVE_OFFSET(move_offset - 1) {}
+ const size_t LENGTH;
+ const int MOVE_OFFSET;
+
+ __device__ __host__ static size_t fast_log(size_t a) {
+ float t = a;
+ return (((*(int *)&t) >> 23) + 1) & 127;
+ }
+
+ __device__ __host__ size_t calculate_index(size_t rank) const {
+ size_t bit_low = (LENGTH + 1) >> fast_log(++rank) >> 1;
+ return (((rank << 1) | 1) * bit_low - LENGTH - 1);
+ }
+
+ __device__ __host__ size_t calculate_rank(size_t index) const {
+ index++;
+ size_t low_bit = index & (-index);
+ return ((LENGTH + index) / low_bit) >> 1;
+ }
+
+ __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);
+ // printf("%lu %lu\n", l, l2);
+ assert(i + 1 == l2);
+ }
+ }
+
+ __device__ __host__ const key_type *binary_search(key_type *const start,
+ 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;
+ if (*last_known_point == val) {
+ return last_known_point;
+ }
+
+ // son = get_son_from_step(son, (*last_known_point > val));
+ auto tmp = ((*last_known_point - val) >> MOVE_OFFSET);
+ // printf("tmp: %llu\n", tmp);
+ // printf("%llu %llu ", val, *last_known_point);
+ son = son * 2 + tmp;
+ // 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) >> MOVE_OFFSET));*/
+ last_known_point = next_level_start + son;
+ }
+ return last_known_point;
+ }
+
+ __device__ __host__ double sample_cdf_custom_version(key_type *start,
+ key_type x) {
+ auto it = this->binary_search(start, x);
+ assert(it <= start + this->LENGTH);
+ if (it < start) {
+ printf("it: %p, start: %p\n", it, start);
+ }
+ assert(it >= start);
+ if (it == start + this->LENGTH) {
+ return 1;
+ }
+ if (it == start) {
+ return 0;
+ }
+
+ auto prev_real_location = calculate_rank(it - start) - 2;
+
+ auto it_prev = start + calculate_index(prev_real_location) - 1;
+
+ return ((double)prev_real_location +
+ (double)(x - *it_prev) / (*it - *it_prev)) /
+ (double)(this->LENGTH - 1);
+ }
+
+ __device__ __host__ key_type *
+ original_binary_search(key_type *start, const key_type *end, key_type &val) {
+ auto begin = start;
+ key_type *last_known_point = nullptr;
+ while (begin < end) {
+ auto mid = (end - begin) / 2;
+ auto mid_val = *(begin + mid);
+ if (val == mid_val) {
+ return begin + mid;
+ }
+ last_known_point = begin;
+ // printf("%llu %llu ", val, mid_val);
+ // puts(val > mid_val ? "right" : "left");
+ // printf("%llu\n", ((val - mid_val) >> MOVE_OFFSET) * (mid + 1));
+ begin += ((mid_val - val) >> MOVE_OFFSET) * (mid + 1);
+ end -= ((val - mid_val) >> MOVE_OFFSET) * (mid + 1);
+ // printf("%llu\t%p %p\n", val, begin, end);
+ /*if (val > mid_val) {
+ begin = begin + mid + 1;
+ } else {
+ end = end - mid - 1;
+ }*/
+ }
+ return last_known_point;
+ }
+
+ __device__ __host__ double sample_cdf(key_type *start, key_type *end,
+ key_type x) {
+ auto it = this->original_binary_search(start, end, x);
+ if (it == end) {
+ return 1;
+ }
+ if (it == start) {
+ return 0;
+ }
+ auto it_prev = it - 1;
+
+ return ((double)(it_prev - start) +
+ (double)(x - *it_prev) / (double)(*it - *it_prev)) /
+ (double)((end - start) - 1);
+ }
+};
+
+__global__ void testCustomCalculation(size_t length) {
+ CustomSort(length, sizeof(long) * 8).testCalculation();
+}
+#endif // LOCKFREE_SORTLIB_CUH
diff --git a/sortlib.h b/sortlib.h
index c00c07f..8e5a763 100644
--- a/sortlib.h
+++ b/sortlib.h
@@ -3,7 +3,7 @@
#include <cstddef>
#include <cstdio>
-template <typename C> class CustomSort {
+template <typename> class CustomSort {
public:
CustomSort(size_t length, int move_offset)
: LENGTH(length), MOVE_OFFSET(move_offset) {}
@@ -45,11 +45,12 @@ public:
}
// son = get_son_from_step(son, (*last_known_point > val));
- auto tmp = (int)((*last_known_point - val) >> MOVE_OFFSET);
- printf("%llu %llu ", val, *last_known_point);
+ auto tmp = ((*last_known_point - val) >> MOVE_OFFSET);
+ // printf("%llu %llu ", val, *last_known_point);
son = son * 2 + tmp;
- puts(tmp == 0 ? "1:left" : "1:right");
- // if (son < 0) son = 0;
+ // 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) >> MOVE_OFFSET));*/
last_known_point = next_level_start + son;
@@ -65,16 +66,17 @@ public:
if (val == mid_val) {
return begin + mid;
}
- printf("%llu %llu ", val, mid_val);
- puts(val > mid_val ? "right" : "left");
- /*begin += (int)((mid_val - val) >> MOVE_OFFSET) & (mid + 1);
- end -= (int)(~((mid_val - val) >> MOVE_OFFSET)) & (mid + 1);*/
- if (val > mid_val) {
+ last_known_point = begin;
+ // printf("%llu %llu ", val, mid_val);
+ // puts(val > mid_val ? "right" : "left");
+ // printf("%llu\n", ((val - mid_val) >> MOVE_OFFSET) * (mid + 1));
+ begin += ((mid_val - val) >> MOVE_OFFSET) * (mid + 1);
+ end -= (((val - mid_val) >> MOVE_OFFSET)) * (mid + 1);
+ /*if (val > mid_val) {
begin = begin + mid + 1;
} else {
end = end - mid - 1;
- }
- last_known_point = begin;
+ }*/
}
return last_known_point;
}