aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2012-06-14 14:24:15 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2012-06-14 14:24:15 +0200
commitb9f25ee656b5b5c4aec6975f3296a1cb10ceea87 (patch)
tree2ad2811a291cc80b72802a2001055d0973d5702b
parenta3e700db72300d739605a8b734831b8b644f6272 (diff)
bug #466: better fix for the race condition: this new patch add an initParallel()
function which must be called at the initialization time of any multi-threaded application calling Eigen from multiple threads.
-rw-r--r--Eigen/Core2
-rw-r--r--Eigen/src/Core/products/GeneralBlockPanelKernel.h5
-rw-r--r--Eigen/src/Core/products/Parallelizer.h18
-rw-r--r--doc/TopicMultithreading.dox46
4 files changed, 65 insertions, 6 deletions
diff --git a/Eigen/Core b/Eigen/Core
index a8a15c053..0cf101636 100644
--- a/Eigen/Core
+++ b/Eigen/Core
@@ -329,9 +329,9 @@ using std::ptrdiff_t;
#include "src/Core/GeneralProduct.h"
#include "src/Core/TriangularMatrix.h"
#include "src/Core/SelfAdjointView.h"
+#include "src/Core/products/GeneralBlockPanelKernel.h"
#include "src/Core/products/Parallelizer.h"
#include "src/Core/products/CoeffBasedProduct.h"
-#include "src/Core/products/GeneralBlockPanelKernel.h"
#include "src/Core/products/GeneralMatrixVector.h"
#include "src/Core/products/GeneralMatrixMatrix.h"
#include "src/Core/SolveTriangular.h"
diff --git a/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/Eigen/src/Core/products/GeneralBlockPanelKernel.h
index 57285468b..d631fa28e 100644
--- a/Eigen/src/Core/products/GeneralBlockPanelKernel.h
+++ b/Eigen/src/Core/products/GeneralBlockPanelKernel.h
@@ -26,7 +26,7 @@
#define EIGEN_GENERAL_BLOCK_PANEL_H
namespace Eigen {
-
+
namespace internal {
template<typename _LhsScalar, typename _RhsScalar, bool _ConjLhs=false, bool _ConjRhs=false>
@@ -44,8 +44,7 @@ inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1=0, std::ptrdi
{
static std::ptrdiff_t m_l1CacheSize = 0;
static std::ptrdiff_t m_l2CacheSize = 0;
- #pragma omp threadprivate(m_l1CacheSize,m_l2CacheSize)
- if(m_l1CacheSize==0)
+ if(m_l2CacheSize==0)
{
m_l1CacheSize = manage_caching_sizes_helper(queryL1CacheSize(),8 * 1024);
m_l2CacheSize = manage_caching_sizes_helper(queryTopLevelCacheSize(),1*1024*1024);
diff --git a/Eigen/src/Core/products/Parallelizer.h b/Eigen/src/Core/products/Parallelizer.h
index bb1d70dda..725216162 100644
--- a/Eigen/src/Core/products/Parallelizer.h
+++ b/Eigen/src/Core/products/Parallelizer.h
@@ -57,12 +57,23 @@ inline void manage_multi_threading(Action action, int* v)
}
}
+}
+
+/** Must be call first when calling Eigen from multiple threads */
+inline void initParallel()
+{
+ int nbt;
+ internal::manage_multi_threading(GetAction, &nbt);
+ std::ptrdiff_t l1, l2;
+ internal::manage_caching_sizes(GetAction, &l1, &l2);
+}
+
/** \returns the max number of threads reserved for Eigen
* \sa setNbThreads */
inline int nbThreads()
{
int ret;
- manage_multi_threading(GetAction, &ret);
+ internal::manage_multi_threading(GetAction, &ret);
return ret;
}
@@ -70,9 +81,11 @@ inline int nbThreads()
* \sa nbThreads */
inline void setNbThreads(int v)
{
- manage_multi_threading(SetAction, &v);
+ internal::manage_multi_threading(SetAction, &v);
}
+namespace internal {
+
template<typename Index> struct GemmParallelInfo
{
GemmParallelInfo() : sync(-1), users(0), rhs_start(0), rhs_length(0) {}
@@ -121,6 +134,7 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
if(threads==1)
return func(0,rows, 0,cols);
+ Eigen::initParallel();
func.initParallelSession();
if(transpose)
diff --git a/doc/TopicMultithreading.dox b/doc/TopicMultithreading.dox
new file mode 100644
index 000000000..f7d082668
--- /dev/null
+++ b/doc/TopicMultithreading.dox
@@ -0,0 +1,46 @@
+namespace Eigen {
+
+/** \page TopicMultiThreading Eigen and multi-threading
+
+\section TopicMultiThreading_MakingEigenMT Make Eigen run in parallel
+
+Some Eigen's algorithms can exploit the multiple cores present in your hardware. To this end, it is enough to enable OpenMP on your compiler, for instance:
+ * GCC: \c -fopenmp
+ * ICC: \c -openmp
+ * MSVC: check the respective option in the build properties.
+You can control the number of thread that will be used using either the OpenMP API or Eiegn's API using the following priority:
+\code
+ OMP_NUM_THREADS=n ./my_program
+ omp_set_num_threads(n);
+ Eigen::setNbThreads(n);
+\endcode
+Unless setNbThreads has been called, Eigen uses the number of threads specified by OpenMP. You can restore this bahavior by calling \code setNbThreads(0); \endcode
+You can query the number of threads that will be used with:
+\code
+n = Eigen::nbThreads(n);
+\endcode
+You can disable Eigen's multi threading at compile time by defining the EIGEN_DONT_PARALLELIZE preprocessor token.
+
+Currently, the following algorithms can make use of multi-threading:
+ * general matrix - matrix products
+ * PartialPivLU
+
+\section TopicMultiThreading_UsingEigenWithMT Using Eigen in a multi-threaded application
+
+In the case your own application is multithreaded, and multiple threads make calls to Eigen, then you have to initialize Eigen by calling the following routine \b before creating the threads:
+\code
+#include <Eigen/Core>
+
+int main(int argc, char** argv)
+{
+ Eigen::initParallel();
+
+ ...
+}
+\endcode
+
+In the case your application is parallelized with OpenMP, you might want to disable Eigen's own parallization as detailed in the previous section.
+
+*/
+
+}