R语言并行编程


并行编程是一种软件开发实践,它涉及将计算或任务分解成更小的部分,这些部分可以并发或并行执行。通过利用计算机或集群中的多个处理器或核心,并行编程可以帮助提高 R 代码的性能和效率。并行编程的主要概念是,如果使用单个处理器在一个操作中需要 S 秒,那么当涉及 N 个处理器时,它应该能够在 S / N 秒内执行。

R语言并行编程的必要性

大多数情况下,R 代码在单个核心上运行速度很快。但有时操作可能会:

  • 消耗过多的 CPU 时间。

  • 占用过多的内存空间。

  • 读取或写入磁盘花费的时间过长。

  • 传输时间过长。

隐式并行性

R 提供了强大的库支持。有时,我们甚至在不知不觉中就进行了并行编程。这是因为现在的 R 提供了具有内置并行性的库,我们可以在后台使用它们。这种隐式并行性提高了我们的编程效率。但是了解实际发生的事情(即使是在幕后)也是很好的。

让我们考虑一个隐式并行性的例子

并行基本线性代数子程序 (BLAS)

基本线性代数子程序 (BLAS) 库是为特定类型的 CPU 在 R 中自定义编码的,目的是利用芯片组架构的优势。拥有优化的 BLAS 总是很有益的,因为它可以提高执行性能。

容易并行化的并行性

容易并行化的并行性是统计学和数据科学中的一种常见方法。它能够解决数据科学和统计学中的许多问题。在这种类型的并行性中,问题被分成多个独立的部分,并且所有部分都被同时执行,因为它们彼此之间没有任何联系。

语法

可以使用 `lapply()` 函数在 R 中实现容易并行化的并行性。此函数具有以下语法:

lapply(list, function)

示例

它接受一个列表和一个函数。它返回一个列表,其长度等于输入列表。让我们考虑一个程序来说明此函数的工作原理:

# Creating a list
myList <- list(data1 = 1:5, data2 = 10:15)

# Use lapply() function and
# calculate the mean
lapply(myList, mean)

输出

$data1
[1] 3

$data2
[1] 12.5

正如您在输出中看到的,已经显示了列表元素的平均值。

`lapply()` 函数的工作方式类似于循环,我们迭代列表的每个元素并将函数应用于它。

现在让我们更深入地了解实际发生的情况:

我们逐一迭代每个元素,这就是为什么当我们将函数应用于列表的单个元素时,其他元素只是在内存中空闲。我们可以在 R 中并行化这件事。主要思想是将列表对象分成多个处理器,然后我们可以同时将函数应用于列表的所有子集。

因此,我们可以使用以下步骤实现并行性:

  • 将列表分解到多个处理器中。

  • 将提供的函数克隆到多个处理器中。

  • 同时将函数应用于多个核心。

  • 将来自多个核心的结果组合到单个列表中。

  • 显示结果。

R中的并行编程包

R 中的 `parallel` 包随 R 的安装一起提供。此包结合了 R 中的两个包:`snow` 和 `multicore`。

`parallel` 包专门用于以并行方式将任务交付给每个核心。具体来说,它是通过 `mclapply()` 函数执行的。`mclapply()` 函数类似于 `lapply`,但前者能够将任务分配给多个处理器。`mclapply()` 函数还收集函数调用的结果,将它们组合起来,并将其结果作为长度与原始列表相同的列表返回。请注意,R 允许我们使用 `detectCores()` 函数,我们可以用它来获取系统中存在的核心数量。

让我们考虑以下程序,它说明了 `mclapply()` 函数的工作原理:

注意 - 请注意,`mc.cores` 的值大于 1 仅在非 Windows 操作系统中有效。因此,以下代码是在 Windows 之外的操作系统中执行的。

示例

# Import library
library(parallel)
library(MASS)

# Creating a list
myList <- list(data1 = 1:10000000, data2 = 1:100000000)


cat("The estimated time using lapply() function:
") # Calculate the time taken using lapply system.time( results <- lapply(myList, mean) ) # Get the number of cores numberOfCores <- detectCores() cat("The estimated time using clapply() function:
") # Calculate the time taken using lapply() using mclapply() system.time( results <- mclapply(myList, mean, mc.cores = numberOfCores) )

输出

The estimated time using lapply() function:
   user  system elapsed 
   0.40    0.00    0.43 

The estimated time using clapply() function:
   user  system elapsed 
   0.12    0.00    0.17 

您可以在输出中看到使用 `apply()` 和 `mcapply()` 函数时的差异。

使用 foreach 和 doParallel 包进行并行编程

现在我们将看到如何使用 R 中的 `foreach` 库实现并行编程。但在进入正题之前,让我们看看 R 中基本的 for 循环是如何工作的:

示例

# Iterate using the for loop from 1 to 5
# And print the square of each number
for (data in 1:5) {
   print(data * data)
}

输出

[1] 1
[1] 4
[1] 9
[1] 16
[1] 25

正如您在输出中看到的,从 1 到 5 的每个数字的平方都显示在控制台上。

Foreach 包

现在让我们谈谈 `foreach` 包和方法。`foreach` 包为我们提供了 `foreach()` 方法,我们可以用它轻松实现并行编程。

语法

如果您尚未在系统中安装 `foreach` 库,请在 CRAN 的终端中使用以下命令:

install.packages("foreach")

`foreach` 方法类似于基本的 for 循环方法,但前者使用 `%do%` 运算符,这意味着运行特定类型的表达式。两者在返回数据结构方面也有所不同。

示例

考虑以下程序,它说明了 `foreach` 方法的工作原理:

# Import foreach library
library(foreach)

# Iterate using the foreach loop from 1 to 5
# And print the square of each number
foreach (data=1:5) %do%  {
   data * data
}

输出

[[1]]
[1] 1

[[2]]
[1] 4

[[3]]
[1] 9

[[4]]
[1] 16

[[5]]
[1] 25

正如您在输出中看到的,从 1 到 5 的每个数字的平方都显示在控制台上。

doParallel 包

`doParallel` 包为我们提供了 `%dopar%` 运算符,我们可以将其与 `foreach` 一起使用。通过将此运算符与 `foreach` 一起使用,我们将能够为每次迭代使用不同的处理核心。您可以使用 CRAN 中的以下命令下载“doParallel”包:

install.packages("doParallel")

示例

现在让我们考虑以下程序,它演示了 `foreach` 方法以及 `%dopar%` 运算符的工作原理:

# Import foreach library
library(foreach)
library(doParallel)
library(MASS)

# Get the total number of cores
numOfCores <- detectCores()

# Register all the cores
registerDoParallel(numberOfCores)

# Iterate using the for loop from 1 to 5
# And print the square of each number
# Using parallelism
foreach (data=1:5) %dopar%  {
   print(data * data)
}

输出

[[1]]
[1] 1

[[2]]
[1] 4

[[3]]
[1] 9

[[4]]
[1] 16

[[5]]
[1] 25

从 1 到 5 的每个数字的平方都显示在控制台上。

结论

在本教程中,我们讨论了 R 中的并行编程。我们讨论了 `foreach` 和 `doParallel` 等库,可以使用它们在 R 中实现并行编程。我们还了解了 `mcapply()` 等函数的工作原理。并行编程是任何编程语言最重要的概念之一,我相信本教程肯定有助于在数据科学领域获得良好的知识。

更新于:2023年1月17日

4K+ 次浏览

启动您的 职业生涯

通过完成课程获得认证

开始
广告