#include <base/config.h>
#include <base/conditional_ostream.h>
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+#include <mpi.h>
+#endif
+
#include <string>
#include <list>
#include <map>
*/
Timer ();
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ /**
+ * Constructor that takes an MPI
+ * communicator as input. A timer
+ * constructed this way will sum up the
+ * CPU times over all processors in the
+ * MPI network when requested by the
+ * operator ().
+ *
+ * Starts the timer at 0 sec.
+ *
+ * This constructor is only available
+ * if the deal.II compiler is an MPI
+ * compiler.
+ */
+ Timer (MPI_Comm mpi_communicator);
+#endif
+
/**
* Re-start the timer at the point where
* it was stopped. This way a cumulative
* running.
*/
bool running;
+
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ /**
+ * Store whether the timer is presently
+ * running.
+ */
+ MPI_Comm mpi_communicator;
+#endif
};
* ConditionalOStream to write output to.
*/
TimerOutput (ConditionalOStream &stream,
+ const enum OutputFrequency output_frequency,
+ const enum OutputType output_type);
+
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ /**
+ * Constructor that takes an MPI
+ * communicator as input. A timer
+ * constructed this way will sum up the
+ * CPU times over all processors in the
+ * MPI network for calculating the CPU
+ * time.
+ *
+ * Meant for using std::cout as output
+ * stream.
+ */
+ TimerOutput (MPI_Comm mpi_comm,
+ std::ostream &stream,
const enum OutputFrequency output_frequency,
const enum OutputType output_type);
+ /**
+ * Constructor that takes an MPI
+ * communicator as input. A timer
+ * constructed this way will sum up the
+ * CPU times over all processors in the
+ * MPI network for calculating the CPU
+ * time.
+ *
+ * Constructor that takes a
+ * ConditionalOStream to write output to.
+ */
+ TimerOutput (MPI_Comm mpi_comm,
+ ConditionalOStream &stream,
+ const enum OutputFrequency output_frequency,
+ const enum OutputType output_type);
+#endif
+
/**
* Destructor. Calls print_summary() in
* case the option for writing the
* function.
*/
std::list<std::string> active_sections;
+
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ /**
+ * Store whether the timer is presently
+ * running.
+ */
+ MPI_Comm mpi_communicator;
+#endif
};
DEAL_II_NAMESPACE_CLOSE
#include <sys/time.h>
#include <sys/resource.h>
-#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
-#include <mpi.h>
-#endif
+#include <base/thread_management.h>
// on SunOS 4.x, getrusage is stated in the man pages and exists, but
+ // in case we use an MPI compiler, need
+ // to create a communicator just for the
+ // current process
Timer::Timer()
:
cumulative_time (0.),
cumulative_wall_time (0.)
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ , mpi_communicator (MPI_COMM_SELF)
+#endif
{
start();
}
+ // in case we use an MPI compiler, use
+ // the communicator given from input
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+Timer::Timer(MPI_Comm mpi_communicator)
+ :
+ cumulative_time (0.),
+ cumulative_wall_time (0.),
+ mpi_communicator (mpi_communicator)
+{
+ start();
+}
+#endif
+
+
+
void Timer::start ()
{
running = true;
const double dtime_children =
usage_children.ru_utime.tv_sec + 1.e-6 * usage_children.ru_utime.tv_usec;
+ // in case of MPI, need to get the time
+ // passed by summing the time over all
+ // processes in the network. works also
+ // in case we just want to have the time
+ // of a single thread, since then the
+ // communicator is MPI_COMM_SELF
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ double local_time = dtime - start_time + dtime_children
+ - start_time_children + cumulative_time;
+
+ int mpiInitialized;
+ MPI_Initialized(&mpiInitialized);
+
+ if ( mpiInitialized )
+ {
+ double global_time = 0.;
+ MPI_Allreduce (&local_time, &global_time, 1, MPI_DOUBLE, MPI_SUM,
+ mpi_communicator);
+ return global_time;
+ }
+ else
+ return local_time;
+#else
return dtime - start_time + dtime_children - start_time_children + cumulative_time;
+#endif
}
else
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ {
+ int mpiInitialized;
+ MPI_Initialized(&mpiInitialized);
+
+ if ( mpiInitialized )
+ {
+ double local_time = cumulative_time;
+ double global_time = 0.;
+ MPI_Allreduce (&local_time, &global_time, 1, MPI_DOUBLE, MPI_SUM,
+ mpi_communicator);
+ return global_time;
+ }
+ else
+ return cumulative_time;
+ }
+#else
return cumulative_time;
+#endif
}
output_frequency (output_frequency),
output_type (output_type),
out_stream (stream, true)
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ , mpi_communicator (MPI_COMM_SELF)
+#endif
{}
output_frequency (output_frequency),
output_type (output_type),
out_stream (stream)
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+ , mpi_communicator (MPI_COMM_SELF)
+#endif
+{}
+
+
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
+
+TimerOutput::TimerOutput (MPI_Comm mpi_communicator,
+ std::ostream &stream,
+ const enum OutputFrequency output_frequency,
+ const enum OutputType output_type)
+ :
+ output_frequency (output_frequency),
+ output_type (output_type),
+ out_stream (stream, true),
+ mpi_communicator (mpi_communicator)
+{}
+
+
+
+TimerOutput::TimerOutput (MPI_Comm mpi_communicator,
+ ConditionalOStream &stream,
+ const enum OutputFrequency output_frequency,
+ const enum OutputType output_type)
+ :
+ output_frequency (output_frequency),
+ output_type (output_type),
+ out_stream (stream),
+ mpi_communicator (mpi_communicator)
{}
+#endif
TimerOutput::~TimerOutput()
void
TimerOutput::enter_section (const std::string §ion_name)
{
+ Threads::Mutex mutex;
+ Threads::Mutex::ScopedLock lock (mutex);
+
Assert (section_name.empty() == false,
ExcMessage ("Section string is empty."));
void
TimerOutput::exit_section (const std::string §ion_name)
{
+ Threads::Mutex mutex;
+ Threads::Mutex::ScopedLock lock (mutex);
+
if (section_name != "")
{
Assert (sections.find (section_name) != sections.end(),
sections[actual_section_name].total_wall_time
+= sections[actual_section_name].timer.wall_time();
- // get cpu time. on MPI
- // systems, add the local
- // contributions.
- //
- // TODO: this should rather be
- // in the Timer class itself,
- // shouldn't it?
+ // get cpu time. on MPI systems, add
+ // the local contributions. we could
+ // do that also in the Timer class
+ // itself, but we didn't initialize
+ // the Timers here according to that
double cpu_time = sections[actual_section_name].timer();
{
if( mpiInitialized )
{
MPI_Allreduce (&cpu_time, &total_cpu_time, 1, MPI_DOUBLE, MPI_SUM,
- MPI_COMM_WORLD);
+ mpi_communicator);
cpu_time = total_cpu_time;
}
#endif
if( mpiInitialized )
{
- MPI_Allreduce (&my_cpu_time, &total_cpu_time, 1, MPI_DOUBLE, MPI_SUM,
- MPI_COMM_WORLD);
+ MPI_Allreduce (&my_cpu_time, &total_cpu_time, 1, MPI_DOUBLE,
+ MPI_SUM, mpi_communicator);
}
else
total_cpu_time = my_cpu_time;
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
{
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
const double * shape_value_ptr =
&fe_values.shape_values(shape_function_data[shape_function].row_index, 0);
for (unsigned int q_point=0; q_point<fe_values.n_quadrature_points; ++q_point)
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
{
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
const Tensor<1,spacedim> * shape_gradient_ptr =
&fe_values.shape_gradients[shape_function_data[shape_function].
row_index][0];
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
{
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
const Tensor<2,spacedim> * shape_hessian_ptr =
&fe_values.shape_hessians[shape_function_data[shape_function].
row_index][0];
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
{
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
const unsigned int row_index = shape_function_data[shape_function].row_index;
for (unsigned int q_point=0; q_point<fe_values.n_quadrature_points; ++q_point)
laplacians[q_point] +=
continue;
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
if (snc != -1)
{
const unsigned int comp =
continue;
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
if (snc != -1)
{
const unsigned int comp =
continue;
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
if (snc != -1)
{
const unsigned int comp =
continue;
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
if (snc != -1)
{
const unsigned int comp =
continue;
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
if (snc != -1)
{
const unsigned int comp =
continue;
const double value = dof_values(shape_function);
+ if (value == 0.)
+ continue;
+
if (snc != -1)
{
const unsigned int comp =
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
+
const double *shape_value_ptr = &this->shape_values(shape_func, 0);
for (unsigned int point=0; point<n_quadrature_points; ++point)
values[point] += value * *shape_value_ptr++;
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func]);
+ if (value == 0.)
+ continue;
+
const double *shape_value_ptr = &this->shape_values(shape_func, 0);
for (unsigned int point=0; point<n_quadrature_points; ++point)
values[point] += value * *shape_value_ptr++;
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func+mc*dofs_per_cell]);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func+mc*dofs_per_cell]);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
+
const Tensor<1,spacedim> *shape_gradient_ptr
= &this->shape_gradients[shape_func][0];
-
for (unsigned int point=0; point<n_quadrature_points; ++point)
gradients[point] += value * *shape_gradient_ptr++;
}
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func]);
+ if (value == 0.)
+ continue;
+
const Tensor<1,spacedim> *shape_gradient_ptr
= &this->shape_gradients[shape_func][0];
-
for (unsigned int point=0; point<n_quadrature_points; ++point)
gradients[point] += value * *shape_gradient_ptr++;
}
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func+mc*dofs_per_cell]);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
+
const Tensor<2,spacedim> *shape_hessians_ptr
= &this->shape_hessians[shape_func][0];
-
for (unsigned int point=0; point<n_quadrature_points; ++point)
hessians[point] += value * *shape_hessians_ptr++;
}
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func]);
+ if (value == 0.)
+ continue;
+
const Tensor<2,spacedim> *shape_hessians_ptr
= &this->shape_hessians[shape_func][0];
-
for (unsigned int point=0; point<n_quadrature_points; ++point)
hessians[point] += value * *shape_hessians_ptr++;
}
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func+mc*dofs_per_cell]);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
+
const Tensor<2,spacedim> *shape_hessian_ptr
= &this->shape_hessians[shape_func][0];
-
for (unsigned int point=0; point<n_quadrature_points; ++point)
laplacians[point] += value * trace(*shape_hessian_ptr++);
}
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func]);
+ if (value == 0.)
+ continue;
+
const Tensor<2,spacedim> *shape_hessian_ptr
= &this->shape_hessians[shape_func][0];
-
for (unsigned int point=0; point<n_quadrature_points; ++point)
laplacians[point] += value * trace(*shape_hessian_ptr++);
}
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = dof_values(shape_func);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func+mc*dofs_per_cell]);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{
for (unsigned int shape_func=0; shape_func<dofs_per_cell; ++shape_func)
{
const double value = fe_function(indices[shape_func+mc*dofs_per_cell]);
+ if (value == 0.)
+ continue;
if (fe->is_primitive(shape_func))
{