ecodist::bcdist
вызывает C реализацию расстояния Брея Кертиса, которое довольно сложно преодолеть с точки зрения времени. Однако он является однопоточным и, следовательно, возможный подход заключается в распараллеливании вычислений с использованием OpenMP через R cpp:
bcd.cpp
:
#include <omp.h>
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::plugins(openmp)]]
// [[Rcpp::export]]
NumericMatrix bcd(NumericMatrix m) {
int i, j, k, nr = m.nrow(), nc = m.ncol();
NumericMatrix res(nr, nr);
double ms, sum;
#pragma omp parallel for private(ms, sum, j, k)
for (i = 0; i < nr - 1; i++) {
for (j = i + 1; j < nr; j++) {
ms = 0;
sum = 0;
for (k = 0; k < nc; k++) {
if (m(i, k) < m(j, k)) {
ms += m(i, k);
} else {
ms += m(j, k);
}
sum += m(i, k) + m(j, k);
}
res(j, i) = 1 - 2 * ms / sum;
}
}
return(res);
}
временной код:
set.seed(0L)
library(ecodist)
nr <- 10000
nc <- 100
m <- matrix(round(runif(nr*nc), 1L), nrow=nr, ncol=nc)
library(Rcpp)
sourceCpp("bcd.cpp")
microbenchmark::microbenchmark(times=3L,
a1 <- bcdist(m, rmzero = FALSE),
a2 <- bcd(m))
all.equal(as.vector(a1), a2[lower.tri(a2)])
#[1] TRUE
сроки:
Unit: seconds
expr min lq mean median uq max neval
a1 <- bcdist(m, rmzero = FALSE) 24.348883 24.42572 24.496605 24.502548 24.570466 24.638384 3
a2 <- bcd(m) 8.365889 8.50686 8.563122 8.647831 8.661739 8.675646 3