#include #include #include "kmp.h" #include "util.h" #include #include #ifdef TIME #include #endif #define MASTER 0 #define DEFAULT_TAG 17 void find_end(int, char *, char *, int **, int *); void search_for_splitted_pattern(int *residue, int *match_number, int **matches); void calculate_absolute_indices(int match_number, int *matches); void collect_results(int *match_number, int *matches); int rank, size; int text_len; // length of all text int private_text_len; // length of private text int pattern_len; //length of the pattern char *text; char *pattern; int remain = 0; int *text_piece; int *displacements; char *private_text; int *match_numbers; int *total_matches; int total_match_number; int main(int argc, char **argv) { MPI_Init(NULL, NULL); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Barrier(MPI_COMM_WORLD); #ifdef TIME long_long start_time = PAPI_get_real_usec(); #endif char *text_file_path = get_text_file(argc, argv); private_text = read_file_portion(text_file_path, size, rank, &private_text_len, &remain); pattern = read_file("data/pattern.txt", &pattern_len); #ifdef LOG printf("%d -> input: %s\n", rank, private_text); printf("%d -> text len: %d\n", rank, private_text_len); #endif // create and build lps array int lps[pattern_len]; create_lps(pattern, pattern_len, lps); // search for matches int match_number = 0; int residue; #ifdef TIME long_long start_search = PAPI_get_real_usec(); #endif int *matches = search_pattern(private_text, pattern, lps, &match_number, &residue); search_for_splitted_pattern(&residue, &match_number, &matches); #ifdef TIME long_long stop_search = PAPI_get_real_usec(); #endif //free(private_text); calculate_absolute_indices(match_number, matches); #ifdef LOG printf("%d -> result number: %d\n", rank, match_number); #endif #ifdef TIME long_long start_collect = PAPI_get_real_usec(); #endif collect_results(&match_number, matches); #ifdef TIME long_long end_time = PAPI_get_real_usec(); #endif MPI_Finalize(); if (rank == MASTER) { printf("total matches: %d\n", total_match_number); #ifdef LOG printf("matches index: "); print_array(total_matches, total_match_number); #endif #ifdef TIME printf("total elapsed: %d\n", end_time - start_time); printf("search elapsed: %d\n", stop_search - start_search); printf("collect elapsed: %d\n", end_time - start_collect); #endif } } void find_end(int residue, char *pattern, char *text, int **matches, int *match_number) { int pattern_index = residue; int text_index = 0; int text_len = strlen(text); int pattern_len = strlen(pattern); if (pattern_len - residue > text_len) return; while (pattern_index < pattern_len && pattern[pattern_index] == text[text_index]) { pattern_index++; text_index++; } if (pattern_index != pattern_len) return; *match_number = *match_number + 1; *matches = (int *) realloc(*matches, *match_number * sizeof(int)); (*matches)[*match_number - 1] = -residue; } void search_for_splitted_pattern(int *residue, int *match_number, int **matches) { // send the residue to the next process if (rank + 1 != size) { MPI_Send(residue, 1, MPI_INT, rank + 1, DEFAULT_TAG, MPI_COMM_WORLD); } // receiving the residue from the previous process if (rank != 0) { MPI_Recv(residue, 1, MPI_INT, rank - 1, DEFAULT_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE); if (*residue != 0) // search for a split match find_end(*residue, pattern, private_text, matches, match_number); } } void calculate_absolute_indices(int match_number, int *matches) { // transformation of match indices from relative to absolute position. int shift = rank * (private_text_len - remain); // the rest is zero for all but the last process apply_shift(shift, matches, match_number); } void collect_results(int *match_number, int *matches) { if (rank == MASTER) { // allocation for the array containing the number of matches of each process match_numbers = (int *) malloc(sizeof(int) * size); } // collection of the number of matches from each process MPI_Gather(match_number, 1, MPI_INT, match_numbers, 1, MPI_INT, MASTER, MPI_COMM_WORLD); if (rank == MASTER) { // preparation of the data structures needed to receive match indices from all processes total_match_number = sum_array(match_numbers, size); total_matches = (int *) malloc(sizeof(int) * total_match_number); displacements = (int *) malloc(sizeof(int) * size); displacements[0] = 0; for (int i = 0; i < size - 1; ++i) { displacements[i + 1] = displacements[i] + match_numbers[i]; } } // collection of match indices from each process // gatherv is necessary because each process will have a different number of matches MPI_Gatherv( matches, *match_number, MPI_INT, total_matches, match_numbers, displacements, MPI_INT, MASTER, MPI_COMM_WORLD ); if (rank == MASTER) { free(match_numbers); free(displacements); } }