Created
April 27, 2017 11:06
-
-
Save antonmks/2aefc3089df8eecfb48079b250351230 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <ctime> | |
#include <fstream> | |
#include <iomanip> | |
#include <iostream> | |
#include <iterator> | |
#include <map> | |
#include <numeric> | |
#include <sstream> | |
#include <stdint.h> | |
#include <thrust/device_vector.h> | |
#include <thrust/extrema.h> | |
#include <thrust/reduce.h> | |
#include <thrust/sequence.h> | |
#include <thrust/sort.h> | |
#include <thrust/unique.h> | |
#include <time.h> | |
#include <random> | |
using namespace std; | |
using namespace thrust::placeholders; | |
struct increase_pointers { | |
char **char_pos; | |
char *first_pos; | |
increase_pointers(char **_char_pos, char *_first_pos) | |
: char_pos(_char_pos), first_pos(_first_pos) {} | |
template <typename IndexType> | |
__host__ __device__ void operator()(const IndexType &i) { | |
char_pos[i] = first_pos + 9 * i; | |
// if (i < 10) | |
// printf("INS %d %lld %lld \n", i, char_pos[i], first_pos); | |
} | |
}; | |
// applying WHERE conditions | |
struct check_records { | |
const unsigned int *time6; | |
const char *bool5; | |
bool *res; | |
const unsigned int *time6_from; | |
const unsigned int *time6_to; | |
const char *bool5_val; | |
check_records(const unsigned int *_time6, const char *_bool5, bool *_res, | |
const unsigned int *_time6_from, const unsigned int *_time6_to, | |
const char *_bool5_val) | |
: time6(_time6), bool5(_bool5), res(_res), time6_from(_time6_from), | |
time6_to(_time6_to), bool5_val(_bool5_val) {} | |
template <typename IndexType> | |
__host__ __device__ void operator()(const IndexType &i) { | |
if (time6[i] >= time6_from[0] && time6[i] <= time6_to[0] && | |
bool5[i] == bool5_val[0]) { | |
res[i] = 1; | |
} else | |
res[i] = 0; | |
} | |
}; | |
// sort fixed-length strings | |
struct sort_str { | |
__host__ __device__ bool operator()(const char *t1, const char *t2) { | |
for (unsigned int i = 0; i < 8; i++) { | |
if (t1[i] < t2[i]) | |
return 1; | |
if (t1[i] > t2[i]) | |
return 0; | |
}; | |
return 0; | |
} | |
}; | |
int main(int ac, char **av) { | |
unsigned int time6_from = 19000101, time6_to = 20300101; | |
char bool5_val = 0; | |
const unsigned int seg_size = 200000000; | |
string usage = "Usage : query1 [-time6_from TIME6_FROM] [-time6_to TIME6_TO " | |
"] [-bool5 BOOL5]"; | |
if (ac == 1) { | |
cout << usage << endl; | |
exit(1); | |
}; | |
for (unsigned int i = 1; i < ac; i++) { | |
if (strcmp(av[i], "-time6_from") == 0) { | |
if (i + 1 < ac) { | |
time6_from = atoi(av[i + 1]); | |
i++; | |
} else { | |
cout << usage << endl; | |
exit(1); | |
}; | |
} | |
if (strcmp(av[i], "-time6_to") == 0) { | |
if (i + 1 < ac) { | |
time6_to = atoi(av[i + 1]); | |
i++; | |
} else { | |
cout << usage << endl; | |
exit(1); | |
}; | |
} else if (strcmp(av[i], "-bool5") == 0) { | |
if (i + 1 < ac) { | |
bool5_val = av[i + 1][0]; | |
i++; | |
} else { | |
cout << usage << endl; | |
exit(1); | |
}; | |
} | |
}; | |
thrust::host_vector<uint64_t> id(seg_size); | |
std::uniform_int_distribution<unsigned long long> distr; | |
std::random_device rd; //Get a random seed from the OS entropy device, or whatever | |
std::mt19937_64 eng(rd()); | |
for(int n=0; n<seg_size; n++) { | |
id[n] = distr(eng); | |
}; | |
thrust::device_vector<uint64_t> id2 = id; | |
id.resize(0); | |
thrust::device_vector<unsigned int> time6(seg_size); | |
thrust::fill(time6.begin(), time6.end(),19950101); | |
thrust::device_vector<char> bool5(seg_size); | |
thrust::fill(bool5.begin(), bool5.begin()+(seg_size/2),'0'); | |
thrust::fill(bool5.begin()+(seg_size/2)+1, bool5.end(), '1'); | |
thrust::host_vector<char> file_buffer(9*seg_size); | |
for(int n=1; n<=seg_size; n++) { | |
if(n % 9 == 0) | |
file_buffer[n-1] = '\n'; | |
else | |
file_buffer[n-1] = rand() % 123; | |
}; | |
// Now we have all 4 arrays in a device memory | |
std::clock_t start1 = std::clock(); | |
thrust::device_vector<bool> res(seg_size); | |
// SQL WHERE condition check | |
thrust::device_vector<unsigned int> dev_time6_from(1); | |
thrust::device_vector<unsigned int> dev_time6_to(1); | |
thrust::device_vector<char> dev_bool5(1); | |
dev_time6_from[0] = time6_from; | |
dev_time6_to[0] = time6_to; | |
dev_bool5[0] = bool5_val; | |
thrust::counting_iterator<unsigned int> begin(0); | |
check_records ff( | |
(const unsigned int *)thrust::raw_pointer_cast(time6.data()), | |
(const char *)thrust::raw_pointer_cast(bool5.data()), | |
thrust::raw_pointer_cast(res.data()), | |
(const unsigned int *)thrust::raw_pointer_cast(dev_time6_from.data()), | |
(const unsigned int *)thrust::raw_pointer_cast(dev_time6_to.data()), | |
(const char *)thrust::raw_pointer_cast(dev_bool5.data())); | |
thrust::for_each(begin, begin + res.size(), ff); | |
time6.resize(0); | |
time6.shrink_to_fit(); | |
bool5.resize(0); | |
bool5.shrink_to_fit(); | |
// copy_if the results | |
thrust::device_vector<uint64_t> id2_cpy(res.size()); | |
auto w_count = thrust::copy_if(id2.begin(), id2.end(), res.begin(), | |
id2_cpy.begin(), thrust::identity<bool>()) - | |
id2_cpy.begin(); | |
id2.resize(0); | |
id2.shrink_to_fit(); | |
// SQL DISTINCT | |
thrust::sort(id2_cpy.begin(), id2_cpy.begin() + w_count); | |
auto distinct_cnt = | |
thrust::unique(id2_cpy.begin(), id2_cpy.begin() + w_count) - | |
id2_cpy.begin(); | |
cout << "segment distinct count " << distinct_cnt << endl; | |
unsigned int cycle_cnt = 2; | |
uint64_t * m_A; | |
cudaMallocManaged(&m_A, sizeof(uint64_t)*distinct_cnt*cycle_cnt); | |
thrust::device_ptr<uint64_t> h_values(m_A); | |
uint64_t * m_A_tmp; | |
cudaMallocManaged(&m_A_tmp, sizeof(uint64_t)*distinct_cnt*cycle_cnt); | |
thrust::device_ptr<uint64_t> h_values_tmp(m_A_tmp); | |
thrust::copy(id2_cpy.begin(), id2_cpy.begin() + distinct_cnt, h_values); | |
for(unsigned int i = 0; i < cycle_cnt-1; i++) { | |
thrust::transform(id2_cpy.begin(), id2_cpy.begin() + distinct_cnt, id2_cpy.begin(), _1+1); //changing all values | |
thrust::merge(h_values, h_values + distinct_cnt*(1+i), id2_cpy.begin(), id2_cpy.begin() + distinct_cnt, h_values_tmp); | |
thrust::copy(h_values_tmp, h_values_tmp + distinct_cnt*(2+i), h_values); | |
}; | |
cudaFree(m_A_tmp); | |
auto final_distinct_cnt = | |
thrust::unique(h_values, h_values + distinct_cnt*cycle_cnt) - h_values; | |
cudaFree(m_A); | |
cout << "merge distinct count " << final_distinct_cnt << endl; | |
// SQL AVG - just sum the all segments values and then divide by segment count | |
auto sum = thrust::reduce(id2_cpy.begin(), id2_cpy.end()); | |
for(unsigned int i = 0; i < cycle_cnt-1; i++) { | |
thrust::transform(id2_cpy.begin(), id2_cpy.begin() + distinct_cnt, id2_cpy.begin(), _1+1); //changing all values | |
sum = sum + thrust::reduce(id2_cpy.begin(), id2_cpy.end()); | |
}; | |
cout << "AVG(id2) = " << sum / (w_count *cycle_cnt) << endl; | |
id2_cpy.resize(0); | |
id2_cpy.shrink_to_fit(); | |
// MAX(char3) | |
thrust::device_vector<char> char3(9*seg_size); | |
thrust::copy(file_buffer.begin(), file_buffer.end(), char3.begin()); | |
file_buffer.resize(0); | |
thrust::host_vector<char> max_char(8); | |
thrust::host_vector<char> max_seg_char(8); | |
thrust::device_vector<char *> char_pos(seg_size); | |
increase_pointers func(thrust::raw_pointer_cast(char_pos.data()), | |
thrust::raw_pointer_cast(char3.data())); | |
thrust::for_each(begin, begin + char_pos.size(), func); | |
thrust::device_vector<char *> char_pos_res(w_count); | |
char *device_str; | |
for(unsigned int i = 0; i < cycle_cnt; i++) { //for MAX function we just compare the MAX values of every segment | |
// apply WHERE conditions | |
thrust::copy_if(char_pos.begin(), char_pos.end(), res.begin(), | |
char_pos_res.begin(), thrust::identity<bool>()); | |
auto end = | |
thrust::max_element(char_pos_res.begin(), char_pos_res.end(), sort_str()); | |
device_str = *(end); | |
cudaMemcpy(max_char.data(), (void *)device_str, 8, cudaMemcpyDeviceToHost); | |
for (int z = 0; z < 8; z++) { | |
if(max_char[z] > max_seg_char[z]) | |
max_seg_char = max_char; | |
else | |
if(max_char[z] < max_seg_char[z]) | |
break; | |
}; | |
}; | |
cout << "MAX(char3) = "; | |
for (int z = 0; z < 8; z++) | |
cout << max_seg_char[z]; | |
cout << endl; | |
std::cout << "time " << ((std::clock() - start1) / (double)CLOCKS_PER_SEC) << '\n'; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment