Skip to content

Instantly share code, notes, and snippets.

@antonmks
Created April 27, 2017 11:06
Show Gist options
  • Save antonmks/2aefc3089df8eecfb48079b250351230 to your computer and use it in GitHub Desktop.
Save antonmks/2aefc3089df8eecfb48079b250351230 to your computer and use it in GitHub Desktop.
#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