Commit 5ba70ba8 authored by incardon's avatar incardon

Adding performance test

parent 2a7c5471
LINKLIBS = $(OPENMP_LDFLAGS) $(LIBHILBERT_LIB) $(METIS_LIB) $(PTHREAD_LIBS) $(OPT_LIBS) $(BOOST_LDFLAGS) $(BOOST_IOSTREAMS_LIB) $(CUDA_LIBS) $(PETSC_LIB) $(HDF5_LDFLAGS) $(HDF5_LIBS) $(PARMETIS_LIB) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(BOOST_CHRONO_LIB) $(BOOST_TIMER_LIB) $(BOOST_SYSTEM_LIB) $(LIBIFCORE)
noinst_PROGRAMS = pdata
pdata_SOURCES = main.cpp Grid/grid_dist_id_unit_test.cpp lib/pdata.cpp test_multiple_o.cpp ../openfpm_devices/src/memory/HeapMemory.cpp ../openfpm_devices/src/memory/PtrMemory.cpp ../openfpm_vcluster/src/VCluster/VCluster.cpp ../openfpm_devices/src/Memleak_check.cpp
pdata_SOURCES = main.cpp pdata_performance.cpp Grid/grid_dist_id_unit_test.cpp lib/pdata.cpp test_multiple_o.cpp ../openfpm_devices/src/memory/HeapMemory.cpp ../openfpm_devices/src/memory/PtrMemory.cpp ../openfpm_vcluster/src/VCluster/VCluster.cpp ../openfpm_devices/src/Memleak_check.cpp
pdata_CXXFLAGS = $(OPENMP_CFLAGS) $(AM_CXXFLAGS) $(LIBHILBERT_INCLUDE) $(PETSC_INCLUDE) $(HDF5_CPPFLAGS) $(CUDA_CFLAGS) $(INCLUDES_PATH) $(PARMETIS_INCLUDE) $(METIS_INCLUDE) $(BOOST_CPPFLAGS) $(H5PART_INCLUDE) -DPARALLEL_IO -Wno-unused-local-typedefs
pdata_CFLAGS = $(CUDA_CFLAGS)
pdata_LDADD = $(LINKLIBS) -lparmetis -lmetis
......
......@@ -13,54 +13,86 @@
#include "Plot/GoogleChart.hpp"
#include "vector_dist_performance_util.hpp"
BOOST_AUTO_TEST_SUITE( vector_dist_celllist_hilb_performance_test )
BOOST_AUTO_TEST_SUITE( celllist_comp_reorder_performance_test )
///////////////////// INPUT DATA //////////////////////
// Cut-off radiuses. Can be put different number of values
openfpm::vector<float> r_cutoff {0.01, 0.02, 0.03};
openfpm::vector<float> r_cutoff {0.004, 0.007, 0.01};
// The starting amount of particles (remember that this number is multiplied by number of processors you use for testing)
size_t k_start = 100000;
// The lower threshold for number of particles
size_t k_min = 15000;
// Ghost part of distributed vector
double ghost_part = 0.03;
///////////////////////////////////////////////////////
// Numbers of particles vector
openfpm::vector<size_t> n_particles;
// Vectors to store the data for 2D
openfpm::vector<openfpm::vector<double>> time_rand;
openfpm::vector<openfpm::vector<double>> time_hilb;
openfpm::vector<openfpm::vector<double>> time_total_rand;
openfpm::vector<openfpm::vector<double>> time_total_hilb;
openfpm::vector<openfpm::vector<double>> time_rand_mean;
openfpm::vector<openfpm::vector<double>> time_hilb_mean;
openfpm::vector<openfpm::vector<double>> time_rand_dev;
openfpm::vector<openfpm::vector<double>> time_hilb_dev;
openfpm::vector<openfpm::vector<double>> time_create_rand_mean;
openfpm::vector<openfpm::vector<double>> time_create_hilb_mean;
openfpm::vector<openfpm::vector<double>> time_create_rand_dev;
openfpm::vector<openfpm::vector<double>> time_create_hilb_dev;
// Vectors to store the data for 3D
openfpm::vector<openfpm::vector<double>> time_rand_2;
openfpm::vector<openfpm::vector<double>> time_hilb_2;
openfpm::vector<openfpm::vector<double>> time_total_rand_2;
openfpm::vector<openfpm::vector<double>> time_total_hilb_2;
openfpm::vector<openfpm::vector<double>> time_rand_2_mean;
openfpm::vector<openfpm::vector<double>> time_hilb_2_mean;
openfpm::vector<openfpm::vector<double>> time_rand_2_dev;
openfpm::vector<openfpm::vector<double>> time_hilb_2_dev;
openfpm::vector<openfpm::vector<double>> time_create_rand_2_mean;
openfpm::vector<openfpm::vector<double>> time_create_hilb_2_mean;
openfpm::vector<openfpm::vector<double>> time_create_rand_2_dev;
openfpm::vector<openfpm::vector<double>> time_create_hilb_2_dev;
BOOST_AUTO_TEST_CASE( vector_dist_celllist_random_test )
{
//Benchmark test for 2D and 3D
vd_celllist_random_benchmark<2>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_rand,time_total_rand);
vd_celllist_random_benchmark<3>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_rand_2,time_total_rand_2);
cell_list_comp_reorder_random_benchmark<3>(k_start,k_min,r_cutoff,n_particles,time_rand_mean,time_create_rand_mean,time_rand_dev,time_create_rand_dev);
cell_list_comp_reorder_random_benchmark<2>(k_start,k_min,r_cutoff,n_particles,time_rand_2_mean,time_create_rand_2_mean,time_rand_2_dev,time_create_rand_2_dev);
}
BOOST_AUTO_TEST_CASE( vector_dist_celllist_hilbert_test )
{
//Benchmark test for 2D and 3D
vd_celllist_hilbert_benchmark<2>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_hilb,time_total_hilb);
vd_celllist_hilbert_benchmark<3>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_hilb_2,time_total_hilb_2);
cell_list_comp_reorder_hilbert_benchmark<3>(k_start,k_min,r_cutoff,n_particles,time_hilb_mean,time_hilb_dev,time_create_hilb_mean,time_create_hilb_dev);
cell_list_comp_reorder_hilbert_benchmark<2>(k_start,k_min,r_cutoff,n_particles,time_hilb_2_mean,time_hilb_2_dev,time_create_hilb_2_mean,time_create_hilb_2_dev);
}
BOOST_AUTO_TEST_CASE(vector_dist_cl_performance_write_report)
{
GoogleChart cg;
//Write report for 2D and 3D
vd_celllist_performance_write_report<2>(r_cutoff,n_particles,time_hilb,time_rand,time_total_hilb,time_total_rand);
vd_celllist_performance_write_report<3>(r_cutoff,n_particles,time_hilb_2,time_rand_2,time_total_hilb_2,time_total_rand_2);
cell_list_comp_reorder_report<3>(cg,
r_cutoff,
n_particles,
time_hilb_mean,
time_rand_mean,
time_hilb_dev,
time_rand_dev,
time_create_hilb_mean,
time_create_rand_mean,
time_create_hilb_dev,
time_create_rand_dev);
cell_list_comp_reorder_report<2>(cg,
r_cutoff,
n_particles,
time_hilb_2_mean,
time_rand_2_mean,
time_create_hilb_2_mean,
time_create_rand_2_mean,
time_rand_2_dev,
time_hilb_2_dev,
time_create_hilb_2_dev,
time_create_rand_2_dev);
if (create_vcluster().getProcessUnitID() == 0)
cg.write(std::string(test_dir) + "/openfpm_pdata/Celllist_comp_ord.html");
}
BOOST_AUTO_TEST_SUITE_END()
......
/*
* vector_dist_cl_performance_tests.hpp
*
*
* Created on: Mar 22, 2016
* Author: Yaroslav Zaluzhnyi
*/
#ifndef SRC_VECTOR_VECTOR_DIST_CL_PERFORMANCE_TESTS_HPP_
#define SRC_VECTOR_VECTOR_DIST_CL_PERFORMANCE_TESTS_HPP_
#include "Vector/vector_dist.hpp"
#include "data_type/aggregate.hpp"
#include "Plot/GoogleChart.hpp"
#include <functional>
BOOST_AUTO_TEST_SUITE( celllist_part_reorder_performance_test )
///////////////////// INPUT DATA //////////////////////
// Cut-off radiuses. Can be put different number of values
openfpm::vector<float> r_cutoff {0.004, 0.007, 0.01};
// Orders of a curve. Can be put different number of values
openfpm::vector<size_t> orders = {1,2,3};
// Number of steps of moving the particles
size_t n_moving = 8;
// Moving distance (step size)
double dist = 0.03;
// The starting amount of particles (remember that this number is multiplied by number of processors you use for testing)
size_t k_start = 100000;
// The minimal amount of particles
size_t k_min = 15000;
///////////////////////////////////////////////////////
// Numbers of particles vector
openfpm::vector<size_t> n_particles;
// Vectors to store the data for 2D
openfpm::vector<openfpm::vector<double>> time_rand_mean;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb_mean;
openfpm::vector<openfpm::vector<double>> time_rand_dev;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb_dev;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_reorder_mean;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_reorder_dev;
// Vectors to store the data for 3D
openfpm::vector<openfpm::vector<double>> time_rand_2_mean;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb_2_mean;
openfpm::vector<openfpm::vector<double>> time_rand_2_dev;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb_2_dev;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_reorder_2_mean;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_reorder_2_dev;
BOOST_AUTO_TEST_CASE( vector_dist_cl_random_test )
{
//Benchmark test for 2D and 3D
cell_list_part_reorder_random_benchmark<3>(k_start,k_min,r_cutoff,n_particles,time_rand_mean,time_rand_dev);
cell_list_part_reorder_random_benchmark<2>(k_start,k_min,r_cutoff,n_particles,time_rand_2_mean,time_rand_2_dev);
}
BOOST_AUTO_TEST_CASE( vector_dist_cl_hilbert_test )
{
//Benchmark test for 2D and 3D
cell_list_part_reorder_hilbert_benchmark<3>(k_start,
k_min,
n_moving,
dist,
r_cutoff,
n_particles,
orders,
time_hilb_mean,
time_reorder_mean,
time_hilb_dev,
time_reorder_dev);
cell_list_part_reorder_hilbert_benchmark<2>(k_start,
k_min,
n_moving,
dist,
r_cutoff,
n_particles,
orders,
time_hilb_2_mean,
time_reorder_2_mean,
time_hilb_2_dev,
time_reorder_2_dev);
}
BOOST_AUTO_TEST_CASE(vector_dist_cl_performance_write_report)
{
GoogleChart cg;
/* n_particles.save("debug1");
time_rand_mean.save("debug2");
time_hilb_mean.save("debug3");
time_rand_dev.save("debug4");
time_hilb_dev.save("debug5");
time_reorder_mean.save("debug6");
time_reorder_dev.save("debug7");
time_hilb_moved.save("debug8");
time_rand_2_mean.save("debug9");
time_hilb_2_mean.save("debug10");
time_rand_2_dev.save("debug11");
time_hilb_2_dev.save("debug12");
time_reorder_2_mean.save("debug13");
time_reorder_2_dev.save("debug14");
time_hilb_moved_2.save("debug15");*/
/* n_particles.load("debug1");
time_rand_mean.load("debug2");
time_hilb_mean.load("debug3");
time_rand_dev.load("debug4");
time_hilb_dev.load("debug5");
time_reorder_mean.load("debug6");
time_reorder_dev.load("debug7");
time_hilb_moved.load("debug8");
time_rand_2_mean.load("debug9");
time_hilb_2_mean.load("debug10");
time_rand_2_dev.load("debug11");
time_hilb_2_dev.load("debug12");
time_reorder_2_mean.load("debug13");
time_reorder_2_dev.load("debug14");
time_hilb_moved_2.load("debug15");*/
//Write report for 2D and 3D
cell_list_part_reorder_report<3>(cg,
n_moving,
r_cutoff,
n_particles,
orders,
time_hilb_mean,
time_rand_mean,
time_reorder_mean,
time_hilb_dev,
time_rand_dev,
time_reorder_dev);
cell_list_part_reorder_report<2>(cg,
n_moving,
r_cutoff,
n_particles,
orders,
time_hilb_2_mean,
time_rand_2_mean,
time_reorder_2_mean,
time_hilb_2_dev,
time_rand_2_dev,
time_reorder_2_dev);
if (create_vcluster().getProcessUnitID() == 0)
cg.write(std::string(test_dir) + "/openfpm_pdata/Celllist_part_ord.html");
}
BOOST_AUTO_TEST_SUITE_END()
#endif /* SRC_VECTOR_VECTOR_DIST_CL_PERFORMANCE_TESTS_HPP_ */
/*
* vector_dist_cl_performance_tests.hpp
*
*
* Created on: Mar 22, 2016
* Author: Yaroslav Zaluzhnyi
*/
#ifndef SRC_VECTOR_VECTOR_DIST_CL_PERFORMANCE_TESTS_HPP_
#define SRC_VECTOR_VECTOR_DIST_CL_PERFORMANCE_TESTS_HPP_
#include "Vector/vector_dist.hpp"
#include "data_type/aggregate.hpp"
#include "Vector/vector_dist_unit_test.hpp"
#include "Plot/GoogleChart.hpp"
#include <functional>
BOOST_AUTO_TEST_SUITE( vector_dist_cl_perf_test )
///////////////////// INPUT DATA //////////////////////
// Cut-off radiuses. Can be put different number of values
openfpm::vector<float> r_cutoff {0.007,0.02};
// Orders of a curve. Can be put different number of values
openfpm::vector<size_t> orders = {1,2,3,5,7};
// Number of steps of moving the particles
size_t n_moving = 8;
// Moving distance (step size)
double dist = 0.1;
// The starting amount of particles (remember that this number is multiplied by number of processors you use for testing)
size_t k_start = 100000;
// The minimal amount of particles
size_t k_min = 15000;
// Ghost part of distributed vector
double ghost_part = 0.01;
///////////////////////////////////////////////////////
// Numbers of particles vector
openfpm::vector<size_t> n_particles;
// Vectors to store the data for 2D
openfpm::vector<openfpm::vector<double>> time_rand;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb;
openfpm::vector<openfpm::vector<double>> time_total_rand;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_total_hilb;
openfpm::vector<openfpm::vector<openfpm::vector<openfpm::vector<double>>>> time_hilb_moved;
// Vectors to store the data for 3D
openfpm::vector<openfpm::vector<double>> time_rand_2;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb_2;
openfpm::vector<openfpm::vector<double>> time_total_rand_2;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_total_hilb_2;
openfpm::vector<openfpm::vector<openfpm::vector<openfpm::vector<double>>>> time_hilb_moved_2;
BOOST_AUTO_TEST_CASE( vector_dist_cl_random_test )
{
//Benchmark test for 2D and 3D
vd_cl_random_benchmark<2>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_rand,time_total_rand);
vd_cl_random_benchmark<3>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_rand_2,time_total_rand_2);
}
BOOST_AUTO_TEST_CASE( vector_dist_cl_hilbert_test )
{
//Benchmark test for 2D and 3D
vd_cl_hilbert_benchmark<2>(k_start,k_min,ghost_part,n_moving,dist,r_cutoff,n_particles,orders,time_hilb,time_total_hilb,time_hilb_moved);
vd_cl_hilbert_benchmark<3>(k_start,k_min,ghost_part,n_moving,dist,r_cutoff,n_particles,orders,time_hilb_2,time_total_hilb_2,time_hilb_moved_2);
}
BOOST_AUTO_TEST_CASE(vector_dist_cl_performance_write_report)
{
//Write report for 2D and 3D
vd_cl_performance_write_report<2>(n_moving,r_cutoff,n_particles,orders,time_hilb,time_rand,time_total_hilb,time_total_rand,time_hilb_moved);
vd_cl_performance_write_report<3>(n_moving,r_cutoff,n_particles,orders,time_hilb_2,time_rand_2,time_total_hilb_2,time_total_rand_2,time_hilb_moved_2);
}
BOOST_AUTO_TEST_SUITE_END()
#endif /* SRC_VECTOR_VECTOR_DIST_CL_PERFORMANCE_TESTS_HPP_ */
......@@ -8,62 +8,53 @@
#ifndef SRC_VECTOR_VECTOR_DIST_VERLET_PERFORMANCE_TESTS_HPP_
#define SRC_VECTOR_VECTOR_DIST_VERLET_PERFORMANCE_TESTS_HPP_
#include "Vector/vector_dist.hpp"
#include "data_type/aggregate.hpp"
#include "Plot/GoogleChart.hpp"
#include "vector_dist_performance_util.hpp"
BOOST_AUTO_TEST_SUITE( vector_dist_verlet_perf_test )
BOOST_AUTO_TEST_SUITE( verletlist_part_reorder_performance_test )
///////////////////// INPUT DATA //////////////////////
// Cut-off radiuses. Can be put different number of values
openfpm::vector<float> r_cutoff {0.007,0.02};
openfpm::vector<float> r_cutoff {0.004, 0.007, 0.01};
// Orders of a curve. Can be put different number of values
openfpm::vector<size_t> orders = {1,2,3,5,7};
// The starting amount of particles (remember that this number is multiplied by number of processors you use for testing)
size_t k_start = 100000;
// The minimal amount of particles
size_t k_min = 15000;
// Ghost part of distributed vector
double ghost_part = 0.01;
///////////////////////////////////////////////////////
// Numbers of particles vector
openfpm::vector<size_t> n_particles;
// Vectors to store the data for 2D
openfpm::vector<openfpm::vector<double>> time_rand;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb;
openfpm::vector<openfpm::vector<double>> time_total_rand;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_total_hilb;
openfpm::vector<openfpm::vector<double>> time_force_mean;
openfpm::vector<openfpm::vector<double>> time_force_dev;
openfpm::vector<openfpm::vector<double>> time_create_mean;
openfpm::vector<openfpm::vector<double>> time_create_dev;
// Vectors to store the data for 3D
openfpm::vector<openfpm::vector<double>> time_rand_2;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_hilb_2;
openfpm::vector<openfpm::vector<double>> time_total_rand_2;
openfpm::vector<openfpm::vector<openfpm::vector<double>>> time_total_hilb_2;
openfpm::vector<openfpm::vector<double>> time_force_mean_2;
openfpm::vector<openfpm::vector<double>> time_force_dev_2;
openfpm::vector<openfpm::vector<double>> time_create_mean_2;
openfpm::vector<openfpm::vector<double>> time_create_dev_2;
BOOST_AUTO_TEST_CASE( vector_dist_verlet_random_test )
BOOST_AUTO_TEST_CASE( vector_dist_verlet_test )
{
//Benchmark test for 2D and 3D
vd_verlet_random_benchmark<2>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_rand,time_total_rand);
vd_verlet_random_benchmark<3>(k_start,k_min,ghost_part,r_cutoff,n_particles,time_rand_2,time_total_rand_2);
}
BOOST_AUTO_TEST_CASE( vector_dist_verlet_hilbert_test )
{
//Benchmark test for 2D and 3D
vd_verlet_hilbert_benchmark<2>(k_start,k_min,ghost_part,r_cutoff,n_particles,orders,time_hilb,time_total_hilb);
vd_verlet_hilbert_benchmark<3>(k_start,k_min,ghost_part,r_cutoff,n_particles,orders,time_hilb_2,time_total_hilb_2);
vd_verlet_random_benchmark<3>(k_start,k_min,r_cutoff,n_particles,time_force_mean,time_create_mean,time_force_dev,time_create_dev);
vd_verlet_random_benchmark<2>(k_start,k_min,r_cutoff,n_particles,time_force_mean_2,time_create_mean_2,time_force_dev_2,time_create_dev_2);
}
BOOST_AUTO_TEST_CASE(vector_dist_verlet_performance_write_report)
{
GoogleChart cg;
//Write report for 2D and 3D
vd_verlet_performance_write_report<2>(r_cutoff,n_particles,orders,time_hilb,time_rand,time_total_hilb,time_total_rand);
vd_verlet_performance_write_report<3>(r_cutoff,n_particles,orders,time_hilb_2,time_rand_2,time_total_hilb_2,time_total_rand_2);
vd_verlet_performance_write_report<3>(cg,r_cutoff,n_particles,time_force_mean,time_force_dev,time_create_mean,time_create_dev);
vd_verlet_performance_write_report<2>(cg,r_cutoff,n_particles,time_force_mean_2,time_force_dev_2,time_create_mean_2,time_create_dev_2);
if (create_vcluster().getProcessUnitID() == 0)
cg.write(std::string(test_dir) + "/openfpm_pdata/Verletlist_comp.html");
}
BOOST_AUTO_TEST_SUITE_END()
......
......@@ -11,7 +11,7 @@
#include <random>
#include "Vector/vector_dist.hpp"
#include "data_type/aggregate.hpp"
#include "Vector/performance/vector_dist_performance_util.hpp"
#include "Vector/performance/vector_dist_performance_common.hpp"
/*! \brief Count the total number of particles
*
......
......@@ -40,9 +40,6 @@ int main(int argc, char* argv[])
#include "Decomposition/Distribution/metis_util_unit_test.hpp"
#include "dec_optimizer_unit_test.hpp"
#include "Vector/vector_dist_unit_test.hpp"
#ifdef PERFORMANCE_TEST
#include "pdata_performance.hpp"
#endif
#include "Decomposition/Distribution/Distribution_unit_tests.hpp"
//#include "DLB/DLB_unit_test.hpp"
#include "Graph/dist_map_graph_unit_test.hpp"
......
/*
* performance.hpp
*
* Created on: Mar 9, 2016
* Author: yaroslav
*/
#ifndef SRC_PDATA_PERFORMANCE_CPP_
#define SRC_PDATA_PERFORMANCE_CPP_
#include <iostream>
#include <mpi.h>
#include "config.h"
#include "Vector/vector_dist.hpp"
#include "data_type/aggregate.hpp"
#include "Plot/GoogleChart.hpp"
#include "Point_test.hpp"
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
extern const char * test_dir;
#ifdef PERFORMANCE_TEST
BOOST_AUTO_TEST_SUITE( performance )
#include "Vector/performance/vector_dist_performance_util.hpp"
#include "Vector/performance/verlet_performance_tests.hpp"
#include "Vector/performance/cell_list_part_reorder.hpp"
#include "Vector/performance/cell_list_comp_reorder.hpp"
BOOST_AUTO_TEST_SUITE_END()
#endif
#endif /* SRC_PDATA_PERFORMANCE_CPP_ */
/*
* performance.hpp
*
* Created on: Mar 9, 2016
* Author: yaroslav
*/
#ifndef SRC_PDATA_PERFORMANCE_HPP_
#define SRC_PDATA_PERFORMANCE_HPP_
BOOST_AUTO_TEST_SUITE( performance )
#include "Vector/performance/vector_dist_verlet_performance_tests.hpp"
#include "Vector/performance/vector_dist_cl_performance_tests.hpp"
#include "Vector/performance/vector_dist_cl_hilb_performance_tests.hpp"
BOOST_AUTO_TEST_SUITE_END()
#endif /* SRC_PDATA_PERFORMANCE_HPP_ */
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