Commit 2f573467 authored by Quentin Khan's avatar Quentin Khan
Browse files

Add a simple checksum phase to PerfTest to check run results consistency

parent 5ada23d8
......@@ -67,7 +67,7 @@ namespace args {
std::stringstream sstr{};
tcli::str_vec flags = {"--algo"};
std::string description = "Algorithm to use. One of "
+ (scalfmm::print_container(sstr, scalfmm::algo_list<FReal>()), sstr.str());
+ (scalfmm::print_container(sstr, scalfmm::algo_list<FReal>()), sstr.str()) + '.';
using type = std::string;
};
......@@ -76,7 +76,7 @@ namespace args {
std::stringstream sstr;
tcli::str_vec flags = {"--kernel"};
std::string description = "Kernel to use. One of "
+ (scalfmm::print_container(sstr, scalfmm::kernel_list<FReal>()), sstr.str());
+ (scalfmm::print_container(sstr, scalfmm::kernel_list<FReal>()), sstr.str()) + '.';
using type = std::string;
};
......@@ -88,15 +88,20 @@ namespace args {
struct OpenMPChunkSize {
tcli::str_vec flags = {"--chunk-size"};
const char* description = "OpenMP chunk size for uniform dynamic algorithm";
const char* description = "OpenMP chunk size for uniform dynamic algorithm.";
using type = int;
type def = 0;
};
struct Checksum : tcli::flag_tag {
tcli::str_vec flags = {"--checksum", "--no-checksum"};
const char* description = "Compute some values to compare different executions.";
};
auto cli = tcli::make_parser(TreeHeight{}, SubTreeHeight{}, ThreadCount{},
File{}, PerfFile{}, Algo{}, Kernel{},
AdaptiveDensity{}, OpenMPChunkSize{}, tcli::help{});
auto cli = tcli::make_parser(
TreeHeight{}, SubTreeHeight{}, ThreadCount{},
File{}, PerfFile{}, Algo{}, Kernel{},
AdaptiveDensity{}, OpenMPChunkSize{}, Checksum{}, tcli::help{});
}
......@@ -116,6 +121,7 @@ struct FPerfTestParams {
int adaptive_density = 400; ///< Particle density for adaptive algorithms.
int omp_chunk_size = 0; ///< OpenMP chunk size for basic algorithm (FFmmAlgorithmThread)
int nbProcs = 1;
bool checksum = false;
#ifdef SCALFMM_USE_MPI
FMpi* mpiContext = nullptr;
#endif
......@@ -132,6 +138,7 @@ struct FPerfTestParams {
algo = cli.get<Algo>();
kernel = cli.get<Kernel>();
perf_file = cli.get<PerfFile>();
checksum = cli.get<Checksum>();
adaptive_density = cli.get<AdaptiveDensity>();
omp_chunk_size = cli.get<OpenMPChunkSize>();
}
......
......@@ -346,6 +346,66 @@ namespace scalfmm {
// has_info<T, Args...>::print();
}
/**
* \brief Builds a checksum when called over all the tree leaves
*
*
*/
struct checksum_generator {
FReal energy;
FSize N1, N2, N3;
enum TupleIds {index, potential, posx, posy, posz,fx,fy,fz};
std::array<std::tuple<std::size_t, FReal, FReal, FReal, FReal, FReal, FReal, FReal>, 3> particles;
checksum_generator(const checksum_generator&) = delete;
checksum_generator& operator=(const checksum_generator&) = delete;
/**
*
*/
template<class Leaf,
decltype(std::declval<Leaf*>()->getTargets()->getPositions()) = nullptr>
void operator()(Leaf* leaf) {
const FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
const FReal* const posX = leaf->getTargets()->getPositions()[0];
const FReal* const posY = leaf->getTargets()->getPositions()[1];
const FReal* const posZ = leaf->getTargets()->getPositions()[2];
const FReal* const potentials = leaf->getTargets()->getPotentials();
const FReal* const forcesX = leaf->getTargets()->getForcesX();
const FReal* const forcesY = leaf->getTargets()->getForcesY();
const FReal* const forcesZ = leaf->getTargets()->getForcesZ();
const FReal* const physicalValues = leaf->getTargets()->getPhysicalValues();
const FVector<FSize>& indexes = leaf->getTargets()->getIndexes();
for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
const FSize indexPartOrig = indexes[idxPart];
if ((indexPartOrig == N1) || (indexPartOrig == N2) || (indexPartOrig == N3) ) {
std::size_t idx = (indexPartOrig == N1 ? 0 : (indexPartOrig == N2 ? 1 : 2));
std::get<index>(particles[idx]) = indexPartOrig;
std::get<potential>(particles[idx]) = potentials[idxPart];
std::get<posx>(particles[idx]) = posX[idxPart];
std::get<posy>(particles[idx]) = posY[idxPart];
std::get<posz>(particles[idx]) = posZ[idxPart];
std::get<fx>(particles[idx]) = forcesX[idxPart];
std::get<fy>(particles[idx]) = forcesY[idxPart];
std::get<fz>(particles[idx]) = forcesZ[idxPart];
}
energy += potentials[idxPart]*physicalValues[idxPart] ;
}
}
void operator()(...) {
static bool failed = false;
if(! failed) {
std::cerr << "Checksum is not available...\n";
failed = true;
}
}
};
/**
* \brief Build everything and run algorithm
*
......@@ -396,6 +456,24 @@ namespace scalfmm {
// Gather descriptor specific data
setup_step::call_info<tree_desc>(params, *tree);
setup_step::call_info<kernel_desc>(params, *kernel);
if(params.checksum) {
checksum_generator check{0, 0, loader->getNumberOfParticles()/2, loader->getNumberOfParticles()-1};
tree->forEachLeaf(check);
params.json["checksum"]["energy"] = check.energy;
// for(int i = 0; i < 3; ++i) {
// using Ids = typename checksum_generator::TupleIds;
// params.json["checksum"]["N"+std::to_string(i)]["index"] = std::get<Ids::index>(check.particles[i]) ;
// params.json["checksum"]["N"+std::to_string(i)]["potential"] = std::get<Ids::potential>(check.particles[i]);
// params.json["checksum"]["N"+std::to_string(i)]["posx"] = std::get<Ids::posx>(check.particles[i]) ;
// params.json["checksum"]["N"+std::to_string(i)]["posy"] = std::get<Ids::posy>(check.particles[i]) ;
// params.json["checksum"]["N"+std::to_string(i)]["posz"] = std::get<Ids::posz>(check.particles[i]) ;
// params.json["checksum"]["N"+std::to_string(i)]["fx"] = std::get<Ids::fx>(check.particles[i]) ;
// params.json["checksum"]["N"+std::to_string(i)]["fy"] = std::get<Ids::fy>(check.particles[i]) ;
// params.json["checksum"]["N"+std::to_string(i)]["fz"] = std::get<Ids::fz>(check.particles[i]) ;
// }
}
}
};
......
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