From 0a0b2f89ae4085f0c48471d317ce430a9e104308 Mon Sep 17 00:00:00 2001 From: norangebit Date: Tue, 13 Apr 2021 17:15:40 +0200 Subject: [PATCH] Add version 2 --- makefile | 12 ++++ src/parallel-v2.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 src/parallel-v2.c diff --git a/makefile b/makefile index 73894b5..a65d02e 100644 --- a/makefile +++ b/makefile @@ -7,14 +7,26 @@ sequential-time: src/sequential.c src/util.c src/kmp.c build parallel: src/parallel.c src/util.c src/kmp.c build mpicc -std=c99 src/parallel.c src/util.c src/kmp.c -lm -o build/kmp-p.out +parallel-2: src/parallel-v2.c src/util.c src/kmp.c build + mpicc -std=c99 src/parallel-v2.c src/util.c src/kmp.c -lm -o build/kmp-p-2.out + parallel-time: src/parallel.c src/util.c src/kmp.c build mpicc -std=c99 -D TIME src/parallel.c src/util.c src/kmp.c /usr/local/lib/libpapi.a -lm -o build/kmp-pt.out +parallel-time-2: src/parallel-v2.c src/util.c src/kmp.c build + mpicc -std=c99 -D TIME src/parallel-v2.c src/util.c src/kmp.c /usr/local/lib/libpapi.a -lm -o build/kmp-pt-2.out + parallel-log: src/parallel.c src/util.c src/kmp.c build mpicc -std=c99 -D LOG src/parallel.c src/util.c src/kmp.c -lm -o build/kmp-pl.out +parallel-log-2: src/parallel-v2.c src/util.c src/kmp.c build + mpicc -std=c99 -D LOG src/parallel-v2.c src/util.c src/kmp.c -lm -o build/kmp-pl-2.out + parallel-mpe: src/parallel.c src/util.c src/kmp.c build mpecc -std=c99 -mpilog -lpthread src/parallel.c src/util.c src/kmp.c -lm -o build/kmp-mpe.out +parallel-mpe-2: src/parallel-v2.c src/util.c src/kmp.c build + mpecc -std=c99 -mpilog -lpthread src/parallel-v2.c src/util.c src/kmp.c -lm -o build/kmp-mpe-2.out + build: mkdir build diff --git a/src/parallel-v2.c b/src/parallel-v2.c new file mode 100644 index 0000000..376426c --- /dev/null +++ b/src/parallel-v2.c @@ -0,0 +1,176 @@ +#include +#include +#include "kmp.h" +#include "util.h" +#include +#include + +#ifdef TIME +#include +#endif + +#define MASTER 0 +#define DEFAULT_TAG 17 + +int find_end(int residue, char *pattern, char *text, int shift); + +int main(int argc, char **argv) { + 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; + + 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); + + // send the residue to the next process + if (rank + 1 != size) { + MPI_Request request; + MPI_Isend(&residue, 1, MPI_INT, rank + 1, DEFAULT_TAG, MPI_COMM_WORLD, &request); + } + + // receiving the residue from the previous process + int other_residue = 0; + MPI_Request rec_rq; + if (rank != 0) { + MPI_Irecv(&other_residue, 1, MPI_INT, rank - 1, DEFAULT_TAG, MPI_COMM_WORLD, &rec_rq); + } + + // 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); + + 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 + size)); + + 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); + } + + if (rank != 0) { + MPI_Status myStatus; + MPI_Wait(&rec_rq, &myStatus); + if (residue != 0) { + int splitted_match = find_end(other_residue, pattern, private_text, shift); + MPI_Send(&splitted_match, 1, MPI_INT, MASTER, DEFAULT_TAG, MPI_COMM_WORLD); + } + } + + if (rank == MASTER) { + int splitted_match; + for (int i = 0; i < size - 1; i++) { + MPI_Recv(&splitted_match, 1, MPI_INT, MPI_ANY_SOURCE, DEFAULT_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + if (splitted_match > 0) { + total_matches[total_match_number] = splitted_match; + total_match_number++; + } + } + } + +#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); +#endif + } + +} + +int find_end(int residue, char *pattern, char *text, int shift) { + 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 -1; + + while (pattern_index < pattern_len && pattern[pattern_index] == text[text_index]) { + pattern_index++; + text_index++; + } + + if (pattern_index != pattern_len) return -1; + + return shift - residue; +} +