2012-01-11 12 views
10

Estoy solucionando un problema mucho más grande y me he encontrado con un error cuando trato de usar OpenMP para paralelizar algunos bucles. He reproducido el problema con un código más simple a continuación que imita mi propio código.Usar OpenMP y Eigen causa un bucle infinito/interbloqueo

El problema es que cuando ejecuto el programa, entrará aleatoriamente en un tipo de bucle/interbloqueo infinito (la CPU es 100%, pero no hace nada). Por lo que puedo decir de mis pruebas, uno de los hilos intenta calcular el producto matriz-matriz pero nunca termina por alguna razón.

Sé que si habilita OpenMP, Eigen paralelizará los productos de matriz matricial utilizando OpenMP. También estoy agregando otro bucle paralelo fuera de esto. Sin embargo, esta falla aún ocurre si deshabilito la paralelización de Eigen al definir EIGEN_DONT_PARALLELIZE.

Estoy usando gcc versión 4.6.0 20101127 en MacOS 10.6.8 con Eigen 3.0.4.

No puedo imaginar lo que podría ir mal ...

#include <iostream> 
#include <Eigen/Core> 

using namespace std; 
using namespace Eigen; 

MatrixXd Test(MatrixXd const& F, MatrixXd const& G) 
{ 
    MatrixXd H(F.rows(), G.cols()); 
    H.noalias() = F*G; 

    return H; 
} 

int main() 
{ 
    MatrixXd F = MatrixXd::Random(2,2); 
    MatrixXd G = MatrixXd::Random(2,2); 

    #pragma omp parallel for 
    for (unsigned int i = 0; i < 10000; ++i) 
    MatrixXd H = Test(F,G); 

    cout << "Done!" << endl; 
} 
+0

¿'MatrixXd :: Random' thread-safe? – Mysticial

+0

En mi código real, no estoy llamando a MatrixXd :: Random. Editar: Cambié el código para eliminar las llamadas a MatrixXd :: Random y el error todavía está allí. – user1144371

+0

no es algo estúpido como [esto] (http://eigen.tuxfamily.org/dox/TopicWrongStackAlignment.html)? Porque actualmente esto no parece un error de openmp. Descargué y ejecuté su programa en paralelo sin ningún problema con la versión 4.5.0 20100604 de gcc. – Bort

Respuesta

10

Después de una cierta depuración, creo que el problema se encuentra en Eigen. En el archivo src/Core/products/GeneralBlockPanelKernel.h hay una función llamada manage_caching_sizes que declara dos variables estáticas:

static std::ptrdiff_t m_l1CacheSize = 0; 
static std::ptrdiff_t m_l2CacheSize = 0; 

Cambiando esto a:

static std::ptrdiff_t m_l1CacheSize = 0; 
static std::ptrdiff_t m_l2CacheSize = 0; 
#pragma omp threadprivate(m_l1CacheSize, m_l2CacheSize) 

fijo mi problema.

+2

Acabo de notar que este error se corrigió en las versiones recientes de Eigen, gracias a esta pregunta de stackoverflow, consulte el informe de errores: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=406 Así que ahora la solución sería para actualizar tu biblioteca Eigen – catchmeifyoutry

2

Tuve el mismo problema, incluso con la versión más reciente de Eigen (3.0.5). Probé la solución propuesta más arriba y no es posible con la versión 3.0.5, debido a los nuevos inicializadores. Así que hice el siguiente cambio:

static std::ptrdiff_t m_l1CacheSize; 
static std::ptrdiff_t m_l2CacheSize; 
#pragma omp threadprivate(m_l1CacheSize, m_l2CacheSize) 

if (m_l1CacheSize==0) 
{ 
    m_l1CacheSize = manage_caching_sizes_second_if_negative(queryL1CacheSize(),8 * 1024); 
    m_l2CacheSize = manage_caching_sizes_second_if_negative(queryTopLevelCacheSize(),1*1024*1024); 
} 

solucionó mi problema.

2

Estaba teniendo el mismo problema al usar Microsoft Visual Studio 2010 SP1 PPL/parallel_for. La solución se describe en

http://eigen.tuxfamily.org/dox/TopicMultiThreading.html

Usando Eigen en una aplicación multiproceso

En el caso es multiproceso su propia aplicación, y múltiples hilos hacer llamadas a Eigen, entonces usted tiene que inicializar Eigen por llamando a la siguiente rutina antes de crear los hilos:

#include <Eigen/Core> 

int main(int argc, char** argv) 
{ 
    Eigen::initParallel(); 

    ... 
} 

En En el caso de que su aplicación esté paralelizada con OpenMP, puede querer deshabilitar la propia parallización de Eigen como se detalla en la sección anterior .