Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include <pthread.h>
- struct param_for_mergesort {
- int * array;
- int length;
- };
- /* Funkce vracejici pole cisel a ukladajici do promennych pocet cisel a informace o souboru */
- int * open_input(char * file, int * count_of_item, struct stat * file_inf);
- /* Funkce zapisujici pole cisel do souboru */
- void write_to_file(int * array, char * file, int count_of_item, struct stat file_inf);
- /* Paralelní mergesort */
- int * parallel_merge_sort(int * array, int count_of_threads, int count_of_items);
- /* Funkce tridici pole */
- int * merge_sort(void * param);
- /* Funkce slevajici 2 pole */
- int * merge(int * left, int left_len, int * right, int right_len);
- int main(int argc, char *argv[])
- {
- if (argc < 4) {
- fprintf(stderr,"Chybny pocet argumentu\n");
- return 1;
- }
- int * count = (int *) malloc(sizeof(int));
- struct stat * fileinfo = (struct stat *) malloc(sizeof(struct stat)); /* struktura, ze ktere budu zjistovat velikost souboru */
- int * my_array = open_input(argv[1], count, fileinfo); /* Nactu si pole cisel ze souboru */
- int * sorted_array = parallel_merge_sort(my_array, atoi(argv[3]), *count); /* Setridim si pole cisel */
- write_to_file(sorted_array,argv[2], *count, *fileinfo); /* Ulozim pole do souboru */
- free(my_array);
- free(sorted_array);
- return 0;
- }
- int * open_input(char * file, int * count_of_item, struct stat * file_inf)
- {
- /* Otevru si soubor */
- int file_input = open(file, O_RDONLY);
- if (file_input == -1) {
- fprintf(stderr, "Chyba pri otevirani souboru%s\n", file);
- exit(EXIT_FAILURE);;
- }
- /* Ulozim do struktury informace o souboru */
- stat(file, file_inf);
- /* Namapuji si soubor do pameti */
- char * input_map_adress = (char *) mmap(NULL, file_inf->st_size, PROT_READ, MAP_SHARED, file_input, 0);
- if (input_map_adress == MAP_FAILED) {
- fprintf(stderr, "Selhalo nacteni input souboru do pameti\n");
- close(file_input);
- exit(EXIT_FAILURE);;
- }
- /* Vytvorim si pole a ukladam hodnoty ze souboru a pocitam pocet polozek */
- int i,j = 0;
- int * my_array = (int *) malloc(10 * sizeof(int));
- char tmp_str[255];
- *count_of_item = 0;
- for (i = 0; i < file_inf->st_size; i++) {
- /* Pokud narazim na novy radek, prevedu string na cislo a ulozim */
- if (input_map_adress[i] != '\n') {
- tmp_str[j++] = input_map_adress[i];
- } else {
- my_array[(*count_of_item)++] = atoi(tmp_str);
- memset (tmp_str,'\0',255);
- j = 0;
- }
- /* Realokuju si pole po 10 prvcich */
- if (*count_of_item % 10 == 0) {
- int * tmp = (int *) realloc(my_array, (*count_of_item + 10) * sizeof(int));
- if (tmp != NULL) {
- my_array = tmp;
- } else {
- free(my_array);
- munmap(input_map_adress, file_inf->st_size);
- close(file_input);
- exit(EXIT_FAILURE);;
- }
- }
- }
- /* Uvolnim mapovanou pamet a zavru file deskriptor */
- munmap(input_map_adress, file_inf->st_size);
- close(file_input);
- return my_array;
- }
- void write_to_file(int* array, char* file, int count_of_item, struct stat file_inf)
- {
- /* Otevru si soubor */
- int file_output = open(file, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
- if (file_output == -1) {
- fprintf(stderr, "Chyba pri otevirani souboru %s\n", file);
- exit(EXIT_FAILURE);;
- }
- /* Nastavim velikost souboru na velikost souboru, ze ktereho nacitam */
- if (lseek(file_output, file_inf.st_size-1, SEEK_SET) == -1) {
- close(file_output);
- fprintf(stderr, "Chyba pri zvetsovani souboru na velikost ukladaneho pole\n");
- exit(EXIT_FAILURE);
- }
- /* Zapisu posledni znak do souboru */
- if (write(file_output, "", 1) != 1) {
- close(file_output);
- fprintf(stderr, "Chyba pri zapisovani posledniho znaku do souboru\n");
- exit(EXIT_FAILURE);
- }
- /* Namapuju si soubor do pameti */
- char * output_map_adress = (char *) mmap(NULL, file_inf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_output, 0);
- if (output_map_adress == MAP_FAILED) {
- fprintf(stderr, "Selhalo nacteni output souboru do pameti\n");
- close(file_output);
- exit(EXIT_FAILURE);
- }
- /* Postupne nacitam cisla z pole do retezcu a kopiruji do mapovane pameti */
- int i;
- char tmp_str[255];
- char * tmp_output_map_adress = output_map_adress;
- for (i = 0; i < count_of_item; i++) {
- int count = sprintf(tmp_str,"%d\n",array[i]);
- strcpy( output_map_adress , tmp_str );
- output_map_adress += count;
- }
- /* Uvolnim mapovanou pamet a zavru file deskriptor */
- munmap(tmp_output_map_adress, file_inf.st_size);
- close(file_output);
- }
- int * parallel_merge_sort(int * array, int count_of_threads, int count_of_items)
- {
- if (count_of_threads > count_of_items) {
- printf("Pocet vlaken je vetsi nez pocet cisel, snizuji pocet vlaken na polovinu poctu cisel\n");
- count_of_threads = count_of_items / 2;
- }
- /* Alokuji si pole parametru pro vlakna */
- struct param_for_mergesort * parameters = (struct param_for_mergesort *) malloc(count_of_threads * sizeof(struct param_for_mergesort));
- pthread_t * threads = (pthread_t *) malloc(count_of_threads * sizeof(pthread_t));
- pthread_attr_t * attrs = (pthread_attr_t *) malloc (count_of_threads * sizeof(pthread_attr_t));
- /* Alokuji si vysledne pole */
- int * result = (int *) malloc(count_of_items * sizeof(int));
- int i, j;
- int delim = (count_of_items) / count_of_threads; /* Po kolika bude pole rozdeleno */
- int rest = count_of_items - (count_of_threads-1)*delim; /* Kolik prvku bude mit posledni pole */
- for (i = 0; i < count_of_threads; i++) {
- /* Pokud nebudu poustet vlakno s poslednim polem tak budou prvky po velikost delim */
- if (i < count_of_threads - 1) {
- parameters[i].array = (int *) malloc(delim * sizeof(int));
- parameters[i].length = delim;
- for (j = 0; j < delim; j++) {
- parameters[i].array[j] = array[(i*delim)+j];
- }
- /* Jinak pocet prvku bude zbytek */
- } else {
- parameters[i].array = (int *) malloc(rest * sizeof(int));
- parameters[i].length = rest;
- for (j = 0; j < rest; j++) {
- parameters[i].array[j] = array[count_of_items-rest+j];
- }
- }
- /* Spustim trideni ve vlakne */
- pthread_attr_init(&attrs[i]);
- pthread_create(&threads[i], &attrs[i], (void *)merge_sort, (void *)¶meters[i]);
- }
- /* Postupne pockam na jednotliva vlakna a spojuji do vysledneho pole */
- for (i = 0; i < count_of_threads; i++) {
- void * tmp;
- pthread_join(threads[i], &tmp);
- if (i < count_of_threads - 1) {
- result = merge(result, (i * delim),(int *) tmp, delim);
- } else {
- result = merge(result, ((i-1) * delim) + rest,(int *) tmp, rest);
- }
- }
- free(threads);
- free(parameters);
- free(attrs);
- return result;
- }
- int * merge_sort(void * param)
- {
- /* Puvodni parametr predany funkci */
- struct param_for_mergesort * parameters;
- parameters = (struct param_for_mergesort *) param;
- if (parameters->length <= 1) {
- return parameters->array;
- } else {
- int i;
- int middle = parameters->length / 2; /* Spocitam si stred pole */
- int * result;
- /* Vytvorim si pole pro spusteni merge sortu pro levou a pravou cast */
- struct param_for_mergesort * parameters_left = (struct param_for_mergesort *) malloc(sizeof(struct param_for_mergesort));
- struct param_for_mergesort * parameters_right = (struct param_for_mergesort *) malloc(sizeof(struct param_for_mergesort));
- parameters_left->array = (int *) malloc(middle * sizeof(int));
- parameters_right->array = (int *) malloc((parameters->length-middle) * sizeof(int));
- /* Presunu prvky prvni poloviny do leveho pole */
- for (i = 0; i < middle; i++) {
- parameters_left->array[i] = parameters->array[i];
- }
- /* Presunu prvky prvni poloviny do praveho pole */
- for (i = 0; i < parameters->length-middle; i++) {
- parameters_right->array[i] = parameters->array[i+middle];
- }
- /* Nastavim delky poli */
- parameters_left->length = middle;
- parameters_right->length = parameters->length-middle;
- /* Spustim rekurzivne trideni pro levou a pravou polovinu pole */
- parameters_left->array = merge_sort(parameters_left);
- parameters_right->array = merge_sort(parameters_right);
- /* Sloucim pole a ulozim do vysledku */
- result = merge(parameters_left->array,middle, parameters_right->array, parameters->length-middle);
- /* Uvolnim alokovane leve a prave poloviny */
- free(parameters_left->array);
- free(parameters_right->array);
- free(parameters_left);
- free(parameters_right);
- return result;
- }
- }
- int * merge(int * left, int left_len, int * right, int right_len)
- {
- /* Nastavim si pocatecni indexy */
- int left_index = 0, right_index = 0, index = 0;
- /* Alokuji si vysledne pole */
- int * result = (int *) malloc((left_len+right_len) * sizeof(int));
- /* Postupne prochazim leve a prave pole dokud u jednoho nedojdu na konec */
- while (left_index < left_len && right_index < right_len) {
- /* Pokud je prvek v levem poli mensi nez v pravem, ulozim prvek z leveho pole
- * do vysledku, jinak z praveho a posunu indexy */
- if (left[left_index] <= right[right_index]) {
- result[index] = left[left_index++];
- } else {
- result[index] = right[right_index++];
- }
- index++;
- }
- /* Zbytek leveho pole zkopiruji */
- while (left_index < left_len) {
- result[index] = left[left_index++];
- index++;
- }
- /* Zbytek praveho pole zkopiruji */
- while (right_index < right_len) {
- result[index] = right[right_index++];
- index++;
- }
- return result;
- }
Add Comment
Please, Sign In to add comment