Repository navigation
Replies: 1 comment
|
Small update to my initial message: I profiled
Now the time cost of residual component is much smaller, with |
|
Small update to my initial message: I profiled
Now the time cost of residual component is much smaller, with |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
New CRAN package fastrda promises faster RDA for large data sets. It uses C++ backend with OMP for parallel computation. The package is mainly intended for large genomic data with dimensions in thousands or tens of thousands. I had a quick look at the function and ran some comparisons against vegan – not because I doubt fastrda claims but to see if we can learn something from it and why would that be faster. I used ARM-based Mac M1 which may not be the best platform for fastrda due to poor or lacking OMP support in macOS. Mac ARM platforms also have optimized and very fast BLAS in a matrix algebra suprocessor ("neural engine"). While constrained ordination is written in R, it uses BLAS for all calculations and the R overhead is pretty small so that I do not expect much speed-up from switching from R to compiled code – most of the time is already spent in compiled code of BLAS/Lapack. All below is based on my particular platform, and results can be different with different hardware and OS. Parallel analyses are welcom.
vegan::rdawas much faster in the first quick test withmitedata. This was expected becausefastrda::fastrdais designed for large data sets. The proper test usedbryceveg&brycesitedata of the labdsv package These are more realistic larger vegetation data with dimensions 160 × 169 though not yet large and pretty small when compared to genomic data. I used model matrix~ elev + annrad + pos(rank 6). Heremicrobenchmark::microbenchmarkgotfastrdaas a clear winner when not using M1 optimized BLAS:vegan::rda23.3 msec,fastrda::fastrda6.6 msec median times. With optimized BLAS bothrdaandfastrdaused 6.0 msec.The C++ backend is not the only thing that
fastrdahas for speed-up. It calculates (default) only three first constrained eigenvalues, and it does not calculate residual unconstrained solutions. So I had a look wherevegan::rdaspends its time withRproffor a loop of 100rdawith the same data. Here a selection of relevant entries:rdaordConstrainedsvdordResidordConstrainqr.residThese numbers are with the slower "reference BLAS". Residual unconstrained solution uses nearly two times as much time as the constrained solutions. Moreover,
qr.residis only used inordConstrainto prepare matrix passed on toordResidso that the time cost of unconstrained component is 63.8 + 22.4 = 86.2% of running time.Do we always need the unconstrained component?
fastrdanever calculates that component and that is one explanation why it is faster. We do know the sum of residual eigenvalues (residual inertia) without explicit calculation of eigenvalues and eigenvectors (and do this invegan::simpleRDA2that is used invegan::varpart). Moreover, dropping residual component would make result object smaller: the constrained scores have dimensions 160 × 6, but in this case the unconstrained scores have dimensions 160 × 148. Especially with large genomic data sets with a huge number of columns, the cost of calculating unconstrained scores is huge and object sizes get really big. If we want to suppress the calculation of unconstrained residual component, this should be optional and the default should be to calculate.You perhaps noticed that unconstrained scores had only 148 columns although the input data had dims 160 × 169. This happened because the residual matrix had no full rank but several last eigenvalues were practically zero and dropped from the
vegan::rdaresult. Thereforevegan::rdareports the residual rank as 148, butfastrdaas 153 (160 – 6 constraints - 1). This you only know if you evaluate the rank.vegan:::ordResiddoes this by looking at the eigenvalues, but this could also be estimated faster from the rank of the QR decomposition of the residual matrix (inordResid(Y)withqr(Y)$rank). However, calculation of residual axis scores takes much time, and dropping their calculation can make a big speed-up: according tomicrobenchmarkrunningsvd(Y)took 10.4 msec, butsvd(Y, nv=0, nu=0)3.7 msec or nearly three times speed-up. So if we want to keep the eigenvalues we could optionally suppress only calculating scores. This alone could mean great savings both in time and object sizes.See also Discussion #776 and Issue #527.
All reactions