// To compile this mess (on Linux): // g++ -fopenmp quicksort.cpp -o quicksort // Run it like this: // ./quicksort #include #include #include #include #include #define SIZE 1000*16 inline void swap(int* a, int* b) { *a += *b; *b = *a - *b; *a -= *b; } void bubblesort(int* A, int len) { bool changed = 1; while(changed) { changed = 0; for(int i = 0; i < (len-1); ++i) if(A[i] > A[i+1]) { swap(A+i, A+i+1); changed = 1; } } } void quicksort(int* A, int len) { // Calculate median value, store in A[len/2] if(A[len/2] < A[0]) swap(A + (len/2), A); // same as &(A[len/2]) if(A[len-1] < A[0]) swap(A, A+len-1); if(A[len-1] < A[len/2]) swap(A + len/2, A+len-1); // Move median value to 2nd to last element // The last element is greater than the pivot, for sure swap(A+len/2,A+len-2); /* for(int i = 0; i < len; ++i) printf("%d ", A[i]); printf("\n");//*/ int i = 0; int j = len - 2; register int pivot = A[len-2]; // printf("Pivot: %d\n", pivot); while(1) { while(A[++i] < pivot); while(pivot < A[--j]); if(i < j) swap(A+i,A+j); else break; } // Pivot is in the wrong spot - needs to be put back in place if(i < len-2) swap(A+i, A+len-2); /* printf("Partition: "); for(int i = 0; i < len; ++i) printf("%d ", A[i]); printf("\n");//*/ // If less than 10 items, call bubblesort if(i > 10) quicksort(A, i); else bubblesort(A, i); if(len-i > 10) quicksort(A+i+1,len-i-1); else bubblesort(A+i+1,len-i-1); return; } void quicksort_parallel(int* A, int len, int levcount) { // Calculate median value, store in A[len/2] if(A[len/2] < A[0]) swap(A + (len/2), A); // same as &(A[len/2]) if(A[len-1] < A[0]) swap(A, A+len-1); if(A[len-1] < A[len/2]) swap(A + len/2, A+len-1); // Move median value to 2nd to last element // The last element is greater than the pivot, for sure swap(A+len/2,A+len-2); int i = 0; int j = len - 2; register int pivot = A[len-2]; while(1) { while(A[++i] < pivot); while(pivot < A[--j]); if(i < j) swap(A+i,A+j); else break; } // Pivot is in the wrong spot - needs to be put back in place if(i < len-2) swap(A+i, A+len-2); #pragma omp parallel sections shared(A,i) { #pragma omp section { // If less than 10 items, call bubblesort if(i <= 10) bubblesort(A,i); else if(levcount > 0) quicksort_parallel(A, i, levcount - 1); else quicksort(A, i); } #pragma omp section { if(len-i <= 10) bubblesort(A+i+1,len-i-1); else if(levcount > 0) quicksort_parallel(A+i+1,len-i-1, levcount - 1); else quicksort(A+i+1,len-i-1); } } return; } /* * Returns the time difference in seconds, with 6 decimal places. * Feel free to borrow this for future assignments if you like. */ double timediff(timeval* start, timeval* end) { double s_diff = end->tv_sec - start->tv_sec; double us_diff = end->tv_usec - start->tv_usec; s_diff += us_diff / 1000000; return s_diff; } int main() { timeval start, end; // TODO: These are needed for timing omp_set_nested(1); //Make a test array int *A = (int*)malloc(sizeof(int) * SIZE); for(int i = 0; i < SIZE; ++i){ A[i] = rand()%1000; } int *B = (int*)malloc(sizeof(int) * SIZE); memcpy(B, A, SIZE*sizeof(int)); printf("Array construction complete\n"); // TODO: The next section is important for timing gettimeofday(&start, NULL); bubblesort(A, SIZE); // This is what we are timing gettimeofday(&end, NULL); printf("Bubble Sort: %lf\n", timediff(&start, &end)); // TODO: End of timing code for bubble sort bool right = 1; /* for(int i = 0; i < SIZE-1; ++i) if(A[i] > A[i+1]) right = 0; if(right) printf("Bubble Sort output verified!\n"); */ memcpy(A, B, SIZE*sizeof(int)); gettimeofday(&start, NULL); quicksort(A, SIZE); gettimeofday(&end, NULL); printf("QuickSort: %lf\n", timediff(&start, &end)); right = 1; /* for(int i = 0; i < SIZE-1; ++i) if(A[i] > A[i+1]) { right = 0; printf("Error position %d, A[%d] = %d\n", i, i, A[i]); } if(right) printf("QuickSort output verified!\n"); else { printf("QuickSort output wrong\n"); // for(int i = 0; i < SIZE; ++i) // printf("%d ", A[i]); // printf("\n"); } */ memcpy(A, B, SIZE*sizeof(int)); gettimeofday(&start, NULL); quicksort_parallel(A, SIZE, 0); gettimeofday(&end, NULL); printf("QuickSort (2): %lf\n", timediff(&start, &end)); right = 1; for(int i = 0; i < SIZE-1; ++i) if(A[i] > A[i+1]) { right = 0; printf("Error position %d, A[%d] = %d\n", i, i, A[i]); } if(right) printf("QuickSort output verified!\n"); //*/ memcpy(A, B, SIZE*sizeof(int)); gettimeofday(&start, NULL); quicksort_parallel(A, SIZE, 4); gettimeofday(&end, NULL); printf("QuickSort (32): %lf\n", timediff(&start, &end)); right = 1; for(int i = 0; i < SIZE-1; ++i) if(A[i] > A[i+1]) { right = 0; printf("Error position %d, A[%d] = %d\n", i, i, A[i]); } if(right) printf("QuickSort output verified!\n"); // free(A); // free(B); return 0; }