Commit 512b8e8f authored by BRAMAS Berenger's avatar BRAMAS Berenger
Browse files

add a partitions mapping class

parent e0c49f71
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
#ifndef FPARTITIONSMAPPING_HPP
#define FPARTITIONSMAPPING_HPP
// @SCALFMM_PRIVATE
#include "Utils/FGlobal.hpp"
#include "Utils/FMath.hpp"
#include "Utils/FAssert.hpp"
#include "../Utils/FHUtils.hpp"
#include <functional>
#include <memory>
template <class FReal, class LeafClass, class CellClass >
class FPartitionsMapping {
protected:
struct LeafNode {
FBlockDescriptor infos;
LeafClass leaf;
};
struct CellNode {
FBlockDescriptor infos;
CellClass cell;
};
const int dim;
int nbCells;
CellNode* cells;
int nbLeaves;
LeafNode* leaves;
int totalNbBlocks;
FPartitionsMapping(const FPartitionsMapping&) = delete;
FPartitionsMapping& operator=(const FPartitionsMapping&) = delete;
public:
explicit FPartitionsMapping(const int inDim, const int partitions[], const int nbPartitions,
const int ratioForLeaf = 0)
: dim(inDim),
nbCells(0), cells(nullptr),
nbLeaves(0), leaves(nullptr),
totalNbBlocks(0){
FAssertLF(nbPartitions <= inDim);
FAssertLF(1 <= nbPartitions);
for(int idxPartRow = 0 ; idxPartRow < nbPartitions ; ++idxPartRow){
for(int idxPartCol = 0 ; idxPartCol < nbPartitions ; ++idxPartCol){
if(idxPartRow == idxPartCol
|| partitions[idxPartRow]*partitions[idxPartCol] < ratioForLeaf){
nbLeaves += 1;
}
else{
nbCells += 1;
}
totalNbBlocks += 1;
}
}
leaves = new LeafNode[nbLeaves];
cells = new CellNode[nbCells];
int idxLeaf = 0;
int idxCell = 0;
int offsetRows = 0;
for(int idxPartRow = 0 ; idxPartRow < nbPartitions ; ++idxPartRow){
int offsetCols = 0;
for(int idxPartCol = 0 ; idxPartCol < nbPartitions ; ++idxPartCol){
if(idxPartRow == idxPartCol
|| partitions[idxPartRow]*partitions[idxPartCol] < ratioForLeaf){
leaves[idxLeaf].infos.row = offsetRows;
leaves[idxLeaf].infos.col = offsetCols;
leaves[idxLeaf].infos.nbRows = partitions[idxPartRow];
leaves[idxLeaf].infos.nbCols = partitions[idxPartCol];
leaves[idxLeaf].infos.level = 0;
idxLeaf += 1;
}
else{
cells[idxCell].infos.row = offsetRows;
cells[idxCell].infos.col = offsetCols;
cells[idxCell].infos.nbRows = partitions[idxPartRow];
cells[idxCell].infos.nbCols = partitions[idxPartCol];
cells[idxCell].infos.level = 1;
idxCell += 1;
}
offsetCols += partitions[idxPartCol];
}
FAssertLF(offsetCols == dim);
offsetRows += partitions[idxPartRow];
}
FAssertLF(offsetRows == dim);
}
~FPartitionsMapping(){
delete[] cells;
delete[] leaves;
}
int getNbBlocks() const {
return totalNbBlocks;
}
void forAllBlocksDescriptor(std::function<void(const FBlockDescriptor&)> callback){
for(int idxCell = 0 ; idxCell < nbCells ; ++idxCell){
callback(cells[idxCell].infos);
}
for(int idxLeaf = 0 ; idxLeaf < nbLeaves ; ++idxLeaf){
callback(leaves[idxLeaf].infos);
}
}
void forAllCellBlocks(std::function<void(const FBlockDescriptor&, CellClass&)> callback){
for(int idxCell = 0 ; idxCell < nbCells ; ++idxCell){
callback(cells[idxCell].infos,
cells[idxCell].cell);
}
}
void forAllLeafBlocks(std::function<void(const FBlockDescriptor&, LeafClass&)> callback){
for(int idxLeaf = 0 ; idxLeaf < nbLeaves ; ++idxLeaf){
callback(leaves[idxLeaf].infos,
leaves[idxLeaf].leaf);
}
}
template <class MatrixClass>
void fillBlocks(MatrixClass& matrix){
for(int idxCell = 0 ; idxCell < nbCells ; ++idxCell){
cells[idxCell].cell.fill(matrix.getBlock(
cells[idxCell].infos.row,
cells[idxCell].infos.col,
cells[idxCell].infos.nbRows,
cells[idxCell].infos.nbCols
),
cells[idxCell].infos.level);
}
for(int idxLeaf = 0 ; idxLeaf < nbLeaves ; ++idxLeaf){
leaves[idxLeaf].leaf.fill(matrix.getBlock(
leaves[idxLeaf].infos.row,
leaves[idxLeaf].infos.col,
leaves[idxLeaf].infos.nbRows,
leaves[idxLeaf].infos.nbCols
),
leaves[idxLeaf].infos.level);
}
}
template <class MatrixClass>
void fillBlocks(const MatrixClass& matrix){
for(int idxCell = 0 ; idxCell < nbCells ; ++idxCell){
cells[idxCell].cell.fill(matrix.getBlock(
cells[idxCell].infos.row,
cells[idxCell].infos.col,
cells[idxCell].infos.nbRows,
cells[idxCell].infos.nbCols
),
cells[idxCell].infos.level);
}
for(int idxLeaf = 0 ; idxLeaf < nbLeaves ; ++idxLeaf){
leaves[idxLeaf].leaf.fill(matrix.getBlock(
leaves[idxLeaf].infos.row,
leaves[idxLeaf].infos.col,
leaves[idxLeaf].infos.nbRows,
leaves[idxLeaf].infos.nbCols
),
leaves[idxLeaf].infos.level);
}
}
void gemv(FReal res[], const FReal vec[]) const {
for(int idxCell = 0 ; idxCell < nbCells ; ++idxCell){
cells[idxCell].cell.gemv(&res[cells[idxCell].infos.row],
&vec[cells[idxCell].infos.col]);
}
for(int idxLeaf = 0 ; idxLeaf < nbLeaves ; ++idxLeaf){
leaves[idxLeaf].leaf.gemv(&res[leaves[idxLeaf].infos.row],
&vec[leaves[idxLeaf].infos.col]);
}
}
void gemm(FReal res[], const FReal mat[], const int nbRhs) const {
for(int idxCell = 0 ; idxCell < nbCells ; ++idxCell){
cells[idxCell].cell.gemm(&res[cells[idxCell].infos.col],
&mat[cells[idxCell].infos.row],
nbRhs, dim);
}
for(int idxLeaf = 0 ; idxLeaf < nbLeaves ; ++idxLeaf){
leaves[idxLeaf].leaf.gemm(&res[leaves[idxLeaf].infos.col],
&mat[leaves[idxLeaf].infos.row],
nbRhs, dim);
}
}
};
#endif // FPARTITIONSMAPPING_HPP
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
// @SCALFMM_PRIVATE
#include "../Src/Containers/FPartitionsMapping.hpp"
#include "../Src/Utils/FSvgRect.hpp"
#include "../Src/Viewers/FDenseBlockWrapper.hpp"
#include "../Src/Blocks/FDenseBlock.hpp"
#include "Utils/FParameters.hpp"
#include "Utils/FParameterNames.hpp"
#include <memory>
int main(int argc, char** argv){
static const FParameterNames SvgOutParam = {
{"-fout", "--out", "-out"} ,
"Svg output directory."
};
static const FParameterNames DimParam = {
{"-N", "-nb", "-dim"} ,
"Dim of the matrix."
};
static const FParameterNames PartitionsParam = {
{"-part", "-parts", "-nbparts"} ,
"Number of partitions."
};
FHelpDescribeAndExit(argc, argv,"Test the bisection.",SvgOutParam,DimParam,FParameterDefinitions::OctreeHeight);
const int dim = FParameters::getValue(argc, argv, DimParam.options, 100);
const int nbPartitions = FParameters::getValue(argc, argv, PartitionsParam.options, 9);
const char* outputdir = FParameters::getStr(argc, argv, SvgOutParam.options, "/tmp/");
std::cout << "Config : dim = " << dim << "\n";
std::cout << "Config : nbPartitions = " << nbPartitions << "\n";
std::cout << "Config : outputdir = " << outputdir << "\n";
typedef double FReal;
typedef FDenseBlock<FReal> LeafClass;
typedef FDenseBlock<FReal> CellClass;
typedef FPartitionsMapping<FReal, LeafClass, CellClass> GridClass;
{
std::unique_ptr<int[]> partitions(new int[nbPartitions]);
{
int nbValuesLeft = dim;
for(int idxPartition = 0 ; idxPartition < nbPartitions-1 ; ++idxPartition){
partitions[idxPartition] = FMath::Max(1, int(drand48()*(nbValuesLeft-(nbPartitions-idxPartition))));
nbValuesLeft -= partitions[idxPartition];
}
partitions[nbPartitions-1] = nbValuesLeft;
}
GridClass bissection(dim, partitions.get(), nbPartitions);
FSvgRect output(outputdir, "partitionednp", dim);
bissection.forAllBlocksDescriptor([&](const FBlockDescriptor& info){
output.addRectWithLegend(info.col, info.row, info.nbCols, info.nbRows, info.level);
});
}
return 0;
}
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
// @SCALFMM_PRIVATE
#include "../Src/Containers/FPartitionsMapping.hpp"
#include "../Src/Viewers/FMatDense.hpp"
#include "../Src/Blocks/FDenseBlock.hpp"
#include "Utils/FParameters.hpp"
#include "Utils/FParameterNames.hpp"
#include <memory>
int main(int argc, char** argv){
static const FParameterNames DimParam = {
{"-N", "-nb", "-dim"} ,
"Dim of the matrix."
};
static const FParameterNames PartitionsParam = {
{"-part", "-parts", "-nbparts"} ,
"Number of partitions."
};
FHelpDescribeAndExit(argc, argv, "Test the bisection.", DimParam, FParameterDefinitions::OctreeHeight);
const int dim = FParameters::getValue(argc, argv, DimParam.options, 100);
const int nbPartitions = FParameters::getValue(argc, argv, PartitionsParam.options, 5);
std::cout << "Config : dim = " << dim << "\n";
std::cout << "Config : nbPartitions = " << nbPartitions << "\n";
typedef double FReal;
typedef FMatDense<FReal> MatrixClass;
MatrixClass matrix(dim);
for(int idxRow = 0; idxRow < dim ; ++idxRow){
for(int idxCol = 0; idxCol < dim ; ++idxCol){
matrix.setVal(idxRow, idxCol, 1./(FMath::Abs(FReal(idxRow-idxCol))+1.));
}
}
std::unique_ptr<FReal[]> vec(new FReal[dim]);
for(int idxVal = 0 ; idxVal < dim ; ++idxVal){
vec[idxVal] = 1.0;
}
std::unique_ptr<FReal[]> resTest(new FReal[dim]);
FSetToZeros(resTest.get(), dim);
{
for(int idxRow = 0; idxRow < dim ; ++idxRow){
for(int idxCol = 0; idxCol < dim ; ++idxCol){
resTest[idxRow] += vec[idxCol] * matrix.getVal(idxRow, idxCol);
}
}
}
{
typedef FDenseBlock<FReal> LeafClass;
typedef FDenseBlock<FReal> CellClass;
typedef FPartitionsMapping<FReal, LeafClass, CellClass> GridClass;
std::unique_ptr<int[]> partitions(new int[nbPartitions]);
{
int nbValuesLeft = dim;
for(int idxPartition = 0 ; idxPartition < nbPartitions-1 ; ++idxPartition){
partitions[idxPartition] = FMath::Max(1, int(drand48()*(nbValuesLeft-(nbPartitions-idxPartition))));
nbValuesLeft -= partitions[idxPartition];
}
partitions[nbPartitions-1] = nbValuesLeft;
}
GridClass grid(dim, partitions.get(), nbPartitions);
grid.fillBlocks(matrix);
std::unique_ptr<FReal[]> resDense(new FReal[dim]);
FSetToZeros(resDense.get(), dim);
grid.gemv(resDense.get(), vec.get());
FMath::FAccurater<FReal> testDense(resTest.get(), resDense.get(), dim);
std::cout << "Test Dense partitions mapping, Error = " << testDense << "\n";
}
return 0;
}
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