Skip to content

Commit

Permalink
added horizontal stripped MPI
Browse files Browse the repository at this point in the history
  • Loading branch information
EricBAndrews committed Apr 18, 2021
1 parent be0e540 commit 93ed83a
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
!.gitignore

# Extensions, misc
.DS_Store
*.DS_Store
*.e
*.o
*.dSYM
2 changes: 1 addition & 1 deletion src/common/nw-mpi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
#define SHIFTBITS 31
#define LONGBITS 63

#define COMMBUF_SIZE 64
#define COMMBUF_SIZE 1280

#endif
9 changes: 6 additions & 3 deletions src/mpi/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ COMMON = ../common
OPT = -O3
FLAGS = -Wall $(OPT) -I $(COMMON)

all: nw-mpi.e
all: mpi-vert.e mpi-horz.e

nw-mpi.e: helper.o nw-mpi.cpp $(COMMON)/nw-mpi.hpp $(COMMON)/mpidriver.cpp
$(CC) $(FLAGS) -o nw-mpi.e nw-mpi.cpp helper.o
mpi-vert.e: helper.o mpi-vert.cpp $(COMMON)/nw-mpi.hpp mpi-vert-driver.cpp
$(CC) $(FLAGS) -o mpi-vert.e mpi-vert.cpp helper.o

mpi-horz.e: helper.o mpi-horz.cpp $(COMMON)/nw-mpi.hpp mpi-horz-driver.cpp
$(CC) $(FLAGS) -o mpi-horz.e mpi-horz.cpp helper.o

helper.o: $(COMMON)/helper.hpp $(COMMON)/helper.cpp
$(CC) $(FLAGS) -c $(COMMON)/helper.cpp
Expand Down
95 changes: 95 additions & 0 deletions src/mpi/mpi-horz-driver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <chrono>
#include <iostream>

// TODO
// tune openMP to handle horizontal better?

int main(int argc, char** argv) {
if (argc != 3) {
printf("error: incorrect number of arguments (expected 2, got %i)\n",
argc - 1);
return 1;
}

MPI_Init(NULL, NULL);
int nProc, rank;
MPI_Comm_size(MPI_COMM_WORLD, &nProc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

dnaArray s1, s2;
try {
s1 = readSequence(argv[1]);
s2 = readSequence(argv[2]);
}

catch (std::string e) {
std::cout << "ERROR: no such file " << e << std::endl;
printf("ERROR: file not found\n");
return 1;
}

long int nRows = ((s2.size + 1) / nProc) + (rank > 0);
if (rank == nProc - 1) { nRows += (s2.size + 1) % nProc; }

long int size = nRows * (long int)(s1.size + 1);
int* table = new int[size];
for (long int i = 0; i < size; i += 1024) { table[i] = 0; }

// get start time in ms since epoch
long int wallStart = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();

// print start time
// printf("P%i | wallStart: %li\n", rank, wallStart);

// run the algorithm
needlemanWunsch(s1, s2, nRows, rank, nProc, table);

// get end time in ms since epoch
long int wallEnd = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();

// print end time
// printf("P%i | wallEnd: %li\n", rank, wallEnd);

MPI_Barrier(MPI_COMM_WORLD);


// collect and display time info on rank 0
if (rank == 0) {
// first process to start--used as start for timer
long int first = wallStart;

// collect start times, get minimum
long int recStart, recEnd;
for (int i = 1; i < nProc; ++i) {
MPI_Recv(&recStart, 1, MPI_LONG, i, i, MPI_COMM_WORLD, NULL);
first = (recStart < first) ? recStart: first;
}

// get last time (guaranteed to be last process by data deps)
MPI_Recv(&recEnd, nProc-1, MPI_LONG, nProc-1, nProc-1,
MPI_COMM_WORLD, NULL);

printf("time: %li\n", recEnd - first);
}

// send time info to rank 0
else {
MPI_Send(&wallStart, 1, MPI_LONG, 0, rank, MPI_COMM_WORLD);
}
if (rank == nProc - 1) {
MPI_Send(&wallEnd, 1, MPI_LONG, 0, rank, MPI_COMM_WORLD);
}

MPI_Barrier(MPI_COMM_WORLD);

// display final score
if (rank == nProc - 1) {
printf("final score: %i\n", table[size-1]);
}

MPI_Finalize();

return 0;
}
101 changes: 101 additions & 0 deletions src/mpi/mpi-horz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include "nw-mpi.hpp"

// takes in the array to be filled--don't care about the allocation time
void needlemanWunsch(dnaArray s1, dnaArray s2, long int nRows,
int rank, int nProc, int* t) {
// note: s1 across top, s2 down side

// convenience
long int nCols = s1.size + 1;
int a, b, c, m; // temps for max calculation

// necessary for Isend
// MPI_Request* dummy = new MPI_Request;

// first index of s2 in this table (last index of rank-1's work)
long int start = ((s2.size + 1) / nProc) * rank - (rank > 0);

// populate first column
for (long int i = 0; i < nRows; ++i) { t[i*nCols] = (i + start) * GAP; }

// RANK 0
// never receives; only sends to rank 1
if (rank == 0) {
// populate first row
for (long int i = 0; i < nCols; ++i) { t[i] = i * GAP; }

for (long int h = 1; h < nCols; h += COMMBUF_SIZE) {
long int jMax = (h + COMMBUF_SIZE < nCols) ? h + COMMBUF_SIZE : nCols;
for (long int i = 1; i < nRows; ++i) {
for (long int j = h; j < jMax; ++j) {
m = -(s1.dna[j-1] == s2.dna[start+i-1]);
a = t[((i-1) * nCols) + j-1] + ((m & MATCH) | (~m & MISMATCH));
b = t[((i-1) * nCols) + j] + GAP;
c = t[(i * nCols) + j-1] + GAP;

a = a - (((a - b) >> SHIFTBITS) & (a - b));
a = a - (((a - c) >> SHIFTBITS) & (a - c));
t[(i * nCols) + j] = a;
}
}
MPI_Send(&t[(nRows-1)*nCols+h], jMax - h, MPI_INT, 1, 0,
MPI_COMM_WORLD);
}
}

// RANK N-1
// never sends; only receives from rank-1
else if (rank == nProc - 1) {
for (long int h = 1; h < nCols; h += COMMBUF_SIZE) {
long int jMax = (h + COMMBUF_SIZE < nCols) ? h + COMMBUF_SIZE : nCols;

// receive into first row
MPI_Recv(&t[h], jMax - h, MPI_INT, rank-1, rank-1,
MPI_COMM_WORLD, NULL);

for (long int i = 1; i < nRows; ++i) {
for (long int j = h; j < jMax; ++j) {
m = -(s1.dna[j-1] == s2.dna[start+i-1]);
a = t[((i-1) * nCols) + j-1] + ((m & MATCH) | (~m & MISMATCH));
b = t[((i-1) * nCols) + j] + GAP;
c = t[(i * nCols) + j-1] + GAP;

a = a - (((a - b) >> SHIFTBITS) & (a - b));
a = a - (((a - c) >> SHIFTBITS) & (a - c));
t[(i * nCols) + j] = a;
}
}
}
}

// ALL OTHER RANKS
// receive at the start, then send
else {
for (long int h = 1; h < nCols; h += COMMBUF_SIZE) {
long int jMax = (h + COMMBUF_SIZE < nCols) ? h + COMMBUF_SIZE : nCols;

// receive into first row
MPI_Recv(&t[h], COMMBUF_SIZE, MPI_INT, rank-1, rank-1,
MPI_COMM_WORLD, NULL);

for (long int i = 1; i < nRows; ++i) {
for (long int j = h; j < jMax; ++j) {
m = -(s1.dna[j-1] == s2.dna[start+i-1]);
a = t[((i-1) * nCols) + j-1] + ((m & MATCH) | (~m & MISMATCH));
b = t[((i-1) * nCols) + j] + GAP;
c = t[(i * nCols) + j-1] + GAP;

a = a - (((a - b) >> SHIFTBITS) & (a - b));
a = a - (((a - c) >> SHIFTBITS) & (a - c));
t[(i * nCols) + j] = a;
}
}
MPI_Send(&t[(nRows-1)*nCols+h], jMax-h, MPI_INT, rank+1,
rank, MPI_COMM_WORLD);
}
}

return;
}

#include "mpi-horz-driver.cpp"
File renamed without changes.
7 changes: 3 additions & 4 deletions src/mpi/nw-mpi.cpp → src/mpi/mpi-vert.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "../common/nw-mpi.hpp"
#include "nw-mpi.hpp"

// takes in the array to be filled--don't care about the allocation time
void needlemanWunsch(dnaArray s1, dnaArray s2, int nCols,
void needlemanWunsch(dnaArray s1, dnaArray s2, long int nCols,
int rank, int nProc, int* t) {
// note: s1 across top, s2 down side

Expand All @@ -18,7 +18,6 @@ void needlemanWunsch(dnaArray s1, dnaArray s2, int nCols,

// populate first row
for (long int i = 0; i < nCols; ++i) { t[i] = (i + start) * GAP; }
for (long int i = 0; i < nCols; ++i) { t[i] = (i + start) * GAP; }

// RANK 0
// never receives; only sends to rank 1
Expand Down Expand Up @@ -109,4 +108,4 @@ void needlemanWunsch(dnaArray s1, dnaArray s2, int nCols,
return;
}

#include "../common/mpidriver.cpp"
#include "mpi-vert-driver.cpp"
1 change: 1 addition & 0 deletions src/serial/bdna-link
3 changes: 1 addition & 2 deletions src/serial/serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ void needlemanWunsch(dnaArray s1, dnaArray s2, int* t) {
t[(i * nCols) + j] = a;
}
}

// printTable(t, nRows, nCols);

return;
}

Expand Down

0 comments on commit 93ed83a

Please sign in to comment.