从执行速度的角度来看,“bsxfun”和“sweep”两种方法都不是最优的。实际上,“bsxfun”的性能非常差,对于非玩具应用程序似乎毫无用处。
在我的基准测试中,最快的方法是:
matrix(a, ncol = n_col, nrow = nsample, byrow = TRUE) * b
sweep()
在矩阵大小增加时变得更有竞争力,但即使对于中等大小的矩阵(1e6-by-4),它所需的时间也是双倍的。
以下是完整的基准测试结果
rm(list=ls())
library(microbenchmark)
library(pracma)
a = c(1,0,3,-4)
n_col = 4
nsample = 1e3
b = repmat(matrix(c(0,2,1,9,5,-3,7,4),nrow = 2,ncol = n_col), nsample / 2, 1)
print(microbenchmark(
erg_1 = matrix(a, ncol = n_col, nrow = nsample, byrow = TRUE) * b,
erg_2 = matrix(rep.int(a, nsample), nrow = nsample, ncol = n_col, byrow = TRUE) * b,
erg_3 = matrix(a * c(t(b)), nrow = nsample, ncol = n_col, byrow = TRUE),
erg_4 = sweep(b, 2, a, '*'),
erg_5 = bsxfun('*', repmat(a, nsample, 1), b)
))
nsample = 1e6
b = repmat(matrix(c(0,2,1,9,5,-3,7,4),nrow = 2,ncol = n_col), nsample / 2, 1)
print(microbenchmark(
erg_1 = matrix(a, ncol = n_col, nrow = nsample, byrow = TRUE) * b,
erg_2 = matrix(rep.int(a, nsample), nrow = nsample, ncol = n_col, byrow = TRUE) * b,
erg_3 = matrix(a + c(t(b)), nrow = nsample, ncol = n_col, byrow = TRUE),
erg_4 = sweep(b, 2, a, '*')
))
>Unit: microseconds
expr min lq mean median uq max neval
erg_1 9.057 10.1135 11.93394 11.0195 12.6790 36.226 100
erg_2 14.189 15.3970 18.75324 16.9060 19.9250 41.358 100
erg_3 26.263 28.8295 35.04538 30.9430 34.8675 86.941 100
erg_4 40.452 44.0750 56.88289 51.4705 66.4130 109.279 100
erg_5 2694.827 2968.4755 3243.76025 3208.9185 3417.5125 5575.306 100
>Unit: milliseconds
expr min lq mean median uq max neval
erg_1 10.85538 11.30668 20.58625 12.93408 13.28290 69.17918 100
erg_2 16.07206 18.00058 29.17394 18.24751 20.09845 75.30993 100
erg_3 22.41231 24.58957 30.83620 24.99544 26.49047 79.71910 100
erg_4 20.74838 21.53673 29.52071 22.88867 23.30420 81.07150 100
sweep
函数。 - Hugo Raguet