Commit 61654bc5 authored by remicres's avatar remicres
Browse files

MPI implementation of step 1,2,3. Some work is needed for step 4...

Showing with 397 additions and 234 deletions
+397 -234
...@@ -4,58 +4,71 @@ ...@@ -4,58 +4,71 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if(argc != 8)
{ int myrank, nprocs;
// img/test.tif tiles/ 125 125 4 tmp/ MPI_Init(&argc, &argv);
std::cerr << "[input image] [tile directory] [tile width] [tile height] [number of first iterations] [temporary directory] [output directory]" MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
<< std::endl; MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
return 1;
} if (myrank==0)
std::cout << "Number of MPI process : " << nprocs << std::endl;
/* Parse command line arguments */
const std::string imagePath = argv[1]; if(argc != 8)
std::string tileDir = argv[2]; // May be corrected if badly written. {
const unsigned int tileWidth = atoi(argv[3]); // img/test.tif tiles/ 125 125 4 tmp/
const unsigned int tileHeight = atoi(argv[4]); std::cerr << "[input image] [tile directory] [tile width] [tile height] [number of first iterations] [temporary directory] [output directory]"
const unsigned int niter = atoi(argv[5]); << std::endl;
std::string tmpDir = argv[6]; // May be corrected if badly written. return 1;
std::string outDir = argv[7]; }
/* /* Parse command line arguments */
const std::string imagePath = argv[1];
std::string tileDir = argv[2]; // May be corrected if badly written.
const unsigned int tileWidth = atoi(argv[3]);
const unsigned int tileHeight = atoi(argv[4]);
const unsigned int niter = atoi(argv[5]);
std::string tmpDir = argv[6]; // May be corrected if badly written.
std::string outDir = argv[7];
/*
To add: To add:
internal memory available internal memory available
If we have to do the image division If we have to do the image division
if we have to clean up the directory if we have to clean up the directory
the output directory in case the global graph cannot fit in memory the output directory in case the global graph cannot fit in memory
*/ */
using ImageType = otb::VectorImage<float, 2>; using ImageType = otb::VectorImage<float, 2>;
using SegmenterType = lsrm::BaatzSegmenter<ImageType>; using SegmenterType = lsrm::BaatzSegmenter<ImageType>;
using ControllerType = lsgrm::Controller<SegmenterType>; using ControllerType = lsgrm::Controller<SegmenterType>;
ControllerType controller;
ControllerType controller; controller.SetInputImage(imagePath);
controller.SetInputImage(imagePath); controller.SetTileDirectory(tileDir);
controller.SetTileDirectory(tileDir); controller.SetTemporaryDirectory(tmpDir);
controller.SetTemporaryDirectory(tmpDir); controller.SetOutputGraphDirectory(outDir);
controller.SetOutputGraphDirectory(outDir);
// Memory configuration
// Memory configuration controller.SetInternalMemoryAvailable(4096ul);
controller.SetInternalMemoryAvailable(512ul); controller.SetTileWidth(tileWidth);
controller.SetTileWidth(500); controller.SetTileHeight(tileHeight);
controller.SetTileHeight(500); controller.SetNumberOfFirstIterations(niter);
controller.SetNumberOfFirstIterations(6);
// MPI configuration
// Specific parameters controller.SetNumberOfProcess(nprocs);
lsrm::BaatzParam params; controller.SetProcessRank(myrank);
params.m_SpectralWeight = 0.7;
params.m_ShapeWeight = 0.3; // Specific parameters
controller.SetSpecificParameters(params); lsrm::BaatzParam params;
controller.SetThreshold(60*60); params.m_SpectralWeight = 0.7;
params.m_ShapeWeight = 0.3;
controller.RunSegmentation(); controller.SetSpecificParameters(params);
controller.SetThreshold(60*60);
return 0;
controller.RunSegmentation();
MPI_Finalize();
return 0;
} }
...@@ -33,6 +33,8 @@ namespace lsgrm ...@@ -33,6 +33,8 @@ namespace lsgrm
void SetSpecificParameters(const SegmentationParameterType& params); void SetSpecificParameters(const SegmentationParameterType& params);
void SetThreshold(const float& t); void SetThreshold(const float& t);
void SetInternalMemoryAvailable(long long unsigned int v); // expecting a value in Mbytes. void SetInternalMemoryAvailable(long long unsigned int v); // expecting a value in Mbytes.
void SetNumberOfProcess(int n) {m_NumberOfProcess = n;} ;
void SetProcessRank(int i) {m_ProcessRank = i;} ;
private: private:
...@@ -66,6 +68,8 @@ namespace lsgrm ...@@ -66,6 +68,8 @@ namespace lsgrm
unsigned int m_Margin; unsigned int m_Margin;
unsigned int m_TileWidth; unsigned int m_TileWidth;
unsigned int m_TileHeight; unsigned int m_TileHeight;
int m_NumberOfProcess;
int m_ProcessRank;
std::vector<ProcessingTile> m_Tiles; std::vector<ProcessingTile> m_Tiles;
}; };
} // end of namespace lsgrm } // end of namespace lsgrm
......
...@@ -28,21 +28,29 @@ namespace lsgrm ...@@ -28,21 +28,29 @@ namespace lsgrm
} }
// Divide the input image if necessary // Divide the input image if necessary
if(m_ImageDivisionActivated) if(m_ImageDivisionActivated && (m_ProcessRank == 0))
SplitOTBImage<ImageType>(m_InputImage, m_TileDirectory, m_TileWidth, {
m_TileHeight, m_Margin, m_NumberOfFirstIterations); std::cout << "Splitting tiles in " << m_TileDirectory << std::endl;
boost::timer t; t.restart();
SplitOTBImage<ImageType>(m_InputImage, m_TileDirectory, m_TileWidth,
m_TileHeight, m_Margin, m_NumberOfFirstIterations);
ShowTime(t);
}
MPI_Barrier(MPI_COMM_WORLD);
// Retrieve the problem configuration // Retrieve the problem configuration
RetrieveProblemConfiguration(); RetrieveProblemConfiguration();
// Print values // Print values
std::cout << m_Memory << " bytes, tile dimension " << m_TileWidth << " X " << m_TileHeight std::cout << m_Memory << " bytes, tile dimension " << m_TileWidth << " X " << m_TileHeight
<< ", margin" << m_Margin << " niter " << m_NumberOfFirstIterations << std::endl; << ", margin " << m_Margin << " niter " << m_NumberOfFirstIterations << std::endl;
// Boolean indicating if there are remaining fusions // Boolean indicating if there are remaining fusions
bool isFusion = false; bool isFusion = false;
// Run first partial segmentation // Run first partial segmentation
MPI_Barrier(MPI_COMM_WORLD);
boost::timer t; t.restart();
auto accumulatedMemory = RunFirstPartialSegmentation<TSegmenter>(m_SpecificParameters, auto accumulatedMemory = RunFirstPartialSegmentation<TSegmenter>(m_SpecificParameters,
m_Threshold, m_Threshold,
m_NumberOfFirstIterations, m_NumberOfFirstIterations,
...@@ -57,12 +65,20 @@ namespace lsgrm ...@@ -57,12 +65,20 @@ namespace lsgrm
m_ImageWidth, m_ImageWidth,
m_ImageHeight, m_ImageHeight,
m_TemporaryDirectory, m_TemporaryDirectory,
isFusion); isFusion,
m_ProcessRank,
std::cout << "Accumulated memory " << accumulatedMemory << " bytes, there is fusion "<< isFusion << std::endl; m_NumberOfProcess);
// Gathering useful variables
GatherUsefulVariables(accumulatedMemory, isFusion, m_ProcessRank, m_NumberOfProcess);
// Time monitoring
if (m_ProcessRank == 0)
ShowTime(t);
while(accumulatedMemory > m_Memory && isFusion) while(accumulatedMemory > m_Memory && isFusion)
{ {
isFusion = false; isFusion = false;
accumulatedMemory = RunPartialSegmentation<TSegmenter>(m_SpecificParameters, accumulatedMemory = RunPartialSegmentation<TSegmenter>(m_SpecificParameters,
m_Threshold, m_Threshold,
...@@ -76,12 +92,20 @@ namespace lsgrm ...@@ -76,12 +92,20 @@ namespace lsgrm
m_ImageWidth, m_ImageWidth,
m_ImageHeight, m_ImageHeight,
m_ImageBands, m_ImageBands,
isFusion); isFusion,
std::cout << "Accumulated memory " << accumulatedMemory << " bytes, there is fusion " m_ProcessRank,
<< isFusion << std::endl; m_NumberOfProcess);
// Gathering useful variables
GatherUsefulVariables(accumulatedMemory, isFusion, m_ProcessRank, m_NumberOfProcess);
} }
if(accumulatedMemory <= m_Memory) // Time monitoring
if (m_ProcessRank == 0)
ShowTime(t);
if(accumulatedMemory <= m_Memory && m_ProcessRank == 0)
{ {
// Merge all the graphs // Merge all the graphs
MergeAllGraphsAndAchieveSegmentation<TSegmenter>(m_SpecificParameters, MergeAllGraphsAndAchieveSegmentation<TSegmenter>(m_SpecificParameters,
...@@ -96,7 +120,12 @@ namespace lsgrm ...@@ -96,7 +120,12 @@ namespace lsgrm
m_ImageHeight, m_ImageHeight,
m_ImageBands, m_ImageBands,
isFusion, isFusion,
m_OutputGraphDirectory); m_OutputGraphDirectory,
m_ProcessRank,
m_NumberOfProcess);
ShowTime(t);
} }
else else
{ {
......
...@@ -28,7 +28,9 @@ namespace lsgrm ...@@ -28,7 +28,9 @@ namespace lsgrm
const unsigned int imageHeight, const unsigned int imageHeight,
const unsigned int imageBands, const unsigned int imageBands,
bool& isFusion, bool& isFusion,
const std::string& outputGraphDirectory); const std::string& outputGraphDirectory,
int myrank,
int nprocs);
template<class TSegmenter> template<class TSegmenter>
long long unsigned int RunFirstPartialSegmentation(const typename TSegmenter::ParameterType& params, long long unsigned int RunFirstPartialSegmentation(const typename TSegmenter::ParameterType& params,
...@@ -44,7 +46,9 @@ namespace lsgrm ...@@ -44,7 +46,9 @@ namespace lsgrm
const unsigned int imageWidth, const unsigned int imageWidth,
const unsigned int imageHeight, const unsigned int imageHeight,
const std::string& tmpDir, const std::string& tmpDir,
bool& isFusion); bool& isFusion,
int myrank,
int nprocs);
template<class TSegmenter> template<class TSegmenter>
long long unsigned int RunPartialSegmentation(const typename TSegmenter::ParameterType& params, long long unsigned int RunPartialSegmentation(const typename TSegmenter::ParameterType& params,
...@@ -60,7 +64,9 @@ namespace lsgrm ...@@ -60,7 +64,9 @@ namespace lsgrm
const unsigned int imageWidth, const unsigned int imageWidth,
const unsigned int imageHeight, const unsigned int imageHeight,
const unsigned int imageBands, const unsigned int imageBands,
bool& isFusion); bool& isFusion,
int myrank,
int nprocs);
template<class TSegmenter> template<class TSegmenter>
void RemoveUselessNodes(ProcessingTile& tile, void RemoveUselessNodes(ProcessingTile& tile,
......
This diff is collapsed.
...@@ -11,4 +11,79 @@ ...@@ -11,4 +11,79 @@
#include <stack> #include <stack>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/progress.hpp>
#include "mpi/mpi.h"
#define TAG_SUM 0
#define TAG_AVERAGE 1
#define TAG_BORDER 2
#define TAG_PIECE 3
/*
* This function returns TRUE if it's to the process #myrank to do the
* work on the yard #div in a pool of #nprocs threads
*/
bool MyTurn(int myrank, int nprocs, int div)
{
int proc = 0;
if (nprocs != 0)
proc = div % nprocs;
return (proc == myrank);
}
/*
* This function gather the given value in other process, and update it
*/
template<typename T>
void GatherMe(T& x, MPI_Datatype dataType, int myrank, int nprocs)
{
if (myrank == 0)
{
// Master process
// Gather
for (unsigned int p = 1 ; p < nprocs ; p++)
{
T partial_sum;
MPI_Recv( &partial_sum, 1, dataType, p, TAG_PIECE, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
x += partial_sum;
}
// Dispatch
for (unsigned int p = 1 ; p < nprocs ; p++)
MPI_Send(&x, 1, dataType, p, TAG_PIECE, MPI_COMM_WORLD);
}
else
{
// Slave process
MPI_Send(&x, 1, dataType, 0, TAG_PIECE, MPI_COMM_WORLD);
MPI_Recv(&x, 1, dataType, 0, TAG_PIECE, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
}
/*
* Gather accumulatedMemory and isFusion variables
*/
void GatherUsefulVariables(unsigned long long int& accumulatedMemory, bool& isFusion, int myrank, int nprocs)
{
MPI_Barrier(MPI_COMM_WORLD);
int isFusionInteger = 0;
long long int accumulatedMemoryLLI = static_cast<long long int>(accumulatedMemory);
if (isFusion)
isFusionInteger = 1;
GatherMe<int>(isFusionInteger, MPI_INT, myrank, nprocs);
GatherMe<long long int>(accumulatedMemoryLLI, MPI_LONG_LONG_INT, myrank, nprocs);
accumulatedMemory = static_cast<long long unsigned int>(accumulatedMemoryLLI);
if (isFusionInteger>0)
isFusion = true;
if (myrank == 0)
std::cout << "Accumulated memory " << accumulatedMemory << " bytes, there is fusion "<< isFusion << std::endl;
}
/*
* Print time elapsed
*/
void ShowTime(boost::timer t)
{
std::cout << "--- Process duration : " << t.elapsed() << std::endl;
t.restart();
}
#endif #endif
Supports Markdown
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