2015-07-31 1 views
1

Итак, у меня есть большая функция, которая выполняет алгоритм MCMC. Я считаю, что большая часть из дорогих операций - это умножения больших матриц, но этот вывод Rprof довольно озадачивает.Интерпретация выхода Rprofile: что это такое <Anonymous> Функция?

$by.self 
       self.time self.pct total.time total.pct 
"<Anonymous>"  328.90 81.84  329.34  81.95 
"fprod"    46.16 11.49  376.02  93.57 
"Dikin_Walk"   7.42  1.85  401.32  99.86 
"as.vector"   5.98  1.49  57.56  14.32 
".External"   2.54  0.63  2.54  0.63 
"-"     1.84  0.46  1.84  0.46 
"H_x"    1.16  0.29  225.82  56.19 
"fcrossprod"   1.14  0.28  226.12  56.27 

Edit: Вот эти 3 функции, которые я определяю в моей большой функции обертку:

## first, augment A | b 
A_b <- cbind (b, A) 

## H(x) is the hessian 
H_x <- function(x) { 
    D <- as.vector(1/(A_b[,1] - fprod(A_b[,-1], x))) 
    D_squared <- fdiag(D^2) 
    return(fcrossprod(A, fprod(D_squared, A))) 
} 

## D(x) is the diagonalized matrix of the log-barrier function of Ax <= b 
D_x <- function(x) { 

    D <- as.vector(1/(A_b[,1] - fprod(A_b[,-1], x))) 
    return(fdiag(D)) 
} 

## checks whether a point z is in Ellip(x) 
ellipsoid <- function(z, x) { 

    ## as.numeric converts the expression into an atom, so we get boolean 
    return(as.numeric(fcrossprod(z-x, fprod(H_x(x), (z-x)))) <= r^2) 

} 

fdiag, fcrossprod и fprod все RcppArmEigen версии своих R коллег. Я использовал их, потому что они значительно быстрее.

Главный алгоритм:

> for (i in 1:n) { 
> 
> zeta <- rnorm(length(b), 0, 1) 
> zeta <- r * zeta/sqrt(as.numeric(fcrossprod(zeta,zeta))) 
> 
> rhs <- fcrossprod(A, fprod(D_x(current.point), zeta)) 
>  
> ## DONE 
>  
> y <- fprod(fsolve(H_x(current.point)), rhs) 
> y <- y + current.point 
>  
> 
> while(!ellipsoid(current.point, y)) { 
> zeta <- rnorm(length(b), 0, 1) 
>  
>  ## normalise to be on the m- unit sphere 
>  ## and then compute lhs as a m-vector 
>  zeta <- r * zeta/sqrt(sum(zeta * zeta)) 
>  
>  
>  rhs <- fcrossprod(A, fprod(D_x(current.point), zeta)) 
>  
>  ## 
>  y <- fprod(fsolve(H_x(current.point)), rhs) 
>  y <- y + current.point 
>  
> 
>  if(ellipsoid(current.point, y)) { 
>  
>  probability <- min(1, sqrt(fdet(fprod(fsolve(H_x(current.point)),H_x(y))  ))) 
>   
>   
>  bool <- sample(c(TRUE, FALSE), 1, prob = c(probability, 1-?>probability)) 
>  if(bool) { 
>   break 
>  } 
>  } 
> } 

А вот by.total выхода:

$by.total 
         total.time total.pct self.time self.pct 
"Dikin_Walk"    401.32  99.86  7.42  1.85 
"fprod"     376.02  93.57  46.16 11.49 
"<Anonymous>"    329.34  81.95 328.90 81.84 
"cbind"     268.58  66.83  0.04  0.01 
"fcrossprod"    226.12  56.27  1.14  0.28 
"H_x"      225.82  56.19  1.16  0.29 
"fsolve"     203.82  50.72  0.14  0.03 
"ellipsoid"    126.30  31.43  0.56  0.14 
"fdet"      64.84  16.13  0.02  0.00 
"as.vector"    57.56  14.32  5.98  1.49 
"fdiag"     35.68  8.88  0.50  0.12 

fprod определяется как:

prodCpp <- 'typedef Eigen::Map<Eigen::MatrixXd> MapMatd; 
const MapMatd B(as<MapMatd>(BB)); 
const MapMatd C(as<MapMatd>(CC)); 
return wrap(B * C);' 

fprod <- cxxfunction(signature(BB = "matrix", CC = "matrix"), 
         prodCpp, "RcppEigen") 
+0

Ваш вопрос, если это функция, которая называется , или это почему эта функция займет так много времени? – Dason

+0

Я думаю, что это просто анонимный, потому что вы не называете эту функцию. – Jimbo

+0

@Dason Извините, я думаю, мой вопрос - почему эта анонимная функция занимает так много времени. В моем коде нет другой анонимной функции. –

ответ

1

<Anonymous> относится к анонимным (безымянным) функциям , Если вы выполняете такую ​​функцию в цикле, большую часть времени обычно тратится на эту функцию.

По-видимому A_b является матрицей и x вектор. Использование матричной алгебры вместо цикла:

A_b <- matrix(1:16, 4) 
x <- 1:3 
D <- apply(A_b, 1, function(row) {1/(row[1] - sum(row[-1] * x))}) 

D1 <- as.vector(1/(A_b[,1] - A_b[,-1] %*% x)) 

identical (D, D1) 
#[1] TRUE 

Edit:

Анонимная функция в магии Rcpp из fprod:

B <- matrix(rnorm(1e6),1e3) 
C <- matrix(rnorm(1e6),1e3) 

Rprof() 
for (i in 1:30) BC <- fprod(B, C) 
Rprof(NULL) 
summaryRprof() 
#$by.self 
#    self.time self.pct total.time total.pct 
#"<Anonymous>"  4.24  100  4.24  100 
# 
#$by.total 
#    total.time total.pct self.time self.pct 
#"<Anonymous>"  4.24  100  4.24  100 
#"fprod"    4.24  100  0.00  0 
# 
#$sample.interval 
#[1] 0.02 
# 
#$sampling.time 
#[1] 4.24 

Большая часть вашего времени тратится с матричным умножением , Вы можете воспользоваться оптимизированным BLAS, например, вы можете попробовать OpenBLAS.

+0

замечательный !!!! Большое вам спасибо @Roland! –

+0

я включил его, но я думаю, что я на самом деле интерпретировал функции неправильно: '$ by.self self.time self.pct total.time total.pct «»122,94 96,97 122,94 96.97' У вас есть Есть идеи? –

+0

Не видя больше кода. Я думаю, что вы показали, что на самом деле это «FUN» в профилировании, так как это параметр «apply», которому передается функция. В вашем коде должна быть анонимная функция. Поскольку у меня нет этого кода, я не могу помочь вам найти его. – Roland

1

Прежде всего, игнорируйте «свое время», потому что «общее время» включает в себя плюс призывы. Если вы проводите какое-либо время, в котором вы не нуждаетесь, вы, скорее всего, будете делать это, вызывая функции, чем хруст. **

Во-вторых, даже не смотрите на это. Rprofile создает файл стеков. Просто взгляните на несколько из них, выбранных наугад. Если функция отвечает за 80% времени, вы увидите ее примерно на 4 из 5 трасс стека. Более того, вы увидите, кто его называет, и вы увидите, кого он зовет, чтобы потратить время. Простые номера не говорят об этом. Сортировка трассировки стека также не говорит об этом.

Было бы даже лучше, если бы он дал номера строк, на которых были сделаны вызовы, но это не так. Несмотря на это, просто показ функций по-прежнему очень полезен.

** Профилеры отображают только «свое время», потому что они всегда есть, и потому, что все это делают, и мало кто проснулся до того, что это просто отвлечение. Если функция находится на конце трассировки стека, она находится в «self time». Так или иначе, это «включено время».

+0

Очень информативно! Спасибо. –