2017-03-07 91 views
1

更高效地实现以下功能的任何想法?R功能效率

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

我建议在这里发帖:http://codereview.stackexchange.com/代码审查 – SpaceCowboy

+0

你可以'输''A','B'吗? –

+0

@SpaceCowboy好吧,我也会在那里发帖,谢谢! – ixpl

回答

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 
+1

好的,谢谢!现在确实比较干净。 – ixpl