并行 R 代码在高端 EC2 实例上的运行速度比在笔记本电脑上慢得多

问题描述 投票:0回答:1

我编写了一个引导循环来生成一系列随机试验,我想稍后减少这些试验以运行回归。

我遇到的问题是,该过程在现代 i7 笔记本电脑上运行速度很快,但在相当强大的 EC2 实例(例如 c6i.4xlarge(16 个内核,32GB))上需要更长的时间。在下面提供的示例中,在我的笔记本电脑(i7-12650H、2700 Mhz、16GB)上,32 次迭代大约需要 40 秒,但在 EC2 上则接近 12 分钟。理想情况下,我想运行 300 次迭代(在我的笔记本电脑上大约 5 分钟,在 EC2 上一个小时后我们放弃了)。

我知道我的笔记本电脑上的各个核心频率提升至 3.8GHz,因此将具有更高的线性速度。但除了使用更多(或不同)的 EC2 硬件来解决该问题之外,我可以改进下面的循环代码,使 EC2 Linux 实例更高效吗

提前非常感谢! __

我提供了两个虚拟表。 df 是已知数据。 mrg 是外部刺激。

我的模拟从时间窗口中的已知事件中获取用户 ID,并模拟某些外部时间相关刺激是否与其结果一致(v1)。 v2-v17 是已知的,v20_n - v24_n 是外部的。我使用加权“随机”滚动来决定,但想法是重复使用不同的可能组合来探索更大的可能性。

在从循环返回表之前,我运行“group by”以减少行数和内存开销。

抱歉 - 很多代码,但这包括设置:

set.seed(123)
library(dplyr)
library(doParallel)
library(magrittr)
library(tidyr)

# - Create dummy data for example -|

  # Large data frame - example
  df <- data.frame(matrix(nrow=150000, ncol=20))
  colnames(df) <- c('id', 'dateFrom', 'dateTo', paste0('v', seq.int(from = 1, to = 17)))
  df$id <- seq.int(from = 1, to = nrow(df))
  df$dateFrom <- sample(seq(from = as.Date('2024/01/01'), to = as.Date('2024/01/31'), by="day"), nrow(df), replace=T)
  df$dateTo <- df$dateFrom + sample(c(0:7), nrow(df), replace=T)
  df[, grepl('v', colnames(df))] <- rbinom(nrow(df) * 17, 1, 0.05)
  
  # Data to merge
  mrg <- data.frame(matrix(nrow=120, ncol=4))
  colnames(mrg) <- c('v', 'actionDate', 'numerator', 'denominator')
  mrg$v <- c(rep('v20_n', 30), rep('v21_n', 30), rep('v22_n', 30), rep('v23_n', 30))
  mrg$actionDate <- rep(seq(from = as.Date('2024/01/01'), to = as.Date('2024/01/30'), by = "day"), 4)
  mrg$denominator <- sample(80000:120000, 120)
  mrg$numerator <- floor(mrg$denominator * runif(120, min = 0.01, max = 0.15))
  
  new <- unique(mrg$v)
# -------------------------------- |


# Simulation
  
registerDoParallel(cores=8)

system.time(
bootstrap <- foreach(x=1:32, .combine = rbind.data.frame, .packages = c('dplyr', 'magrittr', 'tidyr')) %dopar% {
  
  df_copy <- df

  for(ch in new) {
    
    sampling <- df %>%
      select(id, dateFrom, dateTo) %>%
      cross_join(mrg %>% 
                   filter(v == ch) %>% 
                   select(actionDate, numerator, denominator)
      ) %>%
      filter(actionDate >= dateFrom - 3 &
             actionDate <= dateTo
      ) %>%
      group_by(id) %>%
      summarise(numer = sum(numerator),
                denom = sum(denominator),
                avg = numer/denom,
                weight = avg * (denom / 150000 * 0.2),
                chance = rbinom(1, 1, weight)
      ) %>%
      select(id, chance) %>%
      rename(!!ch := chance) %>%
      ungroup()
    
    df_copy <- df_copy %>% 
      left_join(sampling, by = 'id')
  
  }  
  
  df_copy <- df_copy %>%
    mutate_at(vars(contains("_n")), replace_na, 0)
  
  df_copy <- df_copy %>% 
    group_by(across(c(-v1, -id, -dateFrom, -dateTo))) %>%
    dplyr::summarise(Occurrences = n(), Events = sum(v1)) %>%
    ungroup()
}

) ## Eight cores - 40 seconds elapsed on laptop
stopImplicitCluster() 
  


r amazon-ec2 parallel-processing
1个回答
0
投票

我通过将连接和过滤器移出循环解决了眼前的问题,因为这个阶段非常昂贵且无需重复。

© www.soinside.com 2019 - 2024. All rights reserved.