Segfault, когда присваивает значения разреженной матрице многопоточностью - PullRequest
1 голос
/ 18 октября 2019

Я намереваюсь заполнить разреженную матрицу значениями, которые получены из серии шагов, чтобы сделать ее более эффективной, OpenMP используется для ускорения этих процессов, я считаю, что он отлично работает при использовании 1 потока, но перехватил segfault для нескольких-потом, я подготовил простой демонстрационный код для воспроизведения ошибки, искренне надеюсь, что кто-то может сделать мне одолжение.

#include <RcppArmadillo.h>
#include <omp.h>

// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(bigmemory, BH)]]

using namespace std;
using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
arma::sp_mat test(arma::vec x, int n, int threads = 1){
    omp_set_num_threads(threads);
    arma::sp_mat m(n, n);
    #pragma omp parallel for schedule(dynamic) 
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            m(i, j) = x[i * n + j];
        }
    }
    return m;
}

# run 
a<-test(sample(c(0,1,2),100*100,rep=T), n=100, threads=1)
a<-test(sample(c(0,1,2),100*100,rep=T), n=100, threads=10)

1 Ответ

3 голосов
/ 18 октября 2019

tl; dr: Вы не можете.

Более длинная история: Одним из ключевых преимуществ (Rcpp) Armadillo является очень хороший и последовательный API поверх базовых операций, которыйгде-то между запутанным и сложным в использовании. Одним из недостатков является то, что мы легко упускаем из виду базовые структуры данных. Матрицы

Плотные являются (по существу, всегда) фиксированными порциями памяти. По сути, вектор размером строки x столбцов. Это то, что позволяет нам эффективно передавать «нулевую копию» между R и (Rcpp) Armadillo. Это также позволяет нам одновременно работать с неперекрывающимися блоками. Это большое дело, и например RcppParallel в полной мере использует его. OpenMP работает здесь.

Разреженные матрицы - это (и я упрощаю здесь) динамический список / векторные типы с взаимозависимостью. Так что параллельная работа просто не может работать. Грустный. Но это то, что есть. Это становится понятным, как только вы присмотритесь к общим структурам данных для разреженных матриц (как это делает например пакет Matrix R). И, например, этот фрагмент википедии - довольно приличное и подробное введение.

...