有任何想法可以更有效地实现以下功能吗?
prod_A_B <- function(A, B, i = NULL, j = NULL) {
if (is.null(i) & is.null(j)) {
A * B
} else if (!is.null(i) & is.null(j)) {
A[i, ] * B[i, ]
} else if (!is.null(i) & !is.null(j)) {
A[i, j] * B[i, j]
}
}
特别是,是否可以更简洁地实现条件语句,从而减少运行时间?
以下是一些基准:
n <- 1e5
d <- 200
A <- matrix(rnorm(n*d), nrow = n, ncol = d)
B <- matrix(rnorm(n*d), nrow = n, ncol = d)
pr1 <- pr2 <- matrix(0, nrow=n, ncol =d)
tm <- microbenchmark(
{for(i in 1:n) pr1[i,] <- prod_A_B(A, B, i)},
{for(i in 1:n) pr2[i, ] <- A[i,] * B[i,]},
times=100L)
print(tm)
Unit: milliseconds
min lq mean median uq max neval
1164.4078 1208.348 1234.607 1224.097 1254.059 1370.098 100
969.9961 1004.821 1036.738 1021.025 1056.182 1278.767 100
鉴于矩阵大小,差异并不大,但我仍然想知道我是否可以稍微提高性能......
谢谢!
答案 0 :(得分:1)
您可以通过简化逻辑谓词来节省一些时间,并且还可以删除多个函数调用,如下所示:
prod2_A_B <- function(A, B, i = NULL, j = NULL) {
ni <- is.null(i)
nj <- is.null(j)
if (ni & nj) {
A * B
} else if (nj) { # must be !ni
A[i, ] * B[i, ]
} else { # must be !ni & !nj
A[i, j] * B[i, j]
}
}
n <- 1e5
d <- 200
pr1 <- pr2 <- pr <- matrix(0, nrow=n, ncol =d)
A <- matrix(rnorm(n*d), nrow = n, ncol = d)
B <- matrix(rnorm(n*d), nrow = n, ncol = d)
library(microbenchmark)
tm <- microbenchmark(
{for(i in 1:n) pr1[i,] <- prod_A_B(A, B, i)},
{for(i in 1:n) pr2[i,] <- prod2_A_B(A, B, i)},
{for(i in 1:n) pr[i,] <- A[i,] * B[i,]},
times=100L)
print(tm)
Unit: milliseconds
expr min lq mean median uq max neval cld
{for (i in 1:n) pr1[i, ] <- prod_A_B(A, B, i)} 937.9470 944.6690 969.7894 952.2308 964.4701 1390.467 100 c
{for (i in 1:n) pr2[i, ] <- prod2_A_B(A, B, i)} 898.6802 908.3323 929.7343 914.6826 929.4356 1211.623 100 b
{for (i in 1:n) pr[i, ] <- A[i, ] * B[i, ]} 661.2350 666.7071 688.8127 672.6218 679.9028 1005.342 100 a