【问题标题】:Can't use read.table() inside foreach loop (doSMP)不能在 foreach 循环中使用 read.table() (doSMP)
【发布时间】:2026-01-15 10:55:02
【问题描述】:

我正在尝试使用 doSMP / foreach 来并行化 R 中的一些代码。

我有一个巨大的遗传数据二维矩阵 - 10,000 个观察值(行)和 300 万个变量(列)。由于内存问题,我不得不将这些数据分成 1000 个变量的块。

我想读入每个文件,做一些统计,然后将这些结果写到一个文件中。使用 for 循环很容易,但我想使用 foreach 来加速它。这就是我正在做的事情:

# load doSMP, foreach, iterators, codetools
require(doSMP)

# files i'm processing
print(filelist <- system("ls matrix1k.*.txt", T))

#initialize processes
w <- startWorkers(2)
registerDoSMP(w)

# for each file, read into memory, do some stuff, write out results.
foreach (i =  1:length(filelist)) %dopar% {
    print(i)
    file <- filelist[i]
    print(file)
    thisfile <- read.table(file,header=T) 
    # here i'll do stuff using that file
    # here i'll write out results of the stuff I do above
}

#stop processes
stopWorkers(w)

但这会导致错误:Error in { : task 2 failed - "cannot open the connection"。当我将%dopar% 更改为%do% 时,完全没有问题。

【问题讨论】:

  • 不回答您的问题,但将数据放入 NetCDF 文件(带有 ncdf 包)可以方便快捷地输入数据块;使用 scan() 而不是 read.table 会快得多。我猜想在循环之外打开文件 (?file) 可能会起作用
  • 现在仍在回答您的问题,但@Martin 建议的中途做法是在read.table 中使用colClasses 参数。这真的可以加快速度。
  • 您能提供更多细节吗? 1)它打开了一些文件,还是立即失败? 2) 你是在写不同的文件还是写一个相同的文件?

标签: r foreach parallel-processing


【解决方案1】:

在你的 foreach 循环中,你必须调用你将要使用的包。

示例:

i)

foreach (i =  1:length(filelist), .packages = "rgdal") %dopar% ......

在你的情况下,你应该调用一个包向量。

示例 2:

ii)

package.vector <- c("package.1","package.2",etc)

foreach (i =  1:length(filelist), .packages = package.vector) %dopar% ......

我建议你调用你正在使用的所有包

【讨论】:

    【解决方案2】:

    我不认为并行输入确实可以加快速度。限制因素是磁盘控制器,因此当您打开 2 个连接并读取数据时它无济于事,因为无论如何它都必须通过磁盘控制器。磁盘 IO 是一项串行作业(很遗憾),除非您有一个带有多个磁盘控制器的 RAID 阵列。并行 IO 仅适用于每台机器都有自己的磁盘的集群。

    【讨论】:

    • 理论上你是对的。然而,在实践中,使用 OP 正在使用的函数在 R 中使用特定大小的数据集(可能是因为上面提到的 cmets 中提到的效率非常低的原因),我已经看到使用并行代码显着提高了速度。