N <- 100000
dataset <- matrix(runif(N * 3, min = 0, max = 100), nrow = N)
M <- colMeans(dataset)
getB.old <- function() {
    dataset - (matrix(rep(M, N), byrow = T, nrow = N))
}
getB.t <- function() {
    t(t(dataset) - M)
}
getB.apply <- function() {
    t(apply(dataset, 1, function(x) x - M))
}

all.equal(getB.old(), getB.t())
## [1] TRUE
all.equal(getB.old(), getB.apply())
## [1] TRUE
#include <Rcpp.h>

using namespace Rcpp;
//[[Rcpp::export]]
NumericMatrix getB_cpp(const NumericMatrix& dataset, const NumericVector& m) {
    int n_row = dataset.nrow();
    int n_col = dataset.ncol();
    NumericMatrix ret(n_row, n_col, dataset.begin());
    for (auto row = 0; row < n_row; ++row) {
        ret(row, _) = ret(row, _) - m;
    }
    return ret;
}
all.equal(getB.old(), getB_cpp(dataset, M))
## [1] TRUE
library("microbenchmark")
microbenchmark(
    getB_cpp(dataset, M),
    getB.old(),
    getB.t(),
    getB.apply()
)
## Unit: microseconds
##                  expr       min         lq       mean     median
##  getB_cpp(dataset, M)  1431.147  1517.0190   3360.346  1563.2425
##            getB.old()   669.378   726.0315   5474.898   854.8665
##              getB.t()   739.683   828.0995   5008.133  1358.6240
##          getB.apply() 79982.989 89367.8450 104940.547 98707.6385
##          uq       max neval
##    2112.956  36240.08   100
##    3472.483  44064.17   100
##    3743.392  36471.36   100
##  118376.453 156308.37   100