Commit 3f292f7a authored by Quentin Khan's avatar Quentin Khan
Browse files

Rearrange PerfTest files

parent b19e9b61
#include <iomanip>
#include "Utils/FParameters.hpp"
#include "Utils/FParameterNames.hpp"
#include "PerfTest/FReal.hpp"
#include "PerfTest/FPerfTestParams.hpp"
......@@ -11,51 +10,14 @@
#define HOST_NAME_MAX 64
using FReal = double;
namespace ParName {
const FParameterNames Algo = {{"--algo"},"Algorithm to run."};
const FParameterNames Kern = {{"--kernel"},"Kernel to use."};
const FParameterNames Density = {{"--density"},"Maximum particle count per leaf in adaptive algorihtms."};
const FParameterNames Schedule = {{"--schedule"},"OpenMP scheduling policy."};
const FParameterNames ChunkSize = {{"--chunk-size"},"OpenMP chunk size for basic dynamic algorithm."};
const FParameterNames PerfFile = {{"--perf-file"},"Output file for performance measures."};
}
int main (int argc, char** argv)
{
// Parameter handling //////////////
FHelpDescribeAndExit(
argc, argv,
"Performance test program for FMM balancing techniques. ",
FParameterDefinitions::InputFile,
FParameterDefinitions::OctreeHeight,
FParameterDefinitions::OctreeSubHeight,
FParameterDefinitions::NbThreads,
ParName::Algo,
ParName::Kern,
ParName::Density,
ParName::PerfFile,
ParName::Schedule,
ParName::ChunkSize);
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, omp_get_max_threads());
params.algo = getStr(argc,argv,ParName::Algo.options,"task");
params.kernel = getStr(argc,argv,ParName::Kern.options,"lagrange");
params.adaptive_density = getValue(argc, argv, ParName::Density.options, 400);
params.omp_chunk_size = getValue(argc, argv, ParName::ChunkSize.options, 0);
params.perf_file = getStr(argc,argv,ParName::PerfFile.options,"");
}
args::cli.parse(argc,argv);
FPerfTestParams params(args::cli);
omp_set_num_threads(params.nbThreads);
// End of Parameter handling ///////
{ // Save hostname
char hostname[HOST_NAME_MAX];
......@@ -79,9 +41,9 @@ int main (int argc, char** argv)
}
std::cout << "Available kernels: ";
scalfmm::kernel_list<FReal>();
scalfmm::print_container(std::cout, scalfmm::kernel_list<FReal>()) << '\n';
std::cout << "Available algorithms: ";
scalfmm::algo_list<FReal>();
scalfmm::print_container(std::cout, scalfmm::algo_list<FReal>()) << '\n';
scalfmm::run<FReal>(params);
......
This diff is collapsed.
#ifndef _ALGO_DESCRIPTORS_HPP_
#define _ALGO_DESCRIPTORS_HPP_
#include <cstddef>
#include <memory>
#include "Utils/make_unique.hpp"
#include "../FPerfTestParams.hpp"
#include "tree_descriptors.hpp"
#include "algo_descriptors.hpp"
/**
* \brief Algorithm descriptor base model
*/
template<typename FReal, std::size_t I>
struct algo_descriptor {
/// Optional, detected via SFINAE
enum : bool {disabled = true};
/// Algorithm name for runtime lookup, must be unique
constexpr static const char* name = "";
/// Tree descriptor associated to this algorithm
using tree_desc = tree_descriptor;
/// Used after a successful algorithm lookup to build algorithm
template<typename kernel_desc> struct algo_factory {
/**
* \brief Build the algorithm
*
* \note Template parameters are there to explain the method
* signature. It does not need to be a template.
*
* \tparam algo_t Algorithm type, should already be known or deduced
* \tparam tree_t Tree type
* \tparam kernel_t Kernel type
*/
template<typename algo_t, typename tree_t, typename kernel_t>
std::unique_ptr<algo_t> build(FPerfTestParams&, tree_t&, kernel_t&);
};
};
// Sequential adaptive FMM algorithm descriptor //
#include "Adaptive/new/FAdaptiveSequential.hpp"
template<typename FReal> struct algo_descriptor<FReal, 0> {
constexpr static const char* name = "adaptive-sequential";
using tree_desc = adaptive_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_factory>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FAdaptiveSequential<tree_t, kernel_t>;
template<typename tree_t, typename kernel_t>
std::unique_ptr<algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique<algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
// Task adaptive FMM algorithm ///////////////////
#include "Adaptive/new/FAdaptiveTask.hpp"
template<typename FReal> struct algo_descriptor<FReal, 1> {
constexpr static const char* name = "adaptive-task";
using tree_desc = adaptive_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_factory>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FAdaptiveTask<tree_t, kernel_t>;
template<typename tree_t, typename kernel_t>
std::unique_ptr<algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique<algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
// Sequential uniform FMM algorithm descriptor ///
#include "Core/FFmmAlgorithm.hpp"
template<typename FReal> struct algo_descriptor<FReal, 2> {
constexpr static const char* name = "uniform-sequential";
using tree_desc = uniform_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_descriptor>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FFmmAlgorithm<
tree_t, typename kernel_descriptor::cell_data_t,
typename kernel_descriptor::container_t, kernel_t,
typename tree_desc::template leaf_tpl<kernel_descriptor> >;
template<typename tree_t, typename kernel_t>
std::unique_ptr< algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique< algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
// Threaded uniform FMM algorithm descriptor ////
#include "Core/FFmmAlgorithmThread.hpp"
template<typename FReal> struct algo_descriptor<FReal, 3> {
constexpr static const char* name = "uniform-thread";
using tree_desc = uniform_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_descriptor>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FFmmAlgorithmThread<
tree_t, typename kernel_descriptor::cell_data_t,
typename kernel_descriptor::container_t, kernel_t,
typename tree_desc::template leaf_tpl<kernel_descriptor> >;
template<typename tree_t, typename kernel_t>
std::unique_ptr< algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique< algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
// Task uniform FMM algorithm descriptor
#include "Core/FFmmAlgorithmTask.hpp"
template<typename FReal> struct algo_descriptor<FReal, 4> {
constexpr static const char* name = "uniform-task";
using tree_desc = uniform_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_descriptor>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FFmmAlgorithmTask<
tree_t, typename kernel_descriptor::cell_data_t,
typename kernel_descriptor::container_t, kernel_t,
typename tree_desc::template leaf_tpl<kernel_descriptor> >;
template<typename tree_t, typename kernel_t>
std::unique_ptr< algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique< algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
// Section task uniform FMM algorithm descriptor
#include "Core/FFmmAlgorithmSectionTask.hpp"
template<typename FReal> struct algo_descriptor<FReal, 5> {
constexpr static const char* name = "uniform-sectiontask";
using tree_desc = uniform_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_descriptor>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FFmmAlgorithmSectionTask<
tree_t, typename kernel_descriptor::cell_data_t,
typename kernel_descriptor::container_t, kernel_t,
typename tree_desc::template leaf_tpl<kernel_descriptor> >;
template<typename tree_t, typename kernel_t>
std::unique_ptr< algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique< algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
// OpenMP 4 task uniform fmm algorithm ///////////
#ifndef __clang__
#include "Core/FFmmAlgorithmOmp4.hpp"
template<typename FReal> struct algo_descriptor<FReal, 6> {
constexpr static const char* name = "uniform-task-omp4";
using tree_desc = uniform_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_descriptor>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FFmmAlgorithmOmp4<
tree_t, typename kernel_descriptor::cell_data_t,
typename kernel_descriptor::container_t, kernel_t,
typename tree_desc::template leaf_tpl<kernel_descriptor> >;
template<typename tree_t, typename kernel_t>
std::unique_ptr< algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique< algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
#endif
// StarPU adaptive fmm algorithm
#include "Adaptive/new/FAdaptiveStarPU.hpp"
template<typename FReal> struct algo_descriptor<FReal, 7> {
constexpr static const char* name = "adaptive-starpu";
using tree_desc = adaptive_tree_descriptor<FReal>;
using loader_descriptor = default_loader_descriptor<FReal>;
template<typename kernel_factory>
struct algo_factory {
template<typename tree_t, typename kernel_t>
using algo_t = FAdaptiveStarPU<tree_t, kernel_t>;
template<typename tree_t, typename kernel_t>
std::unique_ptr<algo_t<tree_t, kernel_t> >
build(const FPerfTestParams&, tree_t& tree, kernel_t& kernel) {
return std::make_unique<algo_t<tree_t, kernel_t> >(&tree, &kernel);
}
};
};
#endif /* _ALGO_DESCRIPTORS_HPP_ */
#ifndef _KERNEL_DESCRIPTORS_HPP_
#define _KERNEL_DESCRIPTORS_HPP_
#include <cstddef>
#include <memory>
#include "Utils/make_unique.hpp"
#include "../FPerfTestParams.hpp"
/**
* \brief Kernel descriptor base model
*/
template<typename FReal, std::size_t I>
struct kernel_descriptor {
/// Optional, detected via SFINAE
enum : bool {disabled = true};
/// Kernel name for runtime lookup, must be unique
constexpr static const char* name = "";
/// Cell tree type used by kernel
using cell_data_t = void;
/// Particle container type used in tree
using container_t = void;
/// Used after a successful kernel lookup to build the kernel
template<typename tree_desc> struct kernel_factory {
/**
* \brief Build the kernel
*
* \note Template parameters are there to explain the method
* signature. It does not need to be a template.
*
* \tparam kernel_t Kernel type, should already be known or deduced
* \tparam tree_t Tree type
*/
template<typename kernel_t, typename tree_t>
std::unique_ptr<kernel_t> build(FPerfTestParams&, tree_t&);
};
};
// Lagrange kernel descriptor ////////////////////
#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp"
#include "Kernels/Interpolation/FInterpMatrixKernel.hpp"
#include "Kernels/Uniform/FUnifCell.hpp"
#include "Adaptive/new/FAdaptUnifKernel.hpp"
/**
* \brief Lagrange kernel descriptor specialisation
*/
template<typename FReal>
struct kernel_descriptor<FReal, 0> {
//enum : bool {disabled = true};
/// Kernel lookup name
constexpr static const char* name = "lagrange";
/// Interpolation order
constexpr static const int ORDER = 7;
/// Kernel cell data type
using cell_data_t = FUnifCell<FReal, ORDER>;
/// Particle container data type
using container_t = FP2PParticleContainerIndexed<FReal>;
/// Direct interaction kernel type
using MatrixKernelClass = FInterpMatrixKernelR<FReal>;
template<typename tree_descriptor>
struct kernel_factory {
/// Kernel type
using kernel_t = FAdaptUnifKernel<FReal, cell_data_t, container_t , MatrixKernelClass, ORDER>;
/// Direct interation kernel instance
MatrixKernelClass MatrixKernel;
/** \brief Build method */
template<typename tree_t>
std::unique_ptr<kernel_t> build(const FPerfTestParams&, tree_t& tree) {
return std::make_unique<kernel_t>(static_cast<int>(tree.getHeight()),
tree.getBoxWidth(),
tree.getBoxCenter(),
&(this->MatrixKernel));
}
};
};
// Chebyshev kernel descriptor ///////////////////
#include "Kernels/Chebyshev/FChebCell.hpp"
#include "Adaptive/new/FAdaptChebKernel.hpp"
template<typename FReal> struct kernel_descriptor<FReal, 1> {
enum : bool {disabled = true};
/// Kernel lookup name
constexpr static const char* name = "chebyshev";
/// Kernel interpolation order
constexpr static const int ORDER = 7;
/// Kernel cell data
using cell_data_t = FChebCell<FReal, ORDER>;
/// Particle container data type
using container_t = FP2PParticleContainerIndexed<FReal>;
/// Direct interaction kernel type
using MatrixKernelClass = FInterpMatrixKernelR<FReal>;
template<typename tree_descriptor>
struct kernel_factory {
/// Kernel type
using kernel_t = FAdaptChebKernel<FReal, cell_data_t, container_t , MatrixKernelClass, ORDER>;
/// Direct interaction kernel instance
MatrixKernelClass MatrixKernel;
/** \brief Build method */
template<typename tree_t>
std::unique_ptr<kernel_t> build(const FPerfTestParams&, tree_t& tree) {
return std::make_unique<kernel_t>(static_cast<int>(tree.getHeight()),
tree.getBoxWidth(),
tree.getBoxCenter(),
&(this->MatrixKernel));
}
};
};
// Count kernel descriptor ///////////////////////
#include "../../Adaptive/FCountKernel.hpp"
template<typename FReal> struct kernel_descriptor<FReal, 2> {
/// Kernel lookup name
constexpr static const char* name = "count";
/// Kernel cell data
using cell_data_t = TestCountNodeData;
/// Particle type
using particle_t = TestCountParticle<FReal, 3>;
/// Particle container type
using container_t = FVariadicParticleContainer<particle_t>;
/// Kernel type
using kernel_t = FCountKernel<cell_data_t, container_t>;
template<typename tree_descriptor>
struct kernel_factory {
/// Kernel type
using kernel_t = kernel_descriptor<FReal, 2>::kernel_t;
/** \brief Build method */
template<typename tree_t>
std::unique_ptr<kernel_t> build(const FPerfTestParams&, tree_t& /*tree*/) {
return std::make_unique<kernel_t>();
}
};
static void info(FPerfTestParams& params, const kernel_t& kernel) {
for(auto t : kernel.call_count) {
params.json["calls"][t.first] = t.second;
}
}
};
#endif /* _KERNEL_DESCRIPTORS_HPP_ */
#ifndef _LOADER_DESCRIPTORS_HPP_
#define _LOADER_DESCRIPTORS_HPP_
#include <cstddef>
#include <memory>
#include "Utils/make_unique.hpp"
#include "../FPerfTestParams.hpp"
/// Tree loader descriptor base model
struct loader_descriptor {
/// Loads particles in a tree
struct loader {
/**
* \brief Load the tree
* \tparam tree_t Tree type
* \note Does not need to be a template
*/
template<typename tree_t>
void load(tree_t&);
};
/// Used to build the loader
struct loader_factory {
/// Build the loader
std::unique_ptr<loader> build(FPerfTestParams&);
};
};
// Basic loader descriptor ///////////////////////
#include <thread>
struct progress_bar {
std::stringstream sstr;
std::thread t;
progress_bar() {
this->sstr.precision(3);
}
template<typename Loader>
void follow(FSize& idx, Loader& l) {
this->t = std::thread(
[this,&idx,&l]() {
bool run = true;
while(run) {
sstr.str("");
sstr.clear();
sstr.precision(4);
double p = static_cast<double>(idx) * 100.
/ static_cast<double>(l.getNumberOfParticles());
sstr << "Loading particles: [";
for(double i = 0; i < 100; i += 7.5) {
sstr << (i < p ? '|' : ' ');
}
sstr << "] " << p << "% ";
std::cout << '\r' << sstr.str() << std::flush;
run = idx < l.getNumberOfParticles();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
});
}
void finish() {
this->t.join();
}
};
#include "Files/FFmaGenericLoader.hpp"
template<typename FReal>
struct default_loader_descriptor {
struct loader_t : public FFmaGenericLoader<FReal> {
progress_bar progress;
loader_t(const FPerfTestParams& params)
: FFmaGenericLoader<FReal>(params.filename){
}
template<typename tree_t>
void load(tree_t& tree) {
std::cout << "Loading particles: " << std::flush;
FSize idxPart = 0;