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,
......
...@@ -16,17 +16,26 @@ namespace lsgrm ...@@ -16,17 +16,26 @@ 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)
{ {
// TODO parallelize this ...
if (myrank == 0)
{
TSegmenter segmenter; TSegmenter segmenter;
std::string nodesPath, edgesPath; std::string nodesPath, edgesPath;
std::cout << "Graph aggregation..." << std::endl; if (myrank == 0)
std::cout << "--- Graph aggregation...\n" << std::endl;
for(unsigned int row = 0; row < nbTilesY; ++row) for(unsigned int row = 0; row < nbTilesY; ++row)
{ {
for(unsigned int col = 0; col < nbTilesX; col++) for(unsigned int col = 0; col < nbTilesX; col++)
{ {
std::cout << "*" << std::flush; // std::cout << "*" << std::flush;
typename TSegmenter::GraphType graph; typename TSegmenter::GraphType graph;
// Load the graph // Load the graph
...@@ -39,55 +48,63 @@ namespace lsgrm ...@@ -39,55 +48,63 @@ namespace lsgrm
graph.m_Nodes.end()); graph.m_Nodes.end());
} }
} }
std::cout << "\nRemoving duplicated nodes and updating neighbors..." << std::endl; if (myrank == 0)
std::cout << "\nRemoving duplicated nodes and updating neighbors..." << std::endl;
for(unsigned int row = 0; row < nbTilesY; ++row) for(unsigned int row = 0; row < nbTilesY; ++row)
{ {
for(unsigned int col = 0; col < nbTilesX; col++) for(unsigned int col = 0; col < nbTilesX; col++)
{ {
std::cout << "*" << std::flush; // std::cout << "*" << std::flush;
// if (MyTurn(myrank,nprocs,row*nbTilesX + col))
{
std::cout << "Cleaning nodes of tile " << (row*nbTilesX + col) << " on " << (nbTilesX*nbTilesY) << std::endl;
std::unordered_map<long unsigned int, std::unordered_map<long unsigned int,
std::vector<typename TSegmenter::NodePointerType> > borderPixelMap; std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col, BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col,
nbTilesX, nbTilesY, borderPixelMap, imageWidth); nbTilesX, nbTilesY, borderPixelMap, imageWidth);
RemoveDuplicatedNodes<TSegmenter>(borderPixelMap, segmenter.m_Graph, imageWidth);
RemoveDuplicatedNodes<TSegmenter>(borderPixelMap, segmenter.m_Graph, imageWidth);
UpdateNeighborsOfNoneDuplicatedNodes<TSegmenter>(borderPixelMap,
UpdateNeighborsOfNoneDuplicatedNodes<TSegmenter>(borderPixelMap, imageWidth,
imageWidth, imageHeight);
imageHeight);
}
} }
} }
std::cout << "\nAchieve segmentation process..." << std::endl; if (myrank == 0)
{
// Segmentation of the graph std::cout << "\nAchieve segmentation process..." << std::endl;
segmenter.SetImageWidth(imageWidth);
segmenter.SetImageHeight(imageHeight); // Segmentation of the graph
segmenter.SetNumberOfComponentsPerPixel(imageBands); segmenter.SetImageWidth(imageWidth);
segmenter.SetParam(params); segmenter.SetImageHeight(imageHeight);
segmenter.SetThreshold(threshold); segmenter.SetNumberOfComponentsPerPixel(imageBands);
segmenter.SetDoBFSegmentation(true); segmenter.SetParam(params);
segmenter.SetNumberOfIterations(75); segmenter.SetThreshold(threshold);
segmenter.SetDoBFSegmentation(true);
lsrm::GraphOperations<TSegmenter>::PerfomAllIterationsWithLMBFAndConstThreshold(segmenter); segmenter.SetNumberOfIterations(75);
// Write output graph to the output graph directory lsrm::GraphOperations<TSegmenter>::PerfomAllIterationsWithLMBFAndConstThreshold(segmenter);
WriteGraph<TSegmenter>(segmenter.m_Graph, outputGraphDirectory, 0, 0);
// Write output graph to the output graph directory
typedef unsigned char ClusterPixelType; WriteGraph<TSegmenter>(segmenter.m_Graph, outputGraphDirectory, 0, 0);
typedef otb::VectorImage<ClusterPixelType, 2> ClusterImageType;
typedef otb::ImageFileWriter<ClusterImageType> ClusterImageWriterType; typedef unsigned char ClusterPixelType;
auto clusterWriter = ClusterImageWriterType::New(); typedef otb::VectorImage<ClusterPixelType, 2> ClusterImageType;
clusterWriter->SetFileName("out/finalimage.png"); typedef otb::ImageFileWriter<ClusterImageType> ClusterImageWriterType;
clusterWriter->SetInput(segmenter.GetClusteredImageOutput()); auto clusterWriter = ClusterImageWriterType::New();
clusterWriter->Update(); clusterWriter->SetFileName("out/finalimage.png");
clusterWriter->SetInput(segmenter.GetClusteredImageOutput());
clusterWriter->Update();
}
}
} }
template<class TSegmenter> template<class TSegmenter>
...@@ -103,124 +120,135 @@ namespace lsgrm ...@@ -103,124 +120,135 @@ 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)
{ {
long long unsigned int accumulatedMemory = 0; long long unsigned int accumulatedMemory = 0;
std::string nodesPath, edgesPath; std::string nodesPath, edgesPath;
isFusion = false; isFusion = false;
const unsigned int numberOfNeighborLayers = static_cast<unsigned int>(pow(2, niter + 1) - 2); const unsigned int numberOfNeighborLayers = static_cast<unsigned int>(pow(2, niter + 1) - 2);
std::cout << "Number of neighbor layers " << numberOfNeighborLayers << std::endl;
std::cout << "Partial segmentations..." << std::endl; if (myrank == 0)
std::cout << "--- Running partial segmentations...\nNumber of neighbor layers " << numberOfNeighborLayers << std::endl;
for(unsigned int row = 0; row < nbTilesY; ++row) for(unsigned int row = 0; row < nbTilesY; ++row)
{ {
for(unsigned int col = 0; col < nbTilesX; col++) for(unsigned int col = 0; col < nbTilesX; col++)
{ {
//std::cout << "*" << std::flush; //std::cout << "*" << std::flush;
TSegmenter segmenter; if (MyTurn(myrank, nprocs, row*nbTilesX + col))
std::cout << "Tile " << row << " " << col << std::endl; {
std::cout << "\tLoad graph..." << std::endl; TSegmenter segmenter;
// Load the graph std::cout << "Tile " << row << " " << col << std::endl;
nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; std::cout << "\tLoad graph..." << std::endl;
edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; // Load the graph
ReadGraph<TSegmenter>(segmenter.m_Graph, nodesPath, edgesPath); nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
ReadGraph<TSegmenter>(segmenter.m_Graph, nodesPath, edgesPath);
// Add stability margin to the graph // Add stability margin to the graph
{ {
std::cout << "\tAdd stability margin..." << std::endl; std::cout << "\tAdd stability margin..." << std::endl;
AddStabilityMargin<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], tmpDir, AddStabilityMargin<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], tmpDir,
row, col, nbTilesX, nbTilesY, row, col, nbTilesX, nbTilesY,
tileWidth, tileHeight); tileWidth, tileHeight);
std::unordered_map<long unsigned int,
std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
std::cout << "\tBuild border pixel map..." << std::endl; std::unordered_map<long unsigned int,
BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col, std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
nbTilesX, nbTilesY, borderPixelMap, imageWidth);
std::cout << "\tRemove duplicated nodes..." << std::endl; std::cout << "\tBuild border pixel map..." << std::endl;
RemoveDuplicatedNodes<TSegmenter>(borderPixelMap, segmenter.m_Graph, imageWidth); BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col,
nbTilesX, nbTilesY, borderPixelMap, imageWidth);
std::cout << "\tUpdate neighbors.." << std::endl; std::cout << "\tRemove duplicated nodes..." << std::endl;
UpdateNeighborsOfNoneDuplicatedNodes<TSegmenter>(borderPixelMap, RemoveDuplicatedNodes<TSegmenter>(borderPixelMap, segmenter.m_Graph, imageWidth);
imageWidth,
imageHeight);
std::cout << "\tRemove useless.." << std::endl; std::cout << "\tUpdate neighbors.." << std::endl;
RemoveUselessNodes<TSegmenter>(tiles[row*nbTilesX + col], segmenter.m_Graph, UpdateNeighborsOfNoneDuplicatedNodes<TSegmenter>(borderPixelMap,
row, col, nbTilesX, nbTilesY, imageWidth, numberOfNeighborLayers); imageWidth,
imageHeight);
} std::cout << "\tRemove useless.." << std::endl;
RemoveUselessNodes<TSegmenter>(tiles[row*nbTilesX + col], segmenter.m_Graph,
row, col, nbTilesX, nbTilesY, imageWidth, numberOfNeighborLayers);
}
// Segmentation of the graph
segmenter.SetImageWidth(imageWidth);
segmenter.SetImageHeight(imageHeight);
segmenter.SetNumberOfComponentsPerPixel(imageBands);
segmenter.SetParam(params);
segmenter.SetThreshold(threshold);
segmenter.SetDoBFSegmentation(false);
segmenter.SetNumberOfIterations(niter);
std::cout << "\tPartial segmentation.." << std::endl; // Segmentation of the graph
auto merge = lsrm::GraphOperations<TSegmenter>::PerfomAllIterationsWithLMBFAndConstThreshold(segmenter); segmenter.SetImageWidth(imageWidth);
segmenter.SetImageHeight(imageHeight);
segmenter.SetNumberOfComponentsPerPixel(imageBands);
segmenter.SetParam(params);
segmenter.SetThreshold(threshold);
segmenter.SetDoBFSegmentation(false);
segmenter.SetNumberOfIterations(niter);
if(merge == true) std::cout << "\tPartial segmentation.." << std::endl;
isFusion = true; auto merge = lsrm::GraphOperations<TSegmenter>::PerfomAllIterationsWithLMBFAndConstThreshold(segmenter);
std::cout << "\tRemove unstable segments..." << std::endl; if(merge == true)
// Remove unstable segments isFusion = true;
RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth);
// Retrieve the amount of memory to store this graph std::cout << "\tRemove unstable segments..." << std::endl;
accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter.m_Graph); // Remove unstable segments
RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth);
std::cout << "\tWrite graph..." << std::endl; // Retrieve the amount of memory to store this graph
// Write graph to temporay directory (warning specific to Baatz & Schape !!!) accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter.m_Graph);
WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col);
std::cout << "\tWrite graph..." << std::endl;
// Write graph to temporay directory (warning specific to Baatz & Schape !!!)
WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col);
}
} }
} }
std::cout << "Add stability margins to graph for the next round..."<< std::endl; MPI_Barrier(MPI_COMM_WORLD);
if (myrank == 0)
std::cout << "Add stability margins to graph for the next round..."<< std::endl;
// During this step we extract the stability margin for the next round // During this step we extract the stability margin for the next round
for(unsigned int row = 0; row < nbTilesY; ++row) for(unsigned int row = 0; row < nbTilesY; ++row)
{ {
for(unsigned int col = 0; col < nbTilesX; col++) for(unsigned int col = 0; col < nbTilesX; col++)
{ {
std::cout << "*" << std::flush; if (MyTurn(myrank, nprocs, row*nbTilesX + col))
typename TSegmenter::GraphType graph; {
// std::cout << "*" << std::flush;
typename TSegmenter::GraphType graph;
// Load the graph // Load the graph
nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
ReadGraph<TSegmenter>(graph, nodesPath, edgesPath); ReadGraph<TSegmenter>(graph, nodesPath, edgesPath);
// Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight - // Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight -
// and write them to the stability margin // and write them to the stability margin
{ {
std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap; std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap;
DetectBorderNodes<TSegmenter>(graph, tiles[row*nbTilesX + col], DetectBorderNodes<TSegmenter>(graph, tiles[row*nbTilesX + col],
borderNodeMap, imageWidth, imageHeight); borderNodeMap, imageWidth, imageHeight);
ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers); ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers);
std::string nodesPath = tmpDir + "tile_nodes_margin_" + std::string nodesPath = tmpDir + "tile_nodes_margin_" +
std::to_string(row) + "_" + std::to_string(col) + ".bin"; std::to_string(row) + "_" + std::to_string(col) + ".bin";
std::string edgesPath = tmpDir + "tile_edges_margin_" + std::string edgesPath = tmpDir + "tile_edges_margin_" +
std::to_string(row) + "_" + std::to_string(col) + ".bin"; std::to_string(row) + "_" + std::to_string(col) + ".bin";
WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath);
}
WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath);
}
std::cout << "Process " << myrank << " finished on tile " << (row*nbTilesX + col) << std::endl;
}
} }
} }
std::cout << std::endl; std::cout << std::endl;
...@@ -669,7 +697,9 @@ namespace lsgrm ...@@ -669,7 +697,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, // MPI rank
int nprocs) // MPI nb of process
{ {
using ImageType = typename TSegmenter::ImageType; using ImageType = typename TSegmenter::ImageType;
using Reader = otb::ImageFileReader<ImageType>; using Reader = otb::ImageFileReader<ImageType>;
...@@ -678,67 +708,73 @@ namespace lsgrm ...@@ -678,67 +708,73 @@ namespace lsgrm
isFusion = false; isFusion = false;
const unsigned int numberOfNeighborLayers = static_cast<unsigned int>(pow(2, niter2 + 1) - 2); const unsigned int numberOfNeighborLayers = static_cast<unsigned int>(pow(2, niter2 + 1) - 2);
std::cout << "Number of neighbor layers " << numberOfNeighborLayers << std::endl; if (myrank==0)
std::cout << "--- Running fist partial segmentation...\nNumber of neighbor layers " << numberOfNeighborLayers << std::endl;
for(unsigned int row = 0; row < nbTilesY; ++row) for(unsigned int row = 0; row < nbTilesY; ++row)
{ {
for(unsigned int col = 0; col < nbTilesX; col++) for(unsigned int col = 0; col < nbTilesX; col++)
{ {
// Reading image if (MyTurn(myrank, nprocs, row*nbTilesX + col))
auto tileReader = Reader::New(); {
tileReader->SetFileName(tileDir + "tile_" + std::to_string(row) + "_" + std::to_string(col) + ".tif"); // Reading image
tileReader->Update(); auto tileReader = Reader::New();
tileReader->SetFileName(tileDir + "tile_" + std::to_string(row) + "_" + std::to_string(col) + ".tif");
// Segmenting image tileReader->Update();
TSegmenter segmenter;
segmenter.SetParam(params); // Segmenting image
segmenter.SetThreshold(threshold); TSegmenter segmenter;
segmenter.SetDoBFSegmentation(false); segmenter.SetParam(params);
segmenter.SetNumberOfIterations(niter); segmenter.SetThreshold(threshold);
segmenter.SetInput(tileReader->GetOutput()); segmenter.SetDoBFSegmentation(false);
segmenter.Update(); segmenter.SetNumberOfIterations(niter);
segmenter.SetInput(tileReader->GetOutput());
if(segmenter.GetComplete() == false) segmenter.Update();
isFusion = true;
if(segmenter.GetComplete() == false)
// Rescale the graph to be in the reference of the image isFusion = true;
RescaleGraph<TSegmenter>(segmenter.m_Graph,
tiles[row*nbTilesX + col], // Rescale the graph to be in the reference of the image
row, RescaleGraph<TSegmenter>(segmenter.m_Graph,
col, tiles[row*nbTilesX + col],
margin, row,
tileWidth, col,
tileHeight, margin,
imageWidth); tileWidth,
tileHeight,
// Remove unstable segments imageWidth);
RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth);
// Remove unstable segments
// Retrieve the amount of memory to store this graph RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth);
accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter.m_Graph);
// Retrieve the amount of memory to store this graph
// Write graph to temporay directory (warning specific to Baatz & Schape !!!) accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter.m_Graph);
WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col);
// Write graph to temporay directory (warning specific to Baatz & Schape !!!)
// Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight -1 WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col);
// and write them to the stability margin
{ // Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight -1
std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap; // and write them to the stability margin
{
DetectBorderNodes<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap;
borderNodeMap, imageWidth, imageHeight);
DetectBorderNodes<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col],
borderNodeMap, imageWidth, imageHeight);
ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers);
std::string nodesPath = tmpDir + "tile_nodes_margin_" + ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers);
std::to_string(row) + "_" + std::to_string(col) + ".bin";
std::string edgesPath = tmpDir + "tile_edges_margin_" + std::string nodesPath = tmpDir + "tile_nodes_margin_" +
std::to_string(row) + "_" + std::to_string(col) + ".bin"; std::to_string(row) + "_" + std::to_string(col) + ".bin";
std::string edgesPath = tmpDir + "tile_edges_margin_" +
std::to_string(row) + "_" + std::to_string(col) + ".bin";
WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath);
}
WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath);
}
std::cout << "Process " << myrank << " finished on tile " << (row*nbTilesX + col) << std::endl;
}
} }
} }
......
...@@ -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