void *qsort_2 (void *threadarg) { //busy thread count mutex static pthread_mutex_t mutex_numBusyThreads = PTHREAD_MUTEX_INITIALIZER; //pivot index after partitioning int pivot; //thread arguments struct recur_pthread_qsort_args *args = threadarg, leftargs, rightargs; memcpy (&leftargs, args, sizeof(leftargs)); memcpy (&rightargs, args, sizeof(rightargs)); //child thread ids pthread_t threadid[2]; //child return stati int status; //temp vals int i; if (args->right - args->left < SWITCH_THRESH) { insertsort(&args->data[args->left], args->right - args->left + 1); } else if (args->left < args->right) { pivot = partition (args->data, args->left, args->right); #ifdef DEBUG printf("pivot is at index %d\n", pivot); #endif leftargs.right = pivot; rightargs.left = pivot + 1; pthread_mutex_lock(&mutex_numBusyThreads); if (*(args->numBusyThreads) >= args->maxThreads) { pthread_mutex_unlock(&mutex_numBusyThreads); //quicksort without spawning qsort_2(&leftargs); qsort_2(&rightargs); } else { //increment busy thread count *(args->numBusyThreads) += 2; #ifdef DEBUG printf("+2 busy thread count: %d\n", *(args->numBusyThreads)); #endif pthread_mutex_unlock(&mutex_numBusyThreads); //spawn new threads if (pthread_create(&threadid[0], NULL, qsort_2, &leftargs)) { perror("pthread_create (left side)"); exit(-1); } if (pthread_create(&threadid[1], NULL, qsort_2, &rightargs)) { perror("pthread_create (right side)"); exit(-1); } for (i = 0; i < 2; i++) { pthread_join (threadid[i], (void **)&status); pthread_mutex_lock(&mutex_numBusyThreads); (*args->numBusyThreads)--; #ifdef DEBUG printf("-1 busy thread count %d\n", *(args->numBusyThreads)); #endif pthread_mutex_unlock(&mutex_numBusyThreads); } } } return 0; }
void qsort_2( void **lineptr,int left, int right, int (*cmp)(void *, void *) ) { int i, last; void swap( void *v[], int i ,int j); if ( left >= right) return ; swap( lineptr, left, (left + right)/2 ); last = left; for ( i= left + 1; i <= right; i++ ){ // if ( strcmp_( lineptr[i], lineptr[left]) < 0) if ( (*cmp)(lineptr[i],lineptr[left]) < 0 ) swap( lineptr, ++last, i ); } swap( lineptr, left, last); qsort_2( lineptr , left, last - 1, cmp ); qsort_2 ( lineptr, last + 1, right, cmp); }
int main (int argc, char **argv) { int N,MxInt,i,Nthread; int *data, *check_data, *unsorted_data; printf("\n COMP4300 Ass2 Sorting Program\n"); printf(" Input Total Number of Data Items\n"); printf(" Maximum Integer Value\n"); printf(" and Number of Threads to Create\n"); scanf("%d%d%d",&N,&MxInt,&Nthread); assert(MxInt<MAX_INTS); assert(N>0 && N<MAX_INTS); assert(Nthread > 0 && Nthread < MAX_THRDS); printf("\n-------------------------------------\n"); printf(" Total Number of Data Items %-12d\n",N); printf(" Maximum Integer Value %-12d\n",MxInt); printf(" Number of Threads to Use %-12d\n",Nthread); printf("-------------------------------------\n\n"); /* Allocate data array and generate random numbers */ unsorted_data = (int *) malloc (N * sizeof(int)); data = (int*) malloc( N*sizeof(int) ); check_data = (int*) malloc( N*sizeof(int) ); init_data (unsorted_data, N, MxInt); prtvec(unsorted_data,N,"Unsorted Data"); /* Take copy and sort using radix sort, then use to verify */ for (i = 0; i < N; i++) check_data[i] = unsorted_data[i]; /* RADIX SORT */ measure_time(START_TIME, NULL); radixsort(check_data, N, MxInt); measure_time(STOP_TIME, "RadixSort"); for (i = 0; i < N; i++) data[i] = unsorted_data[i]; // RECURSIVE SORT measure_time(START_TIME, NULL); recur_qsort(data, 0, N-1); measure_time(STOP_TIME, "Recursive QuickSort"); check_results(check_data, data, N); for (i = 0; i < N; i++) data[i] = unsorted_data[i]; // ROUTINE 1 - ITERATIVE SORT measure_time(START_TIME, NULL); qsort_1(data, N); measure_time(STOP_TIME, "Routine 1"); check_results(check_data, data, N); for (i = 0; i < N; i++) data[i] = unsorted_data[i]; // ROUTINE 2 - RECURSIVE PTHREAD QUICKSORT measure_time(START_TIME, NULL); int numBusyThreads = 1; struct recur_pthread_qsort_args args = { data, 0, N-1, &numBusyThreads, Nthread}; qsort_2 (&args); measure_time(STOP_TIME, "Routine 2"); check_results(check_data, data, N); for (i = 0; i < N; i++) data[i] = unsorted_data[i]; // ROUTINE 3 - ITERATIVE BUSY WAITING PTHREAD QUICKSORT measure_time (START_TIME, NULL); qsort_3 (data, N, Nthread); measure_time (STOP_TIME, "Routine 3"); check_results(check_data, data, N); for (i = 0; i < N; i++) data[i] = unsorted_data[i]; // ROUTINE 4 - ITERATIVE CV PTHREAD QUICKSORT measure_time (START_TIME, NULL); qsort_4 (data, N, Nthread); measure_time (STOP_TIME, "Routine 4"); // PRINT "SORTED" DATA prtvec(data,N,"Sorted Data"); /* Sequential check that the results are correct */ check_results(check_data, data, N); printf("Execution completed successfully\n"); return 0; }