unsigned int per_interval_overlaps(struct interval *A, unsigned int size_A, struct interval *B, unsigned int size_B, unsigned int *R) { unsigned int i, O = 0; unsigned int *B_starts = (unsigned int *) malloc(size_B * sizeof(unsigned int)); unsigned int *B_ends = (unsigned int *) malloc(size_B * sizeof(unsigned int)); for (i = 0; i < size_B; i++) { B_starts[i] = B[i].start; B_ends[i] = B[i].end; } qsort(B_starts, size_B, sizeof(unsigned int), compare_unsigned_int); qsort(B_ends, size_B, sizeof(unsigned int), compare_unsigned_int); for (i = 0; i < size_A; i++) { unsigned int num_cant_before = bsearch_seq(A[i].start, B_ends, size_B, -1, size_B); unsigned int b = bsearch_seq(A[i].end, B_starts, size_B, -1, size_B); while ( ( B_starts[b] == A[i].end) && b < size_B) ++b; unsigned int num_cant_after = size_B - b; unsigned int num_left = size_B - num_cant_before - num_cant_after; O += num_left; R[i] = num_left; } free(B_starts); free(B_ends); return O; }
//{{{ unsigned int count_seq(struct interval *A, unsigned int count_seq(struct interval *A, unsigned int size_A, unsigned int *B_starts, unsigned int *B_ends, unsigned int size_B) { unsigned int i, O = 0; unsigned int num_cant_before, b, num_cant_after, num_left; for (i = 0; i < size_A; i++) { num_cant_before = bsearch_seq(A[i].start, B_ends, size_B, -1, size_B); b = bsearch_seq(A[i].end, B_starts, size_B, -1, size_B); while ( ( B_starts[b] == A[i].end) && b < size_B) ++b; num_cant_after = size_B - b; num_left = size_B - num_cant_before - num_cant_after; O += num_left; } return O; }
//{{{ unsigned int per_interval_count_intersections_bsearch_seq_fast( unsigned int per_interval_count_intersections_bsearch_seq_sorted_int( struct interval *A, unsigned int size_A, unsigned int *B_start, unsigned int *B_end, unsigned int size_B, unsigned int *R) { unsigned int i, O = 0; for (i = 0; i < size_A; i++) { unsigned int num_cant_before = bsearch_seq(A[i].start, B_end, size_B, -1, size_B); unsigned int b = bsearch_seq(A[i].end, B_start, size_B, -1, size_B); while ( ( B_start[b] == A[i].end) && b < size_B) ++b; unsigned int num_cant_after = size_B - b; unsigned int num_left = size_B - num_cant_before - num_cant_after; O += num_left; R[i] = num_left; } return O; }
//{{{ unsigned int per_interval_count_intersections_bsearch_seq(struct interval *A, unsigned int per_interval_count_intersections_bsearch_seq(struct interval *A, unsigned int size_A, struct interval *B, unsigned int size_B, unsigned int *R) { unsigned int i, O = 0; //{{{ i_mem unsigned int *B_starts = (unsigned int *) malloc(size_B * sizeof(unsigned int)); unsigned int *B_ends = (unsigned int *) malloc(size_B * sizeof(unsigned int)); for (i = 0; i < size_B; i++) { B_starts[i] = B[i].start; B_ends[i] = B[i].end; } //}}} i_mem //{{{ i_sort qsort(B_starts, size_B, sizeof(unsigned int), compare_unsigned_int); qsort(B_ends, size_B, sizeof(unsigned int), compare_unsigned_int); //}}} i_sort //{{{ i_do for (i = 0; i < size_A; i++) { unsigned int num_cant_before = bsearch_seq(A[i].start, B_ends, size_B, -1, size_B); unsigned int b = bsearch_seq(A[i].end, B_starts, size_B, -1, size_B); while ( ( B_starts[b] == A[i].end) && b < size_B) ++b; unsigned int num_cant_after = size_B - b; unsigned int num_left = size_B - num_cant_before - num_cant_after; O += num_left; R[i] = num_left; } //}}} i_do //{{{ i_mem free(B_starts); free(B_ends); //}}} return O; }
unsigned int get_intersections(struct interval *A, unsigned int size_A, struct interval *B, unsigned int size_B, unsigned int **R, unsigned int **E) { *R = (unsigned int *) malloc(size_A * sizeof(unsigned int)); unsigned int O = per_interval_overlaps(A, size_A, B, size_B, *R); int i; for (i = 1; i < size_A; i++) (*R)[i] = (*R)[i] + (*R)[i-1]; for (i = 0; i < size_B; i++) B[i].order = i; qsort(B, size_B, sizeof(struct interval), compare_interval_by_start); unsigned int *B_starts = (unsigned int *) malloc(size_B * sizeof(unsigned int)); for (i = 0; i < size_B; i++) B_starts[i] = B[i].start; *E = (unsigned int *) malloc(O * sizeof(unsigned int)); unsigned int start = 0, end; for (i = 0; i < size_A; i++) { if (i != 0) start = (*R)[i - 1]; end = (*R)[i]; if (end - start > 0) { unsigned int from = bsearch_seq(A[i].end, B_starts, size_B, -1, size_B); while ( ( B_starts[from] == A[i].end) && from < size_B) ++from; while ( (end - start) > 0 ) { if ( (A[i].start <= B[from].end) && (A[i].end >= B[from].start) ) { (*E)[start] = B[from].order; start++; } --from; } } } free(B_starts); return O; }
/** * @param A intervals in set A * @param size_A size of set A * @param B intervals in set B * @param size_B size of set B * @param R prefix sum of the intersection between A and B, A[0] is the number * of intervals in B that intersect A[0], A[1] is A[0] + the number of * intervals in B that intersect A[1], and so on * @param E array that will hold the enumberated interval intersections * @param size_E */ unsigned int enumerate_intersections_bsearch_seq(struct interval *A, unsigned int size_A, struct interval *B, unsigned int size_B, unsigned int **R, unsigned int **E) { //{{{ i_do *R = (unsigned int *) malloc(size_A * sizeof(unsigned int)); unsigned int O = per_interval_count_intersections_bsearch_seq(A, size_A, B, size_B, *R); //}}} i_do //{{{ e_scan int i; // Scan R, the resulting array will define the location within E of the // enumerated intersecting intervals for each interval in A // A[i] is allocated E[ R[i-1] ] ... E[ R[i] ] for (i = 1; i < size_A; i++) (*R)[i] = (*R)[i] + (*R)[i-1]; //}}} //{{{ e_sort for (i = 0; i < size_B; i++) B[i].order = i; qsort(B, size_B, sizeof(struct interval), compare_interval_by_start); //}}} e_sort //{{{ e_mem unsigned int *B_starts = (unsigned int *) malloc(size_B * sizeof(unsigned int)); for (i = 0; i < size_B; i++) B_starts[i] = B[i].start; *E = (unsigned int *) malloc(O * sizeof(unsigned int)); //}}} e_mem //{{{ e_do unsigned int start = 0, end; for (i = 0; i < size_A; i++) { if (i != 0) start = (*R)[i - 1]; end = (*R)[i]; if (end - start > 0) { unsigned int from = bsearch_seq(A[i].end, B_starts, size_B, -1, size_B); while ( ( B_starts[from] == A[i].end) && from < size_B) ++from; while ( (end - start) > 0 ) { if ( (A[i].start <= B[from].end) && (A[i].end >= B[from].start) ) { (*E)[start] = B[from].order; start++; } --from; } } } //}}} e_do //{{{ e_mem free(B_starts); //}}} e_mem return O; }
int main(int argc, char *argv[]) { MPI_Status status; int rank, size, seen; MPI_Init (&argc, &argv); /* starts MPI */ MPI_Comm_rank (MPI_COMM_WORLD, &rank); /* get current process id */ MPI_Comm_size (MPI_COMM_WORLD, &size); /* get number of processes */ if (argc < 4) { fprintf(stderr, "usages:\t%s <D size > <Q size> " "<seed>\n", argv[0]); return 1; } int D_size = atoi(argv[1]); // size of data set D int Q_size = atoi(argv[2]); // size of query set Q int seed = atoi(argv[3]); /* * The master thread (0) will create D and Q, send it out to the threads, * then collect the results. There are two ways to do this, send out * portions of D and all of Q, or portions of Q and all of D, it will * likely depend on the size of D and Q. We will try both. * * To aggregate the results, we can also either do a reduction or just have * the master calculate everything. We will try both. */ if (rank == 0) { unsigned int *D = (unsigned int *) malloc(D_size * sizeof(unsigned int)); unsigned int *Q = (unsigned int *) malloc(Q_size * sizeof(unsigned int)); unsigned int *R = (unsigned int *) malloc(Q_size * sizeof(unsigned int)); init_genrand(seed); // Have the mater generate all of the data, in other cases we can have // the worker nodes read in their own portion of files generate_rand_unsigned_int_set(D, D_size); generate_rand_unsigned_int_set(Q, Q_size); // Let each thread sort their own //qsort(D, D_size, sizeof(unsigned int), compare_unsigned_int); // In this case we are going to send out all of Q and portions of D. // } unsigned long total_time_1 = 0; int j; start(); for (j = 0; j < Q_size; j++) { int c = bsearch_seq(Q[j], D, D_size, -1, D_size); } stop(); total_time_1 = report(); unsigned long total_time_2 = 0; start(); for (j = 0; j < Q_size; j++) { int c = bsearch_seq(Q[j], D, D_size, -1, D_size); } stop(); total_time_2 += report(); printf("%lu,%lu\n", total_time_1, total_time_2); return 0; }