Skip to content

Commit 9864f61

Browse files
authored
Merge pull request #26 from chrisdjscott/set-nthreads
Setting number of OpenMP threads with a variable
2 parents f2e385f + 21498b0 commit 9864f61

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

GBS-Chip-Gmatrix.R

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ if (!exists("functions.only")) functions.only <- FALSE
1111
if (!exists("alleles.keep")) alleles.keep <- FALSE
1212
if (!exists("outlevel")) outlevel <- 9
1313
if (!exists("use.Rcpp")) use.Rcpp <- TRUE
14+
if (!exists("nThreads")) nThreads <- 0 # 0 means use all available
1415

1516
# function to locate Rcpp file (assume it is in the same directory as this file and this file was 'sourced')
1617
pathToCppFile = function() {
@@ -246,7 +247,7 @@ GBSsummary <- function() {
246247
if(gform != "chip") {
247248
if (!havedepth) depth <<- alleles[, seq(1, 2 * nsnps - 1, 2)] + alleles[, seq(2, 2 * nsnps, 2)]
248249
if (have_rcpp) {
249-
sampdepth.max <<- rcpp_rowMaximums(depth)
250+
sampdepth.max <<- rcpp_rowMaximums(depth, nThreads)
250251
}
251252
else {
252253
sampdepth.max <<- apply(depth, 1, max)
@@ -338,7 +339,7 @@ cat("Analysing", nind, "individuals and", nsnps, "SNPs\n")
338339
#if(outlevel > 4) sampdepth.med <<- apply(depth, 1, median)
339340
if(outlevel > 4) {
340341
if (have_rcpp) {
341-
sampdepth.med <<- rcpp_rowMedians(depth)
342+
sampdepth.med <<- rcpp_rowMedians(depth, nThreads)
342343
}
343344
else {
344345
sampdepth.med <<- apply(depth, 1, median)
@@ -420,7 +421,7 @@ if(!functions.only) {
420421
depth2K <- function(depthvals) {
421422
# Rcpp version only works with matrix as input, so fallback to R version otherwise
422423
if (is.matrix(depthvals)) {
423-
result <- rcpp_depth2K(depthvals)
424+
result <- rcpp_depth2K(depthvals, nThreads)
424425
} else {
425426
result <- r_depth2K(depthvals)
426427
}
@@ -440,7 +441,7 @@ if(!functions.only) {
440441
# Rcpp version only works with matrix as input, so fallback to R version otherwise
441442
if (is.matrix(depthvals) & alph < Inf) {
442443
if(alph < Inf) {
443-
result <- rcpp_depth2Kbb(depthvals, alph)
444+
result <- rcpp_depth2Kbb(depthvals, nThreads, alph)
444445
} else {
445446
result <- depth2K(depthvals)
446447
}
@@ -464,7 +465,7 @@ if(!functions.only) {
464465
depth2Kmodp <- function(depthvals, modp=0.5) {
465466
# Rcpp version only works with matrix as input, so fallback to R version otherwise
466467
if (is.matrix(depthvals)) {
467-
result <- rcpp_depth2Kmodp(depthvals, modp)
468+
result <- rcpp_depth2Kmodp(depthvals, modp, nThreads)
468469
} else {
469470
result <- r_depth2Kmodp(depthvals, modp)
470471
}
@@ -694,7 +695,7 @@ calcG <- function(snpsubset, sfx = "", puse, indsubset, depth.min = 0, depth.max
694695
dev.off()
695696
lowpairs <- which(cocall/nsnpsub <= cocall.thresh & upper.tri(cocall),arr.ind=TRUE)
696697
if (have_rcpp) {
697-
sampdepth.max <- rcpp_rowMaximums(depthsub)
698+
sampdepth.max <- rcpp_rowMaximums(depthsub, nThreads)
698699
}
699700
else {
700701
sampdepth.max <- apply(depthsub, 1, max)
@@ -762,7 +763,7 @@ calcG <- function(snpsubset, sfx = "", puse, indsubset, depth.min = 0, depth.max
762763
P0 <- matrix(puse[snpsubset], nrow = nindsub, ncol = nsnpsub, byrow = TRUE)
763764
P1 <- 1 - P0
764765
if (have_rcpp) {
765-
rcpp_assignP0P1Genon01(P0, P1, genon01, usegeno, depth[indsubset, snpsubset])
766+
rcpp_assignP0P1Genon01(P0, P1, genon01, usegeno, depth[indsubset, snpsubset], nThreads)
766767
}
767768
else {
768769
genon01[depth[indsubset, snpsubset] < 2] <- 0

GBS-Rcpp-functions.cpp

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,43 @@
66
#include <RcppArmadillo.h>
77

88
// we need OpenMP for parallelisation
9+
#include <omp.h>
910
// [[Rcpp::plugins(openmp)]]
1011

12+
13+
// helper function for deciding number of threads
14+
static int check_nThreads(int nThreads) {
15+
// maximum number of threads available
16+
int maxThreads = omp_get_max_threads();
17+
18+
if (nThreads <= 0) {
19+
// if nThreads is set to zero then use everything
20+
nThreads = maxThreads;
21+
}
22+
else if (nThreads > maxThreads) {
23+
// don't allow more threads than the maximum available
24+
nThreads = maxThreads;
25+
}
26+
27+
return nThreads;
28+
}
29+
30+
1131
// function for finding row medians (alternative to apply(depth, 1, median))
1232
// requires integer type matrix as input, returns list of doubles
1333
// [[Rcpp::export]]
14-
std::vector<double> rcpp_rowMedians(const arma::imat &depth) {
34+
std::vector<double> rcpp_rowMedians(const arma::imat &depth, int nThreads) {
35+
// set up number of threads
36+
nThreads = check_nThreads(nThreads);
37+
1538
// number of rows
1639
const int nrows = depth.n_rows;
1740

1841
// vector for storing the result
1942
std::vector<double> medians(nrows);
2043

2144
// loop over the rows
22-
#pragma omp parallel for
45+
#pragma omp parallel for num_threads(nThreads)
2346
for (int i = 0; i < nrows; i++) {
2447
// convert the row to double type, to compute median correctly
2548
arma::rowvec row = arma::conv_to<arma::rowvec>::from(depth.row(i));
@@ -34,14 +57,18 @@ std::vector<double> rcpp_rowMedians(const arma::imat &depth) {
3457
// function for finding row maximums (alternative to apply(mat, 1, max))
3558
// requires integer type matrix as input, return list of integers
3659
// [[Rcpp::export]]
37-
std::vector<int> rcpp_rowMaximums(const arma::imat &mat) {
60+
std::vector<int> rcpp_rowMaximums(const arma::imat &mat, int nThreads) {
61+
// set up number of threads
62+
nThreads = check_nThreads(nThreads);
63+
64+
// number of rows
3865
const int nrows = mat.n_rows;
3966

4067
// create vector to store the result
4168
std::vector<int> maximums(nrows);
4269

4370
// loop over rows
44-
#pragma omp parallel for
71+
#pragma omp parallel for num_threads(nThreads)
4572
for (int i = 0; i < nrows; i++) {
4673
// find the maximum for this row
4774
maximums[i] = mat.row(i).max();
@@ -52,15 +79,18 @@ std::vector<int> rcpp_rowMaximums(const arma::imat &mat) {
5279

5380
// C++ version of depth2K function
5481
// [[Rcpp::export]]
55-
Rcpp::NumericMatrix rcpp_depth2K(const Rcpp::NumericMatrix &A) {
82+
Rcpp::NumericMatrix rcpp_depth2K(const Rcpp::NumericMatrix &A, int nThreads) {
83+
// set up number of threads
84+
nThreads = check_nThreads(nThreads);
85+
5686
// create the output matrix (same size as input)
5787
Rcpp::NumericMatrix Aout(A.rows(), A.cols());
5888

5989
// number of elements
6090
const long Asize = A.rows() * A.cols();
6191

6292
// loop over elements in parallel and apply operation
63-
#pragma omp parallel for
93+
#pragma omp parallel for num_threads(nThreads)
6494
for (long i = 0; i < Asize; i++) {
6595
Aout[i] = 1.0 / pow(2.0, A[i]);
6696
}
@@ -71,15 +101,18 @@ Rcpp::NumericMatrix rcpp_depth2K(const Rcpp::NumericMatrix &A) {
71101

72102
// C++ version of depth2Kmodp function
73103
// [[Rcpp::export]]
74-
Rcpp::NumericMatrix rcpp_depth2Kmodp(const Rcpp::NumericMatrix &depthvals, double modp = 0.5) {
104+
Rcpp::NumericMatrix rcpp_depth2Kmodp(const Rcpp::NumericMatrix &depthvals, double modp, int nThreads) {
105+
// set up number of threads
106+
nThreads = check_nThreads(nThreads);
107+
75108
// create matrix for storing the result
76109
Rcpp::NumericMatrix result(depthvals.rows(), depthvals.cols());
77110

78111
// size of the matrix
79112
const long size = depthvals.rows() * depthvals.cols();
80113

81114
// loop over the elements in parallel
82-
#pragma omp parallel for
115+
#pragma omp parallel for num_threads(nThreads)
83116
for (long i = 0; i < size; i++) {
84117
double value = 0.5 * pow(modp, depthvals[i] - 1.0);
85118
result[i] = (value == 0) ? 1.0 : value;
@@ -89,15 +122,17 @@ Rcpp::NumericMatrix rcpp_depth2Kmodp(const Rcpp::NumericMatrix &depthvals, doubl
89122

90123
// C++ version of depth2Kbb function
91124
// [[Rcpp::export]]
92-
Rcpp::NumericMatrix rcpp_depth2Kbb(const Rcpp::NumericMatrix & depthvals, const double alph = 9999) {
125+
Rcpp::NumericMatrix rcpp_depth2Kbb(const Rcpp::NumericMatrix & depthvals, int nThreads, const double alph = 9999) {
126+
// set up number of threads
127+
nThreads = check_nThreads(nThreads);
93128
// create matrix for storing the result
94129
Rcpp::NumericMatrix result(depthvals.rows(), depthvals.cols());
95130
// size of the matrix
96131
const long size = depthvals.rows() * depthvals.cols();
97132
// precompute factor
98133
const double factor = 1.0/R::beta(alph, alph);
99134
// loop over the elements in parallel
100-
#pragma omp parallel for
135+
#pragma omp parallel for num_threads(nThreads)
101136
for (long i = 0; i < size; i++) {
102137
result[i] = R::beta(alph, depthvals[i] + alph) * factor;
103138
}
@@ -109,12 +144,15 @@ Rcpp::NumericMatrix rcpp_depth2Kmodp(const Rcpp::NumericMatrix &depthvals, doubl
109144
// modifies the matrices in-place (i.e. doesn't return anything)
110145
// [[Rcpp::export]]
111146
void rcpp_assignP0P1Genon01(Rcpp::NumericMatrix &P0, Rcpp::NumericMatrix &P1, Rcpp::NumericMatrix &genon01,
112-
const Rcpp::LogicalMatrix &usegeno, const Rcpp::NumericMatrix &dsub) {
147+
const Rcpp::LogicalMatrix &usegeno, const Rcpp::NumericMatrix &dsub, int nThreads) {
148+
// set up number of threads
149+
nThreads = check_nThreads(nThreads);
150+
113151
// number of elements (assumes all inputs are the same size!)
114152
const long size = P0.rows() * P0.cols();
115153

116154
// loop over elements in parallel
117-
#pragma omp parallel for
155+
#pragma omp parallel for num_threads(nThreads)
118156
for (long i = 0; i < size; i++) {
119157
// set to zero if they match the conditions
120158
if (dsub[i] < 2.0) {

0 commit comments

Comments
 (0)