polaroid-pp

Schlieren and contour plot tool
git clone https://git.0xfab.ch/polaroid-pp.git
Log | Files | Refs | Submodules | README | LICENSE

commit cd663edf130f2edab7170fa0f2ab29d0be0cec94
parent 4969f5005a914bba9f19e820063ea64147028259
Author: Fabian Wermelinger <fabianw@mavt.ethz.ch>
Date:   Thu, 28 Apr 2016 16:43:14 +0200

implemented polaroidCameraMPI application

Diffstat:
MMakefile | 16++++------------
MMakefile.config | 3+--
Aapps/OrganizerMPI.cpp | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps/OrganizerMPI.h | 43+++++++++++++++++++++++++++++++++++++++++++
Dapps/OrganizerOMP.cpp | 60------------------------------------------------------------
Dapps/OrganizerOMP.h | 63---------------------------------------------------------------
Mapps/polaroidCamera/polaroidCameraMPI.cpp | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mthird_party/Makefile | 1+
Mthird_party/Makefile.cubismz | 1+
9 files changed, 187 insertions(+), 152 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,6 +1,6 @@ include ./Makefile.config -CC = g++ +CC = mpic++ HDR = $(wildcard src/*.h) SRC = $(wildcard src/*.cpp) @@ -15,27 +15,19 @@ APPPOBJ = ${APPSRC:.cpp=.o} polaroidCamera: third_party Polaroid $(APPOBJ) - $(CC) $(CPPFLAGS) $(INC) -o bin/polaroidCamera $(APPSRC) $(LIB) -lpng -lPolaroid + $(CC) $(CPPFLAGS) $(INC) -o bin/polaroidCamera $(APPSRC) -lPolaroid $(LIB) -lpng -lz Polaroid: third_party $(HDR) $(OBJ) ar rcs lib/libPolaroid.a $(OBJ) + ranlib lib/libPolaroid.a third_party: FORCE $(MAKE) -C third_party all FORCE: -# schlierenCamera: all schlierenCamera.cpp -# $(CC) $(CPPFLAGS) $(INC) -o schlierenCamera schlierenCamera.cpp $(OBJ) $(LIB) -lz -lpng -lhdf5 -lWaveletCompressor - -# hsvCamera: all hsvCamera.cpp -# $(CC) $(CPPFLAGS) $(INC) -o hsvCamera hsvCamera.cpp $(OBJ) $(LIB) -lz -lpng -lhdf5 -lWaveletCompressor - -# test: all -# (cd test; make all) - %.o: %.cpp - g++ $(CPPFLAGS) $(INC) -c $< -o $@ + $(CC) $(CPPFLAGS) $(INC) -c $< -o $@ clean: find . -iname "*~" -exec rm -f {} \; diff --git a/Makefile.config b/Makefile.config @@ -1,7 +1,7 @@ config ?= release bs ?= 16 align ?= 16 -omp ?= 1 +omp ?= 0 hdf ?= 1 cubismz ?= 1 prec ?= float @@ -41,5 +41,4 @@ else CPPFLAGS += -O3 -DNDEBUG endif -LIB += -lm -lz -ldl CPPFLAGS += -Wall -Wextra -Wno-deprecated -D_ALIGNBYTES_=$(align) -D_BLOCKSIZE_=$(bs) diff --git a/apps/OrganizerMPI.cpp b/apps/OrganizerMPI.cpp @@ -0,0 +1,64 @@ +// File : OrganizerMPI.cpp +// Date : Thu Apr 28 10:59:03 2016 +// Author : Fabian Wermelinger +// Description: MPI Organizer Implementation +// Copyright 2016 ETH Zurich. All Rights Reserved. +#include <string> +#include <iostream> +#include <cstdio> +#include <cstdlib> +#include "OrganizerMPI.h" + +using namespace std; + +OrganizerMPI::OrganizerMPI(const int argc, char ** const argv) : m_nscenes(0), m_scenes(nullptr), m_argc(1) +{ + m_isroot = (rank() == 0) ? true : false; + + // get scenes + bool bfoundScenes = false; + for (int i=1; i < argc; ++i) + { + const string key(argv[i]); + if (key == "-scenes") + { + m_scenes = (argv + (i+1)); + m_nscenes = argc - (i+1); + bfoundScenes = true; + break; + } + ++m_argc; + } + if (!bfoundScenes) + { + // Define input scenes (=input files) at the end of the argument list + // by using the option "-scenes". You can use globbing here if there + // are many scenes. + if (m_isroot) + { + cerr << "ERROR: No input scenes given. Abort..." << endl; + cerr << " : (Note: -scenes must be the last argument, followed by [list of] input files)" << endl; + } + abort(); + } +} + +vector<char*> OrganizerMPI::split_work() const +{ + const int myrank = rank(); + const int nranks = size(); + const int myshare = m_nscenes/nranks; + const int rem = m_nscenes - nranks * myshare; + vector<char*> myscenes(0); + if (m_nscenes <= nranks) + { + if (myrank < m_nscenes) myscenes.push_back(m_scenes[myrank]); + return myscenes; + } + + for (int i=0; i < myshare; ++i) // try to distribute work equally + myscenes.push_back(m_scenes[i*nranks + myrank]); + if (myrank < rem) + myscenes.push_back(m_scenes[myshare*nranks + myrank]); + return myscenes; +} diff --git a/apps/OrganizerMPI.h b/apps/OrganizerMPI.h @@ -0,0 +1,43 @@ +// File : OrganizerMPI.h +// Date : Thu Apr 28 09:53:58 2016 +// Author : Fabian Wermelinger +// Description: MPI Organizer +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef ORGANIZERMPI_H_8HFBYG90 +#define ORGANIZERMPI_H_8HFBYG90 + +#include <vector> +#include <mpi.h> + +class OrganizerMPI +{ +private: + int m_nscenes; + char** m_scenes; + int m_argc; + bool m_isroot; + +public: + OrganizerMPI(const int argc, char ** const argv); + + inline int size() const + { + int size; + MPI_Comm_size(MPI_COMM_WORLD, &size); + return size; + } + + inline int rank() const + { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + return rank; + } + + std::vector<char*> split_work() const; + inline int argc() const { return m_argc; } + inline bool isroot() const { return m_isroot; } + inline void wait() const { MPI_Barrier(MPI_COMM_WORLD); } +}; + +#endif /* ORGANIZERMPI_H_8HFBYG90 */ diff --git a/apps/OrganizerOMP.cpp b/apps/OrganizerOMP.cpp @@ -1,60 +0,0 @@ -// File : OrganizerOMP.cpp -// Date : Thu Apr 28 10:59:03 2016 -// Author : Fabian Wermelinger -// Description: OpenMP Organizer Implementation -// Copyright 2016 ETH Zurich. All Rights Reserved. -#include <string> -#include <iostream> -#include <cstdio> -#include <cstdlib> -#include "OrganizerOMP.h" - -using namespace std; - -OrganizerOMP::OrganizerOMP(const int argc, char ** const argv) : m_nscenes(0), m_scenes(nullptr), m_argc(1) -{ - // get scenes - bool bfoundScenes = false; - for (int i=1; i < argc; ++i) - { - const string key(argv[i]); - if (key == "-scenes") - { - m_scenes = (argv + (i+1)); - m_nscenes = argc - (i+1); - bfoundScenes = true; - break; - } - ++m_argc; - } - if (!bfoundScenes) - { - // Define input scenes (=input files) at the end of the argument list - // by using the option "-scenes". You can use globbing here if there - // are many scenes. - cerr << "ERROR: No input scenes given. Abort..." << endl; - cerr << " : (Note: -scenes must be the last argument, followed by [list of] input files)" << endl; - abort(); - } -} - -vector<char*> OrganizerOMP::split_work() const -{ - const int myID = tid(); - const int nthreads = size(); - const int myshare = m_nscenes/nthreads; - const int rem = m_nscenes - nthreads * myshare; - vector<char*> myscenes; - - for (int i=0; i < myshare; ++i) // try to distribute work equally - myscenes.push_back(m_scenes[i*nthreads + myID]); - - if (myID < rem) - myscenes.push_back(m_scenes[myshare*nthreads + myID]); - -#pragma omp critical - { - printf("[Thread %d/%d: Load = %d scene(s), start @ %s]\n", myID, nthreads, myscenes.size(), myscenes.front()); - } - return myscenes; -} diff --git a/apps/OrganizerOMP.h b/apps/OrganizerOMP.h @@ -1,63 +0,0 @@ -// File : OrganizerOMP.h -// Date : Thu Apr 28 09:53:58 2016 -// Author : Fabian Wermelinger -// Description: OpenMP Organizer -// Copyright 2016 ETH Zurich. All Rights Reserved. -#ifndef ORGANIZEROMP_H_8HFBYG90 -#define ORGANIZEROMP_H_8HFBYG90 - -#include <vector> -#ifdef _USE_OMP_ -#include <omp.h> -#endif /* _USE_OMP_ */ - - -class OrganizerOMP -{ -private: - int m_nscenes; - char** m_scenes; - int m_argc; - -public: - OrganizerOMP(const int argc, char ** const argv); - - static int max_size() - { -#ifdef _USE_OMP_ - return omp_get_max_threads(); -#else - return 1; -#endif /* _USE_OMP_ */ - } - - static void set_size(const int nthreads) - { -#ifdef _USE_OMP_ - return omp_set_num_threads(nthreads); -#endif /* _USE_OMP_ */ - } - - inline int size() const - { -#ifdef _USE_OMP_ - return omp_get_num_threads(); -#else - return 1; -#endif /* _USE_OMP_ */ - } - - inline int tid() const - { -#ifdef _USE_OMP_ - return omp_get_thread_num(); -#else - return 0; -#endif /* _USE_OMP_ */ - } - - std::vector<char*> split_work() const; - inline int argc() const { return m_argc; } -}; - -#endif /* ORGANIZEROMP_H_8HFBYG90 */ diff --git a/apps/polaroidCamera/polaroidCameraMPI.cpp b/apps/polaroidCamera/polaroidCameraMPI.cpp @@ -4,12 +4,11 @@ // Description: Polaroid Cam app // Copyright 2016 ETH Zurich. All Rights Reserved. #include <iostream> +#include <cstdio> +#include <string> #include <vector> -#ifdef _USE_OMP_ -#include <omp.h> -#endif /* _USE_OMP_ */ -#include "OrganizerOMP.h" +#include "OrganizerMPI.h" #include "ArgumentParser.h" #include "Polaroid.h" #include "Cartridges.h" @@ -19,22 +18,81 @@ using namespace std; int main(int argc, char* argv[]) { -#pragma omp parallel - { - OrganizerOMP threads(argc, argv); + MPI_Init(&argc, (char***)&argv); + + OrganizerMPI worker(argc, argv); + ArgumentParser myparser(worker.argc(), (const char**)argv); - ArgumentParser myparser(threads.argc(), (const char**)argv); + if (worker.isroot()) + { + cout << "Command Line: "; + for (int i = 0; i < argc; ++i) + cout << argv[i] << " "; + cout << endl; myparser.print_args(); + } + worker.wait(); + + + myparser.set_strict_mode(); + const string input_type = myparser("-input").asString(); + const string output_format = myparser("-format").asString(); + myparser.unset_strict_mode(); + + Cartridge* mycartridge; + PhotoPaper* myphoto; + if (myparser("-format").asString("png") == "png") + { + mycartridge = new NormalizerCartridge(myparser); + if (myparser("-type").asString("hsv") == "hsv") + myphoto = new PNG_HSV; + else if (myparser("-type").asString("hsv") == "mono") + myphoto = new PNG_MONO; + } + else if (myparser("-format").asString("png") == "hdf5") + { + mycartridge = new TransmissionCartridge(myparser); + myphoto = new PhotoHDF5; + } + + const double fraction = myparser("-fraction").asDouble(0.5); + const int direction = myparser("-direction").asInt(0); + const int channel = myparser("-channel").asInt(0); + const bool byte_swap = myparser("-swap").asBool(false); + const int wavelet_type = myparser("-wtype").asInt(1); - vector<char*> myscenes = threads.split_work(); + Polaroid mycam; + vector<char*> myscenes = worker.split_work(); + if (myscenes.size() > 0) + printf("[Worker %d/%d: Load = %d scene(s), start @ %s]\n", worker.rank(), worker.size(), myscenes.size(), myscenes.front()); + else + printf("[Worker %d/%d: Load = %d scene(s), start @ %s]\n", worker.rank(), worker.size(), myscenes.size(), "none"); + + size_t k = 0; + for (auto scene: myscenes) + { + string basename(scene); + if (basename.find_last_of(".") != string::npos) + basename = basename.substr(0, basename.find_last_of(".")); - Polaroid cam; - NormalizerCartridge transmission(myparser); - // PhotoHDF5 photo("hello"); - PNG_MONO photo("hello"); - cam.load_hdf5(myscenes[0], 0.5, 2, 0); - cam.capture(transmission, photo); + if (input_type == "hdf5") + mycam.load_hdf5(scene, fraction, direction, channel); + else if (input_type == "wavelet") + mycam.load_wavelet(scene, fraction, direction, channel, byte_swap, wavelet_type); + + myphoto->make_new(basename+"-polaroid", mycam.width(), mycam.height()); + mycam.capture(*mycartridge, *myphoto); + + ++k; + if (worker.isroot()) + printf("[Progress %3.1f %%]\n", static_cast<double>(k)/myscenes.size()*100.0); } + delete mycartridge; + delete myphoto; + + worker.wait(); + MPI_Finalize(); + return 0; } diff --git a/third_party/Makefile b/third_party/Makefile @@ -15,6 +15,7 @@ libCubismZ.a: libpng.a: $(OBJLib2) $(OBJLib3) ar rcs ../lib/libpng.a $(OBJLib2) $(OBJLib3) + ranlib ../lib/libpng.a .c.o: gcc -c $(CFLAGS) -o $@ $< diff --git a/third_party/Makefile.cubismz b/third_party/Makefile.cubismz @@ -5,6 +5,7 @@ OBJLib1 = ${CubismZ_SRC:.cpp=.o} all: $(OBJLib1) ar rcs ../lib/libCubismZ.a $(OBJLib1) + ranlib ../lib/libCubismZ.a .cpp.o: g++ -c $(CPPFLAGS) $(INC) -o $@ $<