Commit d2cff93f authored by Quentin Khan's avatar Quentin Khan

Merge branch 'balancing' : Creation of a new program to run performance tests.

parents 26a0f75b f5c0e6ee
......@@ -7,6 +7,17 @@
#include <type_traits>
/**
* \brief Empty trait class.
* \author Quentin Khan
*
* This class is used to check whether a cell class has FCostCell in its
* inheritance tree.
*/
class FCostCellTypeTrait {};
/**
* \brief Cell with a cost memory for balance computations.
* \author Quentin Khan
......@@ -18,7 +29,7 @@
* \tparam CostType The type to use in order to store the cost. Defaults to FSize.
*/
template<typename BaseClass, typename CostType = FSize>
class FCostCell : public BaseClass {
class FCostCell : public BaseClass, virtual public FCostCellTypeTrait {
static_assert(std::is_arithmetic<CostType>::value,
"The cell cost type must be an arithmetic type.");
......
#ifndef _ALGOLOADERCOSTZONES_HPP_
#define _ALGOLOADERCOSTZONES_HPP_
#include "PerfTestUtils.hpp"
#include "Core/FFmmAlgorithm.hpp"
#include "BalanceTree/FFmmAlgorithmThreadBalanced.hpp"
#include "BalanceTree/FCostCell.hpp"
#include "BalanceTree/FCostZones.hpp"
/**
* \brief Algorithm loader for the CostZones algorithm.
*
* \warning : This loader requires that the KernelLoader supply a type definition
* for a `CostKernelClass`
*/
template <class _TreeLoader, template<typename> class _KernelLoader>
class AlgoLoaderCostZones : public FAlgoLoader<_TreeLoader, _KernelLoader> {
public:
using TreeLoader = _TreeLoader;
using KernelLoader = _KernelLoader<TreeLoader>;
using FReal = typename TreeLoader::FReal;
using CellClass = typename TreeLoader::CellClass;
using ContainerClass = typename TreeLoader::ContainerClass;
using LeafClass = typename TreeLoader::LeafClass;
using OctreeClass = typename TreeLoader::OctreeClass;
using KernelClass = typename KernelLoader::KernelClass;
using CostKernelClass= typename KernelLoader::CostKernelClass;
static_assert(std::is_base_of<FCostCellTypeTrait, CellClass>::value,
"The tree cells must derive from FCostCell.");
using FMMClass = FFmmAlgorithmThreadBalanced
<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass>;
using CostFmmClass = FFmmAlgorithm
<OctreeClass, CellClass, ContainerClass, CostKernelClass, LeafClass>;
TreeLoader& _treeLoader;
KernelLoader& _kernelLoader;
/// Builds the loader
AlgoLoaderCostZones(FPerfTestParams& /*params*/,
TreeLoader& treeLoader,
KernelLoader& kernelLoader) :
_treeLoader(treeLoader),
_kernelLoader(kernelLoader) {
}
/// Computes the tree cells costs then runs the costzones and FMM algorithms.
void run() {
OctreeClass* p_tree = &(_treeLoader._tree);
// Compute tree cells costs
CostFmmClass costAlgo(p_tree, &(_kernelLoader._costKernel));
this->time.tic();
costAlgo.execute();
this->time.tac();
std::cout << "Generating tree cost: " << this->time.elapsed() << "s.\n";
FCostZones<OctreeClass, CellClass> costzones(p_tree, omp_get_max_threads());
this->time.tic();
costzones.run();
this->time.tac();
std::cout << "Generating cost zones: " << this->time.elapsed() << "s.\n";
this->time.tic();
FMMClass algo(p_tree, &(_kernelLoader._kernel), costzones.getZoneBounds(), costzones.getLeafZoneBounds());
algo.execute();
this->time.tac();
}
};
#endif
#ifndef _ALGOLOADERTASK_HPP_
#define _ALGOLOADERTASK_HPP_
#include "PerfTestUtils.hpp"
#include "Core/FFmmAlgorithmTask.hpp"
template <class _TreeLoader, template<typename> class _KernelLoader>
class AlgoLoaderTask : public FAlgoLoader<_TreeLoader, _KernelLoader> {
public:
using TreeLoader = _TreeLoader;
using KernelLoader = _KernelLoader<TreeLoader>;
using FReal = typename TreeLoader::FReal;
using CellClass = typename TreeLoader::CellClass;
using ContainerClass = typename TreeLoader::ContainerClass;
using LeafClass = typename TreeLoader::LeafClass;
using OctreeClass = typename TreeLoader::OctreeClass;
using KernelClass = typename KernelLoader::KernelClass;
using FMMClass = FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass>;
TreeLoader& _treeLoader;
KernelLoader& _kernelLoader;
AlgoLoaderTask(FPerfTestParams& /*params*/,
TreeLoader& treeLoader,
KernelLoader& kernelLoader) :
_treeLoader(treeLoader),
_kernelLoader(kernelLoader) {
}
void run() {
FMMClass algo(&(_treeLoader._tree), &(_kernelLoader._kernel));
algo.execute();
}
};
#endif
#ifndef _ALGOLOADERTHREAD_HPP_
#define _ALGOLOADERTHREAD_HPP_
#include "PerfTestUtils.hpp"
#include "Core/FFmmAlgorithmThread.hpp"
template <class _TreeLoader, template<typename> class _KernelLoader>
class AlgoLoaderThread : public FAlgoLoader<_TreeLoader, _KernelLoader> {
public:
using TreeLoader = _TreeLoader;
using KernelLoader = _KernelLoader<TreeLoader>;
using FReal = typename TreeLoader::FReal;
using CellClass = typename TreeLoader::CellClass;
using ContainerClass = typename TreeLoader::ContainerClass;
using LeafClass = typename TreeLoader::LeafClass;
using OctreeClass = typename TreeLoader::OctreeClass;
using KernelClass = typename KernelLoader::KernelClass;
using FMMClass = FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass>;
TreeLoader& _treeLoader;
KernelLoader& _kernelLoader;
AlgoLoaderThread(FPerfTestParams& /*params*/,
TreeLoader& treeLoader,
KernelLoader& kernelLoader) :
_treeLoader(treeLoader),
_kernelLoader(kernelLoader) {
}
void run() {
FMMClass algo(&(_treeLoader._tree), &(_kernelLoader._kernel), false);
algo.execute();
}
};
#endif
#ifndef _KERNELLOADERFCHEBSYM_HPP_
#define _KERNELLOADERFCHEBSYM_HPP_
#include "PerfTestUtils.hpp"
#include "Kernels/Interpolation/FInterpMatrixKernel.hpp"
#include "Kernels/Chebyshev/FChebSymKernel.hpp"
#include "BalanceTree/FChebSymCostKernel.hpp"
/**
* \brief Kernel loader for the symetric Chebyshev kernel.
*
* \warning This loader requires that TreeLoader::CellClass inherits from
* FChebCell.
*
* \note This loader also provides the typedef CostKernelClass and a member
* _costKernel that cam be used by the AlgoLoaderCostZones.
*/
template <typename _TreeLoader>
class KernelLoaderFChebSym : public FKernelLoader<_TreeLoader> {
public:
// Required type definitions
using TreeLoader = _TreeLoader;
using FReal = typename TreeLoader::FReal;
/// Must derive from FChebCell
using CellClass = typename TreeLoader::CellClass;
using ContainerClass = typename TreeLoader::ContainerClass;
using OctreeClass = typename TreeLoader::OctreeClass;
using MatrixKernelClass = FInterpMatrixKernelR<FReal>;
using KernelClass = FChebSymKernel <FReal, CellClass, ContainerClass,
MatrixKernelClass, TreeLoader::ORDER>;
/// Kernel class used to compute the tree cell costs.
using CostKernelClass = FChebSymCostKernel<FReal, CellClass, ContainerClass,
MatrixKernelClass, TreeLoader::ORDER,
OctreeClass>;
// Meaningfull (?) error message.
static_assert(std::is_base_of<FChebCell<FReal,TreeLoader::ORDER>,CellClass>::value,
"TreeLoader::CellClass must derive from FChebCell");
const FReal epsilon = 1e-4;
const MatrixKernelClass _matrixKernel;
/// kernel used to compute the tree cells interactions.
KernelClass _kernel;
/// Kernel used to compute the tree cells costs.
CostKernelClass _costKernel;
/// Builds the loader and loads the kernel.
KernelLoaderFChebSym(FPerfTestParams& /*params*/, TreeLoader& treeLoader) :
_matrixKernel(),
_kernel(treeLoader._tree.getHeight(),
treeLoader._tree.getBoxWidth(),
treeLoader._tree.getBoxCenter(),
&_matrixKernel),
_costKernel(&(treeLoader._tree), epsilon){
}
};
#endif
/**
* \file
* \author Quentin Khan
*
* This program is used to run different performance tests for the various
* algorithms that have been implemented for ScalFMM.
*
* See the PerfUtils.hpp file classes for some more in depth information. Run
* with argument --help for usage information.
*/
#include <iostream>
#include <string>
#include "Utils/FParameters.hpp"
#include "Utils/FParameterNames.hpp"
#include "PerfTestUtils.hpp"
#include "TreeLoaderFCheb.hpp"
#include "KernelLoaderFChebSym.hpp"
#include "AlgoLoaderThread.hpp"
#include "AlgoLoaderTask.hpp"
#include "AlgoLoaderCostZones.hpp"
/**
* \brief Runs a generic sequence of actions to use an algorithm.
*
* This function runs the basic steps that are needed to run an FMM algorithm
* over a set of particles. It does the following steps :
*
* - Load a tree using the class defined as a TreeLoader
* - Prepares the needed kernels using the KernelLoader
* - Prepares and runs the algorithm using the AlgorithmLoader
*
* See documentation of FTreeLoader, FKernelLoader, FAlgoLoader.
*/
template <class TreeLoader,
template <typename TL> class KernelLoader,
template <typename TL, template <typename TL> class KL> class AlgoLoader>
void runperf(FPerfTestParams& params)
{
TreeLoader treeLoader(params);
KernelLoader<TreeLoader> kernelLoader(params, treeLoader);
AlgoLoader<TreeLoader, KernelLoader> algoLoader(params, treeLoader, kernelLoader);
algoLoader.run();
}
int main (int argc, char** argv)
{
FHelpDescribeAndExit(argc, argv,
"Driver for Chebyshev interpolation kernel (1/r kernel).",
FParameterDefinitions::InputFile,
FParameterDefinitions::OctreeHeight,
FParameterDefinitions::OctreeSubHeight,
FParameterDefinitions::NbThreads,
{{"--algo"},"Algorithm to run (costzones, basic-static,"
" basic-dynamic, task)"});
FPerfTestParams params;
{
using namespace FParameterDefinitions;
using namespace FParameters;
params.filename = getStr(argc,argv,InputFile.options,
"../Data/unitCubeXYZQ100.bfma");
params.treeHeight = getValue(argc, argv, OctreeHeight.options, 5);
params.subTreeHeight = getValue(argc, argv, OctreeSubHeight.options, 2);
params.nbThreads = getValue(argc, argv, NbThreads.options, 1);
params.algo = getStr(argc,argv,{"--algo"},"task");
}
if( "basic-dynamic" == params.algo ) {
runperf<TreeLoaderFCheb<>, KernelLoaderFChebSym, AlgoLoaderThread>(params);
} else if( "task" == params.algo ) {
runperf<TreeLoaderFCheb<>, KernelLoaderFChebSym, AlgoLoaderTask>(params);
} else if ( "costzones" == params.algo ) {
runperf<TreeLoaderFCheb<>, KernelLoaderFChebSym, AlgoLoaderCostZones>(params);
}
}
#ifndef _PERFTESTUTILS_HPP_
#define _PERFTESTUTILS_HPP_
#include <string>
#include "Utils/FTic.hpp"
#include "Files/FFmaGenericLoader.hpp"
#include "Containers/FOctree.hpp"
/**
* \brief Store the PerfTest program parameters.
*/
struct FPerfTestParams {
int subTreeHeight = 2; ///< Subtree height.
int treeHeight = 5; ///< Tree height.
int nbThreads = 1; ///< Maximum number of threads (when used).
std::string filename = ""; ///< Particles file.
std::string algo = "task"; ///< Algorithm to run.
};
/**
* \brief Base class for tree loaders.
*
* This class itself does not provide anything but a base on which to build tree
* loaders. A tree loader should satisfy the following rules.
*
* - Define the public typedefs : CellClass, ContainerClass, LeafClass,
* OctreeClass.
* - Provide public acces to a member of type OctreeClass _tree as the tree
* that is loaded.
* - Tree loading must happen at construction.
* - It may provide any other members or typdefs required by a special
* FKernelLoader or FAlgoLoader.
*
* For convenience, this class provides a timer and a basic loadTree method that
* should be enough to load a tree from and FMA file.
*
* \note It is not mandatory that a loader inherit from this class. It must
* however follow the aforementioned rules.
*/
class FTreeLoader {
public:
/// A timer
/** Is used to time the loadTree method.
*/
FTic time;
protected:
/**
* \brief A template which type is always false.
*
* This template is only expanded by the compiler when it is requested
* (ie. the compiler will not try to optimize out its value.). Must be used
* to create false static_assert to catch unintended use of a template.
*/
template <typename... Args>
struct false_type {
bool value = false;
};
/**
* \brief Failure method for unimplemented loadTree templates.
*
* This template will catch unspecialised call to the loadTree method and
* will cause the compilation to fail with a (somewhat) meaningfull message.
*/
template <typename...Args>
void loadTree(Args...) {
static_assert(false_type<Args...>::value,
"I don't know how to load this tree with this loader...");
}
/**
* \brief Simple method to load a tree from a FMA file.
*
* The template parameters are usualy guessed by the compiler.
*
* \tparam OctreeClass The class of the tree to fill.
* \tparam FReal The floating point type.
*
* \param loader The file loader to read from the file.
* \param tree The tree to be filled.
*/
template <class OctreeClass, typename FReal>
void loadTree(FFmaGenericLoader<FReal>& loader, OctreeClass& tree) {
std::cout << "Creating & inserting particles" << std::flush;
time.tic();
FPoint<FReal> position;
FReal physicalValue = 0.0;
for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart) {
// Read particle per particle from file
loader.fillParticle(&position,&physicalValue);
// put particle in octree
tree.insert(position, idxPart, physicalValue);
}
time.tac();
std::cout << " Done (" << time.elapsed() << "s)." << std::endl;
}
};
/**
* \brief Base class for kernel loaders.
*
* This class itself does not provide anything but a base on which to build
* kernel loaders. A kernel loader should satisfy the following rules.
*
* - Define the public typedefs : TreeLoader, KernelClass.
* - Provide public acces to a member of type Kernelclass _kernel as the
* kernel that is loaded.
* - Kernel loading must happen at construction.
* - It may provide any other members or typdefs required by a special
* FAlgoLoader.
*
* For convenience, this class provides a timer.
*
* \tparam _TreeLoader The tree loader that was used.
*
* \note It is not mandatory that a loader inherit from this class. It must
* however follow the aforementioned rules.
*/
template<class _TreeLoader>
class FKernelLoader {
/// The tree loader that was used (see FTreeLoader).
using TreeLoader = _TreeLoader;
public:
FTic time;
};
/**
* \brief Base class for algorithm loaders.
*
* This class itself does not provide anything but a base on which to build
* algorithm loaders. A kernel loader should satisfy the following rules.
*
* - Define the public typedefs : TreeLoader, KernelLoader.
* - Provide public acces to a member of type
* \link TreeLoader Treeloader::OctreeClass* \endlink` _algo`
* as the algorithm that is loaded. This pointer should be valid from the
* end of the ::run method to the destruction of the loader.
* - It may provide any other members or typdefs.
*
* For convenience, this class provides a timer.
*
* \tparam _TreeLoader The tree loader that was used.
* \tparam _KernelLoader The kernel loader *template* that was used, the
* KernelLoader type will then be _KernelLoader<_TreeLoader>.
*
* \note It is not mandatory that a loader inherit from this class. It must
* however follow the aforementioned rules.
*/
template <class _TreeLoader, template<typename> class _KernelLoader>
class FAlgoLoader {
/// The tree loader that was used (see FTreeLoader).
using TreeLoader = _TreeLoader;
/// The kernel loader that was used (see FKernelLoader).
using KernelLoader = _KernelLoader<TreeLoader>;
public:
/// A timer.
FTic time;
/// Method that runs the algorithm.
virtual void run() = 0;
};
#endif
#ifndef _TREELOADERFCHEB_HPP_
#define _TREELOADERFCHEB_HPP_
#include "PerfTestUtils.hpp"
#include "Kernels/Chebyshev/FChebCell.hpp"
#include "Containers/FOctree.hpp"
#include "Components/FSimpleLeaf.hpp"
#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp"
#include "BalanceTree/FCostCell.hpp"
/**
* \brief Tree loader for a Chebyshev cell type tree.
*
* See FTreeLoader documentation.
*/
template <typename _FReal = double>
class TreeLoaderFCheb : public FTreeLoader {
public:
using FReal = _FReal;
enum {ORDER = 7}; ///< Chebyshev interpolation order.
// Required type definitions.
using CellClass = FCostCell<FChebCell<FReal, ORDER>>;
using ContainerClass = FP2PParticleContainerIndexed<FReal>;
using LeafClass = FSimpleLeaf<FReal, ContainerClass >;
using OctreeClass = FOctree<FReal, CellClass, ContainerClass, LeafClass>;
/// File loader.
FFmaGenericLoader<FReal> _loader;
/// Required tree member.
OctreeClass _tree;
/// Constructs the loader and loads the tree.
TreeLoaderFCheb(FPerfTestParams& params):
_loader(params.filename),
_tree(params.treeHeight,
params.subTreeHeight,
_loader.getBoxWidth(),
_loader.getCenterOfBox()) {
this->loadTree(_loader, _tree);
}
};
#endif
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