快速处理模拟中的规则 [英] Fast handling of rules in a simulation

查看:123
本文介绍了快速处理模拟中的规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果离散事件模拟中只有几个规则,那么这并不重要,但是如果有很多规则并且它们可以互相干扰,则您可能希望跟踪它们的哪个"和哪里"使用.

If you only have a few rules in a discrete event simulation this is not critical but if you have a lot of them and they can interfere with each other and you may want to track the "which" and "where" they are used.

  • 有人知道如何像原始函数一样快速地获取下面的代码吗?
  • 是否有比eval(parse(...)更好的选择?
  • Does anybody know how to get the code below as fast as the original function?
  • Are there better options than eval(parse(...)?

这是一个简单的示例,显示我将速度降低了100 .假设您运行了一个模拟,其中一个(许多规则中)是:选择时间少于5的状态:

Here is an simple example which shows that I loose a factor 100 in speed. Assume you run a simulation and one (of many rules) is: Select the states with time less 5:

> a <- rnorm(100, 50, 10)
> print(summary(microbenchmark::microbenchmark(a[a < 5], times = 1000L, unit = "us")))
   expr  min   lq     mean median   uq    max neval
a[a < 5] 0.76 1.14 1.266745  1.141 1.52 11.404  1000

myfun <- function(a0) {
  return(eval(parse(text = myrule)))
}

> myrule <- "a < a0" # The rule could be read from a file.
print(summary(microbenchmark::microbenchmark(a[myfun(5)], times = 1000L, unit = "us")))
    expr    min      lq     mean  median      uq     max neval
a[myfun(5)] 137.61 140.271 145.6047 141.411 142.932 343.644  1000

注意:我认为我不需要额外的 rete包,可以有效地进行簿记.但是,如果还有其他意见,请告诉我...

Note: I don't think that I need an extra rete package which can do the book keeping efficiently. But if there are other opinions, let me know...

推荐答案

让我们对此进行配置:

Rprof()
for (i in 1:1e4) a[myfun(5)]
Rprof(NULL)
summaryRprof()

#$by.self
#             self.time self.pct total.time total.pct
#"parse"           0.36    69.23       0.48     92.31
#"structure"       0.04     7.69       0.06     11.54
#"myfun"           0.02     3.85       0.52    100.00
#"eval"            0.02     3.85       0.50     96.15
#"stopifnot"       0.02     3.85       0.06     11.54
#"%in%"            0.02     3.85       0.02      3.85
#"anyNA"           0.02     3.85       0.02      3.85
#"sys.parent"      0.02     3.85       0.02      3.85
#
#$by.total
#               total.time total.pct self.time self.pct
#"myfun"              0.52    100.00      0.02     3.85
#"eval"               0.50     96.15      0.02     3.85
#"parse"              0.48     92.31      0.36    69.23
#"srcfilecopy"        0.12     23.08      0.00     0.00
#"structure"          0.06     11.54      0.04     7.69
#"stopifnot"          0.06     11.54      0.02     3.85
#".POSIXct"           0.06     11.54      0.00     0.00
#"Sys.time"           0.06     11.54      0.00     0.00
#"%in%"               0.02      3.85      0.02     3.85
#"anyNA"              0.02      3.85      0.02     3.85
#"sys.parent"         0.02      3.85      0.02     3.85
#"match.call"         0.02      3.85      0.00     0.00
#"sys.function"       0.02      3.85      0.00     0.00

大部分时间都用在parse中.我们可以使用基准进行确认:

Most of the time is spent in parse. We can confirm this with a benchmark:

microbenchmark(a[myfun(5)], times = 1000L, unit = "us")
#Unit: microseconds
#        expr    min     lq     mean median     uq     max neval
# a[myfun(5)] 67.347 69.141 72.12806 69.909 70.933 160.303  1000

a0 <- 5
microbenchmark(parse(text = myrule), times = 1000L, unit = "us")
#Unit: microseconds
#                 expr    min     lq     mean median     uq     max neval
# parse(text = myrule) 62.483 64.275 64.99432 64.787 65.299 132.903  1000

如果从文件中以文本形式读取规则非常困难,那么我认为没有办法加快速度.当然,您不应该重复解析相同的规则,但现在我假设您是这样.

If reading the rules as text from a file is a hard requirement, I don't think there is a way to speed this up. Of course, you should not parse the same rule repeatedly, but I assume you now that.

根据评论进行编辑以提供更多说明:

您应该将规则存储为带引号的表达式(例如,如果需要将其作为文件使用,请使用saveRDS列表):

You should store your rules as quoted expressions (e.g., in a list using saveRDS if you need them as a file):

myrule1 <- quote(a < a0)
myfun1 <- function(rule, a, a0) {eval(rule)}

microbenchmark(a[myfun1(myrule1, a, 30)], times = 1000L, unit = "us")
#Unit: microseconds
#                      expr   min    lq     mean median    uq    max neval
# a[myfun1(myrule1, a, 30)] 1.792 2.049 2.286815  2.304 2.305 30.217  1000

为方便起见,您可以将表达式列表设为S3对象,并为其创建漂亮的print方法,以便获得更好的概览.

For convenience, you could then make that list of expressions an S3 object and create a nice print method for it in order to get a better overview.

这篇关于快速处理模拟中的规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆