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+ 次瀏覽

啟動您的 職業生涯

透過完成課程獲得認證

開始
廣告
© . All rights reserved.