# Platform checks:
#
+INCLUDE(check_for_compiler_features)
+
INCLUDE(check_for_cxx_features)
INCLUDE(check_for_compiler_bugs)
* volatile. We do this here in a very old-fashioned C-style, but still
* convenient way.
*/
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
# define DEAL_VOLATILE volatile
#else
# define DEAL_VOLATILE
#include <cstddef>
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
# include <tbb/parallel_for.h>
# include <tbb/parallel_reduce.h>
# include <tbb/partitioner.h>
namespace internal
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
/**
* Take a range argument and call the
* given function with its begin and end.
namespace internal
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
/**
* A class that conforms to the Body
* requirements of the TBB
namespace parallel
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
namespace internal
{
const std::size_t end,
const std::size_t minimum_parallel_grain_size) const
{
-#if DEAL_II_USE_MT == 0
+#ifndef DEAL_II_USE_MT
// make sure we don't get compiler
// warnings about unused arguments
(void) minimum_parallel_grain_size;
#include <deal.II/base/config.h>
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
# include <tbb/enumerable_thread_specific.h>
#endif
ThreadLocalStorage<T> & operator = (const T &t);
private:
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
/**
* The data element we store. If we support threads, then this
* object will be of a type that provides a separate object
T &
ThreadLocalStorage<T>::get ()
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
return data.local();
#else
return data;
#include <deal.II/base/std_cxx1x/shared_ptr.h>
#include <deal.II/base/std_cxx1x/bind.h>
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
# include <deal.II/base/std_cxx1x/thread.h>
# include <deal.II/base/std_cxx1x/mutex.h>
# include <deal.II/base/std_cxx1x/condition_variable.h>
#include <utility>
-#if DEAL_II_USE_MT
-# if defined(DEAL_II_USE_MT_POSIX)
+#ifdef DEAL_II_USE_MT
+# ifdef DEAL_II_USE_MT_POSIX
# include <pthread.h>
# endif
# include <tbb/task.h>
};
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
/**
* Class implementing a
namespace internal
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
/**
* A class that represents threads. For
namespace internal
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
template <typename> struct TaskDescriptor;
#include <deal.II/base/std_cxx1x/function.h>
#include <deal.II/base/std_cxx1x/bind.h>
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
# include <deal.II/base/thread_management.h>
# include <tbb/pipeline.h>
#endif
namespace WorkStream
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
namespace internal
if (!(begin != end))
return;
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
// create the three stages of the
// pipeline
internal::IteratorRangeToItemStream<Iterator,ScratchData,CopyData>
void
SparseVanka<number>::compute_inverses ()
{
- if (!DEAL_II_USE_MT)
- compute_inverses (0, matrix->m());
- else
- {
- const unsigned int n_inverses = std::count (selected.begin(),
- selected.end(),
- true);
-
- const unsigned int n_inverses_per_thread = std::max(n_inverses / n_threads,
- 1U);
-
- // set up start and end index
- // for each of the
- // threads. note that we have
- // to work somewhat to get this
- // appropriate, since the
- // indices for which inverses
- // have to be computed may not
- // be evenly distributed in the
- // vector. as an extreme
- // example consider numbering
- // of DoFs by component, then
- // all indices for which we
- // have to do work will be
- // consecutive, with other
- // consecutive regions where we
- // do not have to do something
- std::vector<std::pair<unsigned int, unsigned int> > blocking (n_threads);
+#ifndef DEAL_II_USE_MT
+ compute_inverses (0, matrix->m());
+#else
+ const unsigned int n_inverses = std::count (selected.begin(),
+ selected.end(),
+ true);
- unsigned int c = 0;
- unsigned int thread = 0;
- blocking[0].first = 0;
+ const unsigned int n_inverses_per_thread = std::max(n_inverses / n_threads,
+ 1U);
+
+ // set up start and end index
+ // for each of the
+ // threads. note that we have
+ // to work somewhat to get this
+ // appropriate, since the
+ // indices for which inverses
+ // have to be computed may not
+ // be evenly distributed in the
+ // vector. as an extreme
+ // example consider numbering
+ // of DoFs by component, then
+ // all indices for which we
+ // have to do work will be
+ // consecutive, with other
+ // consecutive regions where we
+ // do not have to do something
+ std::vector<std::pair<unsigned int, unsigned int> > blocking (n_threads);
- for (unsigned int i=0; (i<matrix->m()) && (thread+1<n_threads); ++i)
+ unsigned int c = 0;
+ unsigned int thread = 0;
+ blocking[0].first = 0;
+
+ for (unsigned int i=0; (i<matrix->m()) && (thread+1<n_threads); ++i)
+ {
+ if (selected[i] == true)
+ ++c;
+ if (c == n_inverses_per_thread)
{
- if (selected[i] == true)
- ++c;
- if (c == n_inverses_per_thread)
- {
- blocking[thread].second = i;
- blocking[thread+1].first = i;
- ++thread;
+ blocking[thread].second = i;
+ blocking[thread+1].first = i;
+ ++thread;
- c = 0;
- };
+ c = 0;
};
- blocking[n_threads-1].second = matrix->m();
-
- typedef void (SparseVanka<number>::*FunPtr)(const unsigned int,
- const unsigned int);
- const FunPtr fun_ptr = &SparseVanka<number>::compute_inverses;
-
- // Now spawn the threads
- Threads::ThreadGroup<> threads;
- for (unsigned int i=0; i<n_threads; ++i)
- threads += Threads::new_thread (fun_ptr, *this,
- blocking[i].first,
- blocking[i].second);
- threads.join_all ();
};
+ blocking[n_threads-1].second = matrix->m();
+
+ typedef void (SparseVanka<number>::*FunPtr)(const unsigned int,
+ const unsigned int);
+ const FunPtr fun_ptr = &SparseVanka<number>::compute_inverses;
+
+ // Now spawn the threads
+ Threads::ThreadGroup<> threads;
+ for (unsigned int i=0; i<n_threads; ++i)
+ threads += Threads::new_thread (fun_ptr, *this,
+ blocking[i].first,
+ blocking[i].second);
+ threads.join_all ();
+#endif
}
else
// otherwise: blocking requested
{
- if (DEAL_II_USE_MT)
- {
- // spawn threads. since
- // some compilers have
- // trouble finding out
- // which 'encapsulate'
- // function to take of all
- // those possible ones if
- // we simply drop in the
- // address of an overloaded
- // template member
- // function, make it
- // simpler for the compiler
- // by giving it the correct
- // type right away:
- typedef void (SparseVanka<number>::*mem_fun_p)
- (Vector<number2> &,
- const Vector<number2> &,
- const std::vector<bool> * const) const;
- const mem_fun_p comp
- = &SparseVanka<number>::template apply_preconditioner<number2>;
- Threads::ThreadGroup<> threads;
- for (unsigned int block=0; block<n_blocks; ++block)
- threads += Threads::new_thread (comp,
- *static_cast<const SparseVanka<number>*>(this),
- dst, src,&dof_masks[block]);
- threads.join_all ();
- }
- else
+#ifdef DEAL_II_USE_MT
+ // spawn threads. since
+ // some compilers have
+ // trouble finding out
+ // which 'encapsulate'
+ // function to take of all
+ // those possible ones if
+ // we simply drop in the
+ // address of an overloaded
+ // template member
+ // function, make it
+ // simpler for the compiler
+ // by giving it the correct
+ // type right away:
+ typedef void (SparseVanka<number>::*mem_fun_p)
+ (Vector<number2> &,
+ const Vector<number2> &,
+ const std::vector<bool> * const) const;
+ const mem_fun_p comp
+ = &SparseVanka<number>::template apply_preconditioner<number2>;
+ Threads::ThreadGroup<> threads;
+ for (unsigned int block=0; block<n_blocks; ++block)
+ threads += Threads::new_thread (comp,
+ *static_cast<const SparseVanka<number>*>(this),
+ dst, src,&dof_masks[block]);
+ threads.join_all ();
+#else
for (unsigned int block=0; block<n_blocks; ++block)
this->apply_preconditioner (dst, src,
&dof_masks[block]);
+#endif
}
}
template <typename number>
void SwappableVector<number>::alert ()
{
+#ifndef DEAL_II_USE_MT
// note: this function does nothing
// in non-MT mode
- if (!DEAL_II_USE_MT)
return;
+#else
// synchronise with possible other
// invocations of this function and
Threads::new_thread (&SwappableVector<number>::reload_vector, *this, true);
// note that reload_vector also
// releases the lock
+#endif
}
this->block_read (tmp_in);
tmp_in.close ();
+#ifdef DEAL_II_USE_MT
// release the lock that was
// acquired by the calling
// functions
- if (DEAL_II_USE_MT)
- {
- // set the flag if so required
- if (set_flag)
- data_is_preloaded = true;
- lock.release ();
- };
+
+ // set the flag if so required
+ if (set_flag)
+ data_is_preloaded = true;
+ lock.release ();
+#endif
}
// global communication, so we can
// disable the check here only if no
// processor has any such data
-#if DEAL_II_COMPILER_SUPPORTS_MPI
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
unsigned int general_size_glob = 0, general_size_loc = jacobians.size();
MPI_Allreduce (&general_size_loc, &general_size_glob, 1, MPI_UNSIGNED,
MPI_MAX, size_info.communicator);
MemoryConsumption::memory_consumption (jacobians_grad_upper));
}
-#if DEAL_II_COMPILER_SUPPORTS_MPI
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
unsigned int quad_size_glob = 0, quad_size_loc = quadrature_points.size();
MPI_Allreduce (&quad_size_loc, &quad_size_glob, 1, MPI_UNSIGNED,
MPI_MAX, size_info.communicator);
#include <deal.II/matrix_free/dof_info.h>
#include <deal.II/matrix_free/mapping_info.h>
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
#include <tbb/task.h>
#include <tbb/task_scheduler_init.h>
#include <tbb/parallel_for.h>
}
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
// This defines the TBB data structures that
// are needed to schedule the
VectorStruct &dst;
};
-#endif // #if DEAL_II_USE_MT
+#endif // DEAL_II_USE_MT
} // end of namespace internal
OutVector &dst,
const InVector &src) const
{
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
// Use multithreading if so requested and if
// there is enough work to do in parallel (the
void assert_communicator_equality (const dealii::Triangulation<dim>&tria,
const MPI_Comm &comm_mf)
{
-#if DEAL_II_COMPILER_SUPPORTS_MPI
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
const parallel::distributed::Triangulation<dim>* dist_tria =
dynamic_cast<const parallel::distributed::Triangulation<dim>*>(&tria);
if (dist_tria != 0)
// initialize the basic multithreading
// information that needs to be passed to the
// DoFInfo structure
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
if (additional_data.tasks_parallel_scheme != AdditionalData::none)
{
task_info.use_multithreading = true;
// initialize the basic multithreading
// information that needs to be passed to the
// DoFInfo structure
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
if (additional_data.tasks_parallel_scheme != AdditionalData::none)
{
task_info.use_multithreading = true;
// try to balance the number of cells before
// and after the boundary part on each
// processor. probably not worth it!
-#if DEAL_II_COMPILER_SUPPORTS_MPI
+#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
MPI_Allreduce (&n_boundary_cells, &n_max_boundary_cells, 1, MPI_UNSIGNED,
MPI_MAX, size_info.communicator);
#endif
}
}
-#if DEAL_II_USE_P4EST
+#ifdef DEAL_II_USE_P4EST
// if this was a distributed
// DoFHandler, we need to do the
// reduction over the entire domain
#include <deal.II/base/config.h>
-#if DEAL_II_USE_MT && !defined(DEAL_II_CAN_USE_CXX1X) && !defined(DEAL_II_USE_EXTERNAL_BOOST)
+#if defined(DEAL_II_USE_MT) && !defined(DEAL_II_CAN_USE_CXX1X) && !defined(DEAL_II_USE_EXTERNAL_BOOST)
// if the C++ compiler doesn't completely support the C++1x standard (and
// consequently we can't use std::thread, std::mutex, etc), then include all
// build BOOST itself only to get at this small part of it. it also ensures
// that we use the correct compiler and flags
-# define BOOST_THREAD_BUILD_LIB 1
-# define DBOOST_ALL_NO_LIB 1
+# define BOOST_THREAD_BUILD_LIB
+# define DBOOST_ALL_NO_LIB
# ifdef DEAL_II_USE_MT_POSIX
# define BOOST_THREAD_POSIX
DEAL_II_NAMESPACE_OPEN
-#if DEAL_II_USE_MT
+#ifdef DEAL_II_USE_MT
/* Detecting how many processors a given machine has is something that
varies greatly between operating systems. For a few operating
Threads::ThreadMutex::ScopedLock lock (subscription_lock);
++counter;
-#if DEAL_USE_MT == 0
+#ifndef DEAL_II_USE_MT
const char* const name = (id != 0) ? id : unknown_subscriber;
map_iterator it = counter_map.find(name);
Threads::ThreadMutex::ScopedLock lock (subscription_lock);
--counter;
-#if DEAL_USE_MT == 0
+#ifndef DEAL_II_USE_MT
map_iterator it = counter_map.find(name);
Assert (it != counter_map.end(), ExcNoSubscriber(object_info->name(), name));
Assert (it->second > 0, ExcNoSubscriber(object_info->name(), name));
void Subscriptor::list_subscribers () const
{
-#if DEAL_USE_MT == 0
+#ifndef DEAL_II_USE_MT
for (map_iterator it = counter_map.begin();
it != counter_map.end(); ++it)
deallog << it->second << '/'
void TimeDependent::end_sweep (const unsigned int n_threads)
{
- if (DEAL_II_USE_MT && (n_threads > 1))
+#ifdef DEAL_II_USE_MT
+ if (n_threads > 1)
{
const unsigned int stride = timesteps.size() / n_threads;
Threads::ThreadGroup<> threads;
threads.join_all();
}
else
+ {
// now do the work
end_sweep (0, timesteps.size());
+ }
+#else
+ end_sweep (0, timesteps.size());
+#endif
}