#include #include #include #include #include //#define SMALL_TEST #ifdef SMALL_TEST #define N 15 #else #define N 75 #endif #define T 8 typedef struct { int threadID; int iStart; int iDolzinaSeznama; } thread_args_t; typedef enum { false = 0, true = 1 } bool_t; unsigned int *pSeznam; pthread_barrier_t barrier; pthread_t nit[T]; thread_args_t args[T]; time_t seconds; bool_t isSortedGlobal = true; pthread_mutex_t kljucavnica = PTHREAD_MUTEX_INITIALIZER; void* funkcija_niti(void* argumenti); #ifdef SMALL_TEST //unsigned int seznam[ ] = {6, 1, 7, 8, 3, 2, 5, 4, 0}; //unsigned int seznam[ ] = {2, 1, 3, 4, 5, 6, 7, 8, 9}; unsigned int seznam[] = {10, 66, 73, 89, 45, 30, 27, 49, 37, 11, 2, 70, 23, 6, 88}; #else unsigned int seznam[N]; #endif void izpisi_seznam(unsigned int *pSeznam, int n){ for (int j = 0; j < n; j++) { printf("%d ", *(pSeznam+j)); } printf("\n"); } bool_t primerjaj_in_zamenjaj(unsigned int* a, unsigned int* b){ bool_t isSorted = true; unsigned int temp; //printf("PZ: %d, %d\n", *a, *b); if (*b < *a) { temp = *a; *a = *b; *b = temp; //printf("PZ: %d, %d\n", *a, *b); isSorted = false; } return isSorted; } bool_t sodi_prehod(int iDolzinaSeznama, unsigned int *pSeznam, int threadID){ bool_t isSorted = true; int iStart= (threadID*(N/T))%2; for (int i = iStart; i < iDolzinaSeznama; i=i+2) { isSorted = isSorted & primerjaj_in_zamenjaj(&pSeznam[i], &pSeznam[i+1]); } return isSorted; } bool_t lihi_prehod(int iDolzinaSeznama, unsigned int *pSeznam, int threadID){ bool_t isSorted = true; int iStart = (threadID*(N/T))%2; for (int i = 1-iStart; i < iDolzinaSeznama; i=i+2) { isSorted = isSorted & primerjaj_in_zamenjaj(&pSeznam[i], &pSeznam[i+1]); } return isSorted; } void* funkcija_niti(void* argumenti) { thread_args_t* args = (thread_args_t*) argumenti; bool_t isSorted = true; for (int i = 0; i < N; i++) { isSorted = true; isSorted = isSorted & sodi_prehod(args->iDolzinaSeznama, pSeznam + args->iStart, args->threadID); pthread_mutex_lock(&kljucavnica); isSortedGlobal = isSortedGlobal & isSorted; pthread_mutex_unlock(&kljucavnica); printf("SODI: T%d, i=%d isSorted=%d \n", args->threadID, i, isSorted); pthread_barrier_wait(&barrier); /*********************** PREPREKA ***************************/ isSorted = true; isSorted = isSorted & lihi_prehod(args->iDolzinaSeznama, pSeznam + args->iStart, args->threadID); pthread_mutex_lock(&kljucavnica); isSortedGlobal = isSortedGlobal && isSorted; pthread_mutex_unlock(&kljucavnica); printf("LIHI: T%d, i=%d isSorted=%d \n", args->threadID, i, isSorted); pthread_barrier_wait(&barrier); /*********************** PREPREKA ***************************/ if (isSortedGlobal == true) { break; } pthread_barrier_wait(&barrier); if (args->threadID == 0) { isSortedGlobal = true; } pthread_barrier_wait(&barrier); } } int main(){ //pSeznam = (unsigned int *) malloc (N * sizeof(unsigned int)); pSeznam = seznam; #ifndef SMALL_TEST // init random generatorja: srand((unsigned) time(&seconds)); //init seznama: for(int i = 0; i < N; i++){ seznam[i] = rand() % (100); } #endif izpisi_seznam(pSeznam, N); printf("\n\n"); pthread_barrier_init(&barrier, NULL, T); for (int i = 0; i < T; i++) { args[i].threadID = i; args[i].iStart = i*((int)N/(int)T); if (i < T-1) args[i].iDolzinaSeznama = (int)N/(int)T; else args[i].iDolzinaSeznama = ((int)N/(int)T) + ((int)N%(int)T) - 1; printf("Nit: %d, iStart: %d, iDolzinaSeznama: %d \n", i, args[i].iStart, args[i].iDolzinaSeznama); pthread_create( &nit[i], NULL, funkcija_niti, (void *) &args[i]); } for (int i = 0; i < T; i++){ pthread_join(nit[i], NULL); } izpisi_seznam(pSeznam, N); pthread_barrier_destroy(&barrier); } /* PARALELIZACIJA: - Če imamo T niti, potem vsaka nit dobi (N/2)/T parov - en sam prehod delajo vzporedno vse niti - ko niti zaključijo en prehod (sodi ali lihi), se morajo počakati na prepreki! PREPREKE: 1. najprej jo deklariraj: pthread_barrier_t barrier; 2. potem jo inicializiraj: pthread_barrier_init() 3. niti ki morajo pocakati pred prepreko, kličejo: pthread_barrier_wait() 4. po zaključku programa, morate prepreko umaknit: pthread_barrier_destroy() */