有没有办法在xts中使用period.apply和doParallel和foreach?

有没有办法在xts中使用period.apply和doParallel和foreach?,r,foreach,parallel-processing,xts,doparallel,R,Foreach,Parallel Processing,Xts,Doparallel,我想并行化R中的period.apply函数,我正试图将doParallel与Foreach一起使用,但我不知道如何实现这个函数。我使用的数据是一个带有日期-时间索引和变量值的xts对象,我要做的是每5秒计算一次数据的平均值: VAR 2018-01-01 00:00:00 1945.054 2018-01-01 00:00:02 1944.940 2018-01

我想并行化R中的period.apply函数,我正试图将
doParallel
Foreach
一起使用,但我不知道如何实现这个函数。我使用的数据是一个带有日期-时间索引和变量值的
xts
对象,我要做的是每5秒计算一次数据的平均值:

                                     VAR
2018-01-01 00:00:00                1945.054
2018-01-01 00:00:02                1944.940
2018-01-01 00:00:05                1945.061
2018-01-01 00:00:07                1945.255
2018-01-01 00:00:10                1945.007
2018-01-01 00:00:12                1944.995
下面是我编写的代码示例,但它不起作用:

库(xts)
图书馆(双平行)
图书馆(foreach)

cores您是否在一些简单的数据集上尝试过您的代码?因为一旦我让它运行起来,它就多次完成所有工作(在
x
中,每行一次)。此外,如果您尝试并行化工作,通常最好让“工作者”在发送数据之前尽可能多地完成工作。在您的代码中,有两个连续的
foreach
调用,这会导致额外的通信开销

我的方法是这样的:

  • xts
    对象拆分为
    N
    垃圾,确保以5秒间隔之一拆分
  • 让每个工人为一个区块完成所有工作
  • 结合结果。如何选择
    N
    由于步骤1使用了
    split.xts
    ,因此每个区块的5s间隔数相同。然而,要完成的工作量(可能)更多地取决于数据点的数量,而不是5s间隔的数量。因此,如果这些块之间的点分布不均匀,那么使用更多的块以及一些负载平衡可能是有意义的。如果点的分布是均匀的,则将
    N
    尽可能大以最小化通信开销是有意义的。这里我采用后一种方法,即将
    N
    设置为等于核心数

    现在,让我们生成一些示例数据并应用您的工作解决方案:

    library(xts)
    x <- xts(x = runif(100),
             order.by = as.POSIXct("2018-01-01") + 0:99)
    
    ends <- endpoints(x,"secs",5)
    m <- period.apply(x, ends, mean)
    index(m) <- trunc(index(m),"secs")
    
    接下来,我将
    xts
    对象拆分为
    xts
    对象列表,每个对象的长度大致相同:

    split_x <- split(x, f = "secs", k = 5 * k)
    
    万岁,结果是一样的:

    all.equal(m, m2)
    #> [1] TRUE
    

    我对这个问题中演示的
    period.apply()
    的性能感到非常沮丧。我的抑郁症成了一种使它更快的困扰。所以我用C重写了它。下面是一个使用它并显示性能改进的示例

    library(xts)  # need the GitHub development version
    period_apply <- xts:::period_apply  # not exported
    
    set.seed(21)
    x <- .xts(rnorm(1e7), 1:1e7)
    e <- endpoints(x, "seconds", 5)
    
    system.time(y <- period.apply(x, e, sum))  # current version
    #    user  system elapsed 
    #  77.904   0.368  78.462 
    system.time(z <- period_apply(x, e, sum))  # new C version
    #    user  system elapsed 
    #  15.468   0.232  15.741
    all.equal(y, z)
    # [1] TRUE
    
    library(xts)#需要GitHub开发版本
    
    period\u apply读者不清楚
    period.apply()
    是“xts”中的一个函数-请使用
    library(xts)
    进行更新。关于“不起作用”,您是否收到错误消息,或者它给出了错误的结果,或者它运行得更快?执行时间太长,我应该停止执行。@Riverarodrigoa您的方法是将任务分成(大致)N/5个作业,每个作业只处理几行,其中N是您拥有的数据行数。更有效的方法是设置8个作业,每个作业处理N/8行。我知道拉尔夫的回答就是这样。非常感谢!这解决了我的问题。现在它的运行速度快了3倍,以前没有并行化,现在是27s,现在是8s。你知道这段时间是否可以减少更多吗?@Riverarodrigoa你有多少(真实)内核?实际数据集有多大?在这8秒钟内,所有的岩芯都是100%的吗?或者,在活动岩芯较少的情况下,是否存在(更长的)拉伸?很抱歉延迟,我必须处理的数据集大约是120 000 000个观测值,现在我处理的样本是1028279 obs(8秒钟对应于此样本)。是的,我电脑的所有核心都在这8秒内100%工作。@Riverarodrigoa你有多少核心?无论如何,你可以试一试。为了简单起见,首先没有并行性。虽然RcppRoll是一个非常好的软件包,但我相信它只会滚动(重叠)窗口
    period.apply()
    用于非重叠窗口。
    m2 <- foreach(x = split_x, .packages = c("xts"), .combine = c) %dopar% {
        ends <- endpoints(x,"secs",5)
        m <- period.apply(x, ends, mean)
        index(m) <- trunc(index(m),"secs")
        m
    }
    stopCluster(cluster)
    
    all.equal(m, m2)
    #> [1] TRUE
    
    library(xts)  # need the GitHub development version
    period_apply <- xts:::period_apply  # not exported
    
    set.seed(21)
    x <- .xts(rnorm(1e7), 1:1e7)
    e <- endpoints(x, "seconds", 5)
    
    system.time(y <- period.apply(x, e, sum))  # current version
    #    user  system elapsed 
    #  77.904   0.368  78.462 
    system.time(z <- period_apply(x, e, sum))  # new C version
    #    user  system elapsed 
    #  15.468   0.232  15.741
    all.equal(y, z)
    # [1] TRUE