Spec-Zone.ru › Eigen3

Eigen и многопоточность

Запуск Eigen в параллельном режиме

Некоторые алгоритмы Eigen могут использовать несколько ядер процессора в вашей системе. Для этого достаточно включить OpenMP в вашем компиляторе, например:

  • GCC: -fopenmp
  • ICC: -openmp
  • MSVC: проверьте соответствующий параметр в свойствах сборки.

Вы можете контролировать количество потоков, которые будут использоваться, используя либо API OpenMP, либо API Eigen с приоритетом:

OMP_NUM_THREADS=n ./my_program
omp_set_num_threads(n);
Eigen::setNbThreads(n);

Если setNbThreads не был вызван, Eigen использует количество потоков, указанное в OpenMP. Вы можете восстановить это поведение, вызвав setNbThreads(0);. Вы можете запросить количество используемых потоков с помощью:

n = Eigen::nbThreads( );

Вы можете отключить многопоточность Eigen во время компиляции, определив препроцессорный символ EIGEN_DONT_PARALLELIZE.

В настоящее время следующие алгоритмы могут использовать многопоточность:

  • общие произведения плотных матриц
  • PartialPivLU
  • умножение разреженных матриц в порядке строк на вектор/матрицу
  • ConjugateGradient с Lower|Upper в качестве UpLo шаблона.
  • BiCGSTAB с разреженной матрицей в формате строк.
  • LeastSquaresConjugateGradient
Предупреждение
В большинстве ОС крайне важно ограничить количество потоков количеством физических ядер, иначе ожидается существенное снижение производительности, особенно для операций, включающих плотные матрицы.

Действительно, принцип гиперпоточности заключается в запуске нескольких потоков (в большинстве случаев 2) на одном ядре в перекрывающемся режиме. Однако ядро умножения матриц Eigen полностью оптимизировано и уже использует почти 100% мощности процессора. Следовательно, нет места для запуска нескольких таких потоков на одном ядре, и производительность значительно снижается из-за загрязнения кэша и других накладных расходов. На данном этапе чтения вы, вероятно, задаетесь вопросом, почему Eigen не ограничивает себя количеством физических ядер? Это просто потому, что OpenMP не позволяет узнать количество физических ядер, и поэтому Eigen запустит столько потоков, сколько ядер сообщает OpenMP.

Использование Eigen в многопоточном приложении

В случае, если ваше собственное приложение многопоточное, и несколько потоков обращаются к Eigen, необходимо инициализировать Eigen, вызвав следующую функцию до создания потоков:

#include <Eigen/Core>
 
int main(int argc, char** argv)
{
  Eigen::initParallel();
  
  ...
}
Примечание
В Eigen 3.3 и компиляторе, полностью совместимом с C++11 (т.е., безопасная для потоков инициализация статических локальных переменных), вызов initParallel() является необязательным.
Предупреждение
Обратите внимание, что все функции, генерирующие случайные матрицы, не являются реентерабельными или потокобезопасными. К ним относятся DenseBase::Random() и DenseBase::setRandom(), даже после вызова Eigen::initParallel(). Это связано с тем, что эти функции основаны на std::rand, которая не является реентерабельной. Для потокобезопасного генератора случайных чисел рекомендуется использовать генераторы случайных чисел C++11 (пример) или boost::random.

В случае, если ваше приложение распараллелено с помощью OpenMP, вы можете отключить собственную многопоточность Eigen, как описано в предыдущем разделе.

Предупреждение
Использование OpenMP с пользовательскими типами скаляров, которые могут генерировать исключения, может привести к непредсказуемому поведению при их генерации.

© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/TopicMultiThreading.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API