我有,我会大量调用一个函数(每次迭代大约10^11倍的优化,一些不同的实验)。我已经实现了一个快速版本,但我很努力地看到我可以如何提高性能。 '系统'时间很短,用户时间很长。加快代码:减少“用户”时间
下面的代码,它需要在一个整数,并返回表示该整数是一个不同的基计数系统的载体(例如碱= 2给出了二进制,碱= 10给出了标准结果背面)。参数k给出要返回的向量的长度,所以前面可能有很多零。
正如你看到的,功能采取5或7秒的运行,但它没有一个是系统时间。我想了解为什么,以及是否有办法加快速度。我有其他功能(的99%的时间是花费在一个环路一个功能,但加速它200fold只有一半的运行时间)这个同样的问题,但我出这一个清晰度。
library(Rcpp)
library(microbenchmark)
# Rcpp version of the function
cppFunction('
NumericVector convert10tobase_c(double number_b10, int k, int base = 4){
if(number_b10 >= pow(base, k)){
stop("k is not large enough to contain the number in this base");
}
NumericVector ret(k);
if(k == 1){
return number_b10;
}
for (int i = 1 ;i < k; i++){
double entry = floor(number_b10/pow(base, (k - i)));
ret[i-1] = entry;
number_b10 = number_b10 - entry * pow(base, (k - i));
}
ret[k-1] = number_b10;
return ret;
}')
# R version of the function
convert10tobase <- function(number_b10, k, base = 5){
if(number_b10 >= base^k){
stop("k is not large enough to contain the number in this base")
}
ret <- rep(0, k)
if(k == 1){
return(number_b10)
}
for (i in 1:(k - 1)){
entry <- floor(number_b10/base^(k-i))
ret[i] <- entry
number_b10 <- number_b10 - entry * (base^(k - i))
}
ret[k] <- number_b10
return(ret)
}
# generate test data one hundred, thousand and million integers
set.seed(1)
base <- 4
k <- 8
ints_short <- floor(runif(1e2) * (base^k))
ints_long <- floor(runif(1e4) * (base^k))
ints_v_long <- floor(runif(1e6) * (base^k))
# benchmark the Rcpp version
microbenchmark(
one = convert10tobase_c(ints_short[1], k, base),
hundred = sapply(1:length(ints_short), function(i) convert10tobase_c(ints_short[i], k, base)),
ten_thous = sapply(1:length(ints_long), function(i) convert10tobase_c(ints_long[i], k, base)),
times = 100)
# test R and Rcpp times
r_start <- proc.time()
t <- sapply(1:length(ints_v_long), function(i) convert10tobase(ints_v_long[i], k, base))
r_stop <- proc.time()
c_start <- proc.time()
t <- sapply(1:length(ints_v_long), function(i) convert10tobase_c(ints_v_long[i], k, base))
c_stop <- proc.time()
# results - little time in 'system'
r_stop - r_start
c_stop - c_start
顺便说一句,我包含了一次调用一次,一百次和十万次的比较。一百个电话的时间比一个电话慢300倍,而一个电话的时间比一百个电话慢三十倍。我想了解为什么,并希望能够解释它的任何资源。
谢谢!
你可以从你的矢量化功能,而不是单独调用它要检查每个整数受益。 – Heroka
重复使用“pow”值而不是两次计算它有一个小的潜在好处。另外请注意,可以通过注意'i'和'i + 1'之间的“除以基数”关系来减少指数的数量。 – mvkorpel
大部分时间都花在调用函数的开销上。如果用C++循环替换'sapply',即可以通过向@Heroka指出的矢量化函数,可以显着提高性能。 – Roland