Commit febd5361 authored by Alexandru Dura's avatar Alexandru Dura

Fix race condition and add tests

parent f2fa8d28
......@@ -5,6 +5,7 @@
#include <cmath>
#include <cstddef>
#include <cassert>
#include <omp.h>
#define DEFAULT_COMM MPI_COMM_WORLD
......@@ -98,22 +99,22 @@ static void writeData(int rank, Problem &p, const char *pauseFile) {
printf("%d: Problem written out to file %s\n", rank, pauseFile);
}
static bool isMainThread() {
int isMainThread = 0;
MPI_Is_thread_main(&isMainThread);
return isMainThread;
}
int main(int argc, char **argv) {
// Process arguments for checkpoint facility
const char *pauseFile = nullptr;
const char *restartFile = nullptr;
const char *paramFile = "diffusion.in";
const char *outputFile = "pollution.pgm";
for (int i = 1; i < argc; ++i) {
if (!strncmp(argv[i], "-p=", 3)) {
pauseFile = argv[i] + 3;
} else if (!strncmp(argv[i], "-r=", 3)) {
restartFile = argv[i] + 3;
} else if (!strncmp(argv[i], "-f=", 3)) {
paramFile = argv[i] + 3;
} else if (!strncmp(argv[i], "-o=", 3)) {
outputFile = argv[i] + 3;
}
}
......@@ -134,7 +135,7 @@ int main(int argc, char **argv) {
MPI_Type_commit(&GlobalProblemConfig_t);
if (rank == 0) {
read_param(&config.xdim, &config.ydim, &config.cx, &config.cy, &config.maxiter);
read_param(paramFile, &config.xdim, &config.ydim, &config.cx, &config.cy, &config.maxiter);
}
MPI_Bcast(&config, 1, GlobalProblemConfig_t, 0, DEFAULT_COMM);
......@@ -152,27 +153,35 @@ int main(int argc, char **argv) {
Problem p(nsize, rank, localXdim, localYdim, nGates, nGates, gateVal);
double startTime = MPI_Wtime();
unsigned nOMPThreads;
#pragma omp parallel default(none) \
shared(p, restartFile, pauseFile, rank, config, nsize)
shared(p, restartFile, pauseFile, rank, config, nsize, nOMPThreads)
{
#ifdef _OPENMP
nOMPThreads = omp_get_num_threads();
#else
nOMPThreads = 1;
#endif
// Initialize inside the parallel region. This is the first
// time data is touched, so we want to make sure it ends up
// close to the core that performs the computation.
p.initialize();
#pragma omp single
if (restartFile)
if (restartFile) {
// read in the data, if requested
readData(rank, p, restartFile);
}
// Simulate
for (int i = 0; i < config.maxiter; ++i) {
// Check if this is the main thread, if so, exchange the halos
if (isMainThread())
exchangeHalos(rank, nsize, p);
// Let a single thread do the halo exchange. There is an implicit barrier
// at the end of the single section, so this means that all the threads
// wait until the halos are echanged before proceeding.
#pragma omp single
exchangeHalos(rank, nsize, p);
// step
p.step(config.cx, config.cy);
}
......@@ -183,12 +192,19 @@ int main(int argc, char **argv) {
writeData(rank, p, pauseFile);
}
} // end of pramga omp parallel
double totalTime = MPI_Wtime() - startTime;
// Compute the global min and max
double localMin, localMax;
double globalMin, globalMax;
std::tie(localMin, localMax) = p.getField().minMax();
#pragma omp parallel default(none) \
shared(p) \
reduction(min:localMin) \
reduction(max:localMax)
{
std::tie(localMin, localMax) = p.getField().minMax();
} // end of pragma omp parallel
MPI_Allreduce(&localMin, &globalMin, 1, MPI_DOUBLE, MPI_MIN, DEFAULT_COMM);
MPI_Allreduce(&localMax, &globalMax, 1, MPI_DOUBLE, MPI_MAX, DEFAULT_COMM);
......@@ -207,7 +223,14 @@ int main(int argc, char **argv) {
// Compute the squred local residual; for this we need
// the up-to-date halos
exchangeHalos(rank, nsize, p);
double resNorm2 = p.residualSquared(config.cx, config.cy);
double resNorm2;
#pragma omp parallel default(none) \
shared(config, p) \
reduction(+:resNorm2)
{
resNorm2 = p.residualSquared(config.cx, config.cy);
} // end of pragma omp parallel
double gatherResNorm2;
// Sum up the residuals from all the nodes and put the result
......@@ -218,13 +241,15 @@ int main(int argc, char **argv) {
// We're done gathering the images, write it out
MPI_Wait(&gatherImg, MPI_STATUS_IGNORE);
if (rank == 0) {
write_pgm("polution.pgm", resultImg, bitdepth);
write_pgm(outputFile, resultImg, bitdepth);
}
// We're done gathering the residuals and summing them up
MPI_Wait(&gatherNorm, MPI_STATUS_IGNORE);
if (rank == 0) {
printf("Norm of the residual: %f\n", std::sqrt(gatherResNorm2));
double resNorm = std::sqrt(gatherResNorm2);
// printf("Norm of the residual: %f\n", std::sqrt(gatherResNorm2));
printf("%d,%d,%f,%f\n", nsize, nOMPThreads, totalTime, resNorm);
}
MPI_Finalize();
......
......@@ -10,19 +10,22 @@ CXX=g++
MPICXX=mpic++
CXX_FLAGS=-fopenmp
all: main main-debug test
all: diffusion diffusion-debug test
main-debug : Main.cpp $(CPP_SOURCE_FILES) $(HEADER_FILES)
diffusion-debug : Main.cpp $(CPP_SOURCE_FILES) $(HEADER_FILES)
$(CXX) $(MPIFLAGS) $(CXX_FLAGS) -O0 -g -Wall Main.cpp $(CPP_SOURCE_FILES) $(MPI_LD_FLAGS) -o $@
main : Main.cpp $(CPP_SOURCE_FILES) $(HEADER_FILES)
$(CXX) $(MPIFLAGS) $(CXX_FLAGS) -O3 Main.cpp $(CPP_SOURCE_FILES) $(MPI_LD_FLAGS) -o main
diffusion : Main.cpp $(CPP_SOURCE_FILES) $(HEADER_FILES)
$(CXX) $(MPIFLAGS) $(CXX_FLAGS) -O3 Main.cpp $(CPP_SOURCE_FILES) $(MPI_LD_FLAGS) -o $@
test : Test.cpp $(CPP_SOURCE_FILES) $(HEADER_FILES)
$(CXX) -g -O0 Test.cpp $(CPP_SOURCE_FILES) -o test
$(CXX) -g -O0 Test.cpp $(CPP_SOURCE_FILES) -o $@
run-test : test diffusion
./run-test.sh
clean :
rm *.o
rm main-debug
rm main
rm -f *.o
rm diffusion-debug
rm diffusion
rm test
......@@ -11,8 +11,6 @@ int main() {
}
}
f.print(std::cout);
for (int i = 0; i < 3 + 2; ++i) {
for (int j = 0; j < 4 + 2; ++j) {
assert(f[i][j] == (double) (i + j));
......
......@@ -3,9 +3,9 @@
#include <string>
#include "Matrix.h"
void read_param(int* pxdim, int* pydim, double* pcx, double* pcy, int* pmaxiter)
void read_param(const char *paramFile, int* pxdim, int* pydim, double* pcx, double* pcy, int* pmaxiter)
{
FILE *fp = fopen( "diffusion.in", "r" );
FILE *fp = fopen(paramFile, "r" );
if ( fp == NULL )
{
fprintf(stderr, "No parameter file: diffusion.in found for reading!\n");
......@@ -54,7 +54,7 @@ void write_pgm(const std::string &filename, const Matrix<int> &image, int bitwid
fprintf( fp, "%i \n", bitwidth-1 );
for (i=0; i<height; i++)
for (j=0; j<width; j++)
fprintf( fp, "%i ", image[i][j]);
fprintf( fp, "%i\n", image[i][j]);
fclose(fp);
}
......@@ -2,5 +2,5 @@
#include "Matrix.h"
#include <string>
void read_param(int* pxdim, int* pydim, double* pcx, double* pcy, int* pmaxiter);
void read_param(const char *paramFile, int* pxdim, int* pydim, double* pcx, double* pcy, int* pmaxiter);
void write_pgm(const std::string &filename, const Matrix<int> &image, int bitwidth);
#!/bin/bash
echo "=== TEST 1: internal structures"
./test
if [[ $? == 0 ]]
then
echo "PASS"
else
echo "FAIL"
fi
echo "=== TEST 2: resume restart"
OMP_NUM_THREADS=4 mpiexec --bind-to core ./diffusion -p=test.dat -f=diffusion-100.in
OMP_NUM_THREADS=4 mpiexec --bind-to core ./diffusion -r=test.dat -f=diffusion-100.in -o=pollution-100-100.pgm
OMP_NUM_THREADS=4 mpiexec --bind-to core ./diffusion -f=diffusion-200.in -o=pollution-200.pgm
cmp pollution-200.pgm pollution-100-100.pgm
if [[ $? == 0 ]]
then
echo "=== PASS"
else
echo "*** FAIL"
fi
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment