Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用带if选项的R函数时优化运行时_R_Function - Fatal编程技术网

使用带if选项的R函数时优化运行时

使用带if选项的R函数时优化运行时,r,function,R,Function,我的目标是优化我的R函数的运行时过程。 更具体地说,我的R函数包含各种if选项,例如,在运行使用该函数的模拟时,我需要修复函数选项。 是否有可能使R在不总是检查每个if选项的情况下使用该函数,即跳过所有其他选项并直接跳到预先指定的选项? 下面是一个具有两个函数的示例:fun1()不带任何if/else选项和fun2()带选项。使用两个函数的两个循环,实现相同的计算,然后计算运行时 # Data x = rexp(100) fun1 = function(x){ v= sqrt(x)

我的目标是优化我的R函数的运行时过程。 更具体地说,我的R函数包含各种if选项,例如,在运行使用该函数的模拟时,我需要修复函数选项。 是否有可能使R在不总是检查每个if选项的情况下使用该函数,即跳过所有其他选项并直接跳到预先指定的选项? 下面是一个具有两个函数的示例:
fun1()
不带任何if/else选项和
fun2()
带选项。使用两个函数的两个循环,实现相同的计算,然后计算运行时

# Data
x = rexp(100)

fun1 = function(x){
  
  v= sqrt(x)

  return(v)
}

fun2 = function(x, type = c("a", "b", "c","d","e","f")){
    if(type == "a"){ v = mean(x) }
    if(type == "b"){ v= median(x)}
    if(type == "c"){ v= var(x)}
    if(type == "d"){ v= sd(x)}
    if(type == "e"){ v= sqrt(x)} # type == "e" does the same as fun1
    if(type == "f"){ v= sum(x)}
  return(v)
}

# No. of iterations for loops below
iter = 10000000

system.time(
  for(i in 1:iter){
    res = fun1(x)
  }
)

# user     system      elapsed 
# 19.42      0.06       19.72 

system.time(
for(i in 1:iter){
  res = fun2(x, type = "e")
}
)

# user     system      elapsed 
# 33.10        0.05      33.56
在这里,第一个(无用的)循环比第二个循环快得多,因为函数不需要总是检查内部选项。
所以我的问题是,是否有可能使用
fun2()
,同时达到与使用
fun1()
获得的运行时间相同的运行时间。
tryCatch()
在这种情况下有帮助吗?

通过对100个数字进行10万次的计算,您的基准测试似乎主要是测量“从R到低级代码的转换速度”的速度,而不是基本的计算时间,因此它可能测量的是错误的

在许多情况下,R的最佳性能来自将问题转换为矢量化形式,例如使用嵌套的ifelse(或我的首选项,
dplyr::case\u when
)。(以下是我最喜欢的解释。)

在您的示例中,
fun1
的转换速度更快(毫不奇怪),但如果在较长的数据集上运行矢量化计算,则性能很快就会变得非常类似于
fun2
,对于n=100k或更大的数据集,性能基本相同。您可以看到,这两个函数对于小批量都是低效的,因为大部分时间都花在转换和计算上

有关更多建议,请查看以下内容:

库(tidyverse)
图书馆(微基准)

运行范围``fun3=函数(x,type=c(“a”,“b”,“c”,“d”,“e”,“f”){if(type==“e”){v=sqrt(x)}如何``type==“e”与fun1做的一样{if(type==“a”){v=mean(x)}if(type==“b”){v=median(x)}if(type==“c”){v=var(x)}if(type==“d”){v=sd(x)}if(type==“f)返回值}v}“我认为这几乎和乐趣1一样快,几乎和乐趣2一样有用。谢谢你的想法!那肯定会很有趣。但是,只有在使用type==“e”时,它才适合。因此,没有保持功能的灵活性,这是我的一个缺点。。
library(tidyverse)
library(microbenchmark)
run_ranges <- function(n) {
  x = rexp(n)
  summary(microbenchmark(fun1(x), fun2(x, "e"), unit = "ns", times = 1000))
}
ranges <- 10 ^ c(1:6)
sum_table <- tibble(ranges = rep(ranges, each = 2)) %>%
  bind_cols(results = map_dfr(ranges, run_ranges))
ggplot(sum_table, aes(x = ranges, y = mean/ranges, color = expr)) +
  geom_line() +
  scale_x_log10(name = "#s per run", labels = scales::comma) +
  scale_y_continuous(name = "ns per calculation", labels = scales::comma)