Проблема безопасности потока в eig_sym броненосца

У меня проблема с собственным разложением в броненосце через eig_sym. Когда я пытаюсь вычислить несколько наборов собственных значений и собственных векторов параллельно, время от времени собственные векторы

  • не ортогональный
  • не нормируется
  • и даже не собственные векторы рассматриваемой матрицы.

Эта проблема исчезает, если в каждый момент времени выполняется только один расчет (так что, похоже, это проблема безопасности потока). Как только два вычисления выполняются параллельно, проблема снова возникает. Как ни странно, собственные значения кажутся правильными в каждом случае.

//compile with: g++ -std=c++11 -pthread -larmadillo -o evecs armadillo_evecs.cpp
#include <iostream>
#include <armadillo>
#include <assert.h>
#include <future>
#include <vector>
using namespace std;

void testcalc() {
// set up random symmetric matrix
arma::mat r = arma::randu<arma::mat> (100, 100);
r  = r.t() * r;

arma::vec eval;
arma::mat evec;
// calculate eigenvalues and -vectors
assert(arma::eig_sym(eval, evec, r));
arma::mat test = evec.t() * evec;

// Check whether eigenvectors are orthogonal, (i. e. matrix 'test' is diagonal)
assert(arma::norm(test - arma::diagmat(test)) < 1.0e-10);
}int main() {
// start 100 eigenvalue (+vector) calculations
vector<future<void>> fus;
for (size_t i = 0; i < 100; i++) {
// try parallel evaluation ... fails sometimes
fus.push_back(async(launch::async, &testcalc));

// try sequential evaluation ... works fine
// future<void> f = async(launch::async, &testcalc);
// f.get(); // Wait until calculation has finished, before starting new one
}

// wait until calculations have finished
for(auto it = fus.begin(); it != fus.end(); it++) {
it->get();
}

return 0;
}

Так что в приведенном выше коде утверждение

assert(arma::norm(test - arma::diagmat(test)) < 1.0e-10);

иногда терпит неудачу. Может ли это быть проблемой базовых библиотек (я читал, что у lapack были некоторые проблемы с безопасностью потоков)? Я не знаю, с чего начать.

1

Решение

Вместо того, чтобы «свернуть собственное распараллеливание», проще и безопаснее использовать распараллеливание, уже обеспеченное базовой библиотекой.

Поэтому вместо использования ссылочных BLAS и LAPACK используйте многопоточную версию, например OpenBLAS или же Intel MKL. Смотреть броненосец Часто задаваемые вопросы Больше подробностей.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector