我尝试执行网格搜索,以找到使x和y的线性组合之间的相关性最大化的系数。我的函数采用数据框架,其中每列是要测试该迭代的θ。
corr_grid_search <- function(thetas, modeling_df) {
# thetas = as.vector(thetas)
coeff1 = modeling_df$penalty1 / thetas[1]
coeff2 = modeling_df$penalty2 / thetas[2]
coeff3 = modeling_df$penalty3 / thetas[3]
coeff4 = modeling_df$penalty4 / thetas[4]
coeff5 = modeling_df$penalty5 / thetas[5]
coeff6 = modeling_df$penalty6 / thetas[6]
coeff7 = modeling_df$penalty7 / thetas[7]
coeff8 = modeling_df$penalty8 / thetas[8]
coeff9 = modeling_df$penalty9 / thetas[9]
coeff10 = modeling_df$penalty10 / thetas[10]
df = data.frame(coeff1, coeff2, coeff3, coeff4, coeff5, coeff6, coeff7, coeff8, coeff9, coeff10)
pp_1 = modeling_df$x1 / df$coeff1
pp_2 = modeling_df$x2 / df$coeff2
pp_3 = modeling_df$x3 / df$coeff3
pp_4 = modeling_df$x4 / df$coeff4
pp_5 = modeling_df$x5 / df$coeff5
pp_6 = modeling_df$x6 / df$coeff6
pp_7 = modeling_df$x7 / df$coeff7
pp_8 = modeling_df$x8 / df$coeff8
pp_9 = modeling_df$x9 / df$coeff9
pp_10 = modeling_df$x10 / df$coeff10
recip = 1/df[, c('coeff1', 'coeff2', 'coeff3',
'coeff4', 'coeff5', 'coeff6',
'coeff7', 'coeff8', 'coeff9', 'coeff10')]
recip = as.data.frame(lapply(recip, function(x) replace(x, is.infinite(x), NA)))
df = data.frame(pp_1, pp_2, pp_3, pp_4, pp_5, pp_6, pp_7,
pp_8, pp_9, pp_10)
weighted_x = rowSums(df, na.rm=T) /
rowSums(recip, na.rm=T)
cor(weighted_x[!is.na(weighted_x)],
modeling_df[!is.na(weighted_x),]$y)
}
我用lapply()运行它,如下所示:
lapply(blah, corr_grid_search, modeling_df)
但是我试图并行化它,遇到了麻烦。我尝试过的两种方法使用了parallel和future. apply库,但都没有工作:
一个二个一个一个
这两种方法都出了问题,因为它们耗时长得可怕,慢了2 - 3个数量级。我在这里做错了什么?
1条答案
按热度按时间ycl3bljg1#
并行处理并不总是比单线程快
在我的经验中,有两种常见的情况是并行处理比使用单线程慢:
1.数据量很大,在工作人员之间复制数据的成本很高。
1.分配给每个工作线程的任务足够快,以至于设置工作线程的开销会产生显著影响。
1.在工作线程之间复制数据所花费的时间比并行处理节省的时间要多
如
furrr
docs所示:记住数据必须在工作者之间来回传递是很重要的。这意味着无论您从并行化中获得了什么性能提升,都可能被移动大量数据所粉碎。例如,如果您要将大型 Dataframe 移动到工作者,并行运行模型,并返回大型模型对象,那么数据的移动可能会占用大量时间。
快速模拟
如果我们定义一个低效函数,就可以看到这样的例子。此函数计算数据框列的平均值,但不是返回单个值,而是创建一个循环使用该值的新数据框列。然后返回附加了此新列的整个数据框:
对 Dataframe 的每一列都运行此函数是个坏主意,无论是否并行。
所以,让我们尝试一下只有100行和100列的情况,看看会发生什么:
输出:
如您所见,并行作业的中值大约是单线程作业的35倍。
如果我们用1000行和1000列来尝试,结果如下:
在这里,并行运行需要175倍的时间,您可以看到我在这里只做了一次迭代-单线程迭代需要0.168秒,而并行运行需要29.4秒!
2.设置工作线程的开销可能比节省的时间更昂贵
让我们举一个更合理的例子,只返回实际的均值,而不是整个 Dataframe ,包含1000行和列。你可能会认为,现在我们没有传递大量的数据,并行处理会更快。让我们看看:
这两种方法在绝对时间上都表现得更好(两种情况下,1000行和1000列看起来就像使用愚蠢的方法时各自的100行和1000列)。
但是使用单个线程仍然要快得多,因为与相对较快的计算平均值的操作相比,设置工作线程的开销很高。
总的来说,并行作业可能不会更快,但这并不意味着代码没有按预期创建子进程。并行处理有成本也有好处。在适当的情况下,它会快很多,但如果您要复制大型数据集或创建进程来执行非常简单的计算,它可能会比单线程方法慢。