在R中遇到“内存未映射”错误导致的段错误

36
我在我们的集群上运行一些R脚本遇到了问题。问题突然出现(所有脚本都正常工作,但有一天它们开始出现“caught segfault”错误)。我无法提供可重现的代码,因为即使是在我的电脑上也无法重现该错误-它只会在集群上发生。我还使用相同的代码处理两组数据-一组数据相当小且可以正常运行,另一组数据使用更大的数据框架(约1000万行),在某些点处崩溃。我仅使用CRAN存储库中的软件包; R和所有软件包应该是最新的。错误出现在完全不相关的操作中,请参见以下示例:
会话信息:
R version 3.4.3 (2017-11-30)
Platform: x86_64-redhat-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

将变量写入NetCDF文件
# code snippet
library(ncdf4)
library(reshape2)

input <- read.csv("input_file.csv")
species <- "no2"
dimX <- ncdim_def(name="x", units = "m", vals = unique(input$x), unlim = FALSE)
dimY <- ncdim_def(name="y", units = "m", vals = unique(input$y), unlim = FALSE)
dimTime <- ncdim_def(name = "time", units = "hours", unlim = TRUE)

varOutput <- ncvar_def(name = species, units = "ug/m3",
                dim = list(dimX, dimY, dimTime), missval = -9999, longname = species)

nc_file <- nc_create(filename = "outFile.nc", vars = list(varOutput), force_v4 = T)

ncvar_put(nc = nc_file, varid = species, vals = acast(input, x~y), start = c(1,1,1),
      count = c(length(unique(input$x)), length(unique(input$y)), 1))

目前,我遇到了以下错误:

 *** caught segfault ***
address 0x2b607cac2000, cause 'memory not mapped'

Traceback:
 1: id(rev(ids), drop = FALSE)
 2: cast(data, formula, fun.aggregate, ..., subset = subset, fill = fill,     drop = drop, value.var = value.var)
 3: acast(result, x ~ y)
 4: ncvar_put(nc = nc_file, varid = species, vals = acast(result, x ~     y), start = c(1, 1), count = c(length(unique(result$x)),     length(unique(result$y))))
An irrecoverable exception occurred. R is aborting now ...
/opt/sge/default/spool/node10/job_scripts/122270: line 3: 13959 Segmentation fault      (core dumped)

并行计算的复杂代码

 *** caught segfault ***
address 0x330d39b40, cause 'memory not mapped'

Traceback:
 1: .Call(gstat_fit_variogram, as.integer(fit.method), as.integer(fit.sills),     as.integer(fit.ranges))
 2: fit.variogram(experimental_variogram, model = vgm(psill = psill,     model = model, range = range, nugget = nugget, kappa = kappa),     fit.ranges = c(fit_range), fit.sills = c(fit_nugget, fit_sill),     debug.level = 0)
 3: doTryCatch(return(expr), name, parentenv, handler)
 4: tryCatchOne(expr, names, parentenv, handlers[[1L]])
 5: tryCatchList(expr, classes, parentenv, handlers)
 6: tryCatch(expr, error = function(e) {    call <- conditionCall(e)          if (!is.null(call)) {        if (identical(call[[1L]], quote(doTryCatch)))             call <- sys.call(-4L)        dcall <- deparse(call)[1L]        prefix <- paste("Error in", dcall, ": ")        LONG <- 75L        msg <- conditionMessage(e)        sm <- strsplit(msg, "\n")[[1L]]        w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w")        if (is.na(w))             w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L],                 type = "b")        if (w > LONG)             prefix <- paste0(prefix, "\n  ")    }    else prefix <- "Error : "    msg <- paste0(prefix, conditionMessage(e), "\n")    .Internal(seterrmessage(msg[1L]))    if (!silent && identical(getOption("show.error.messages"),         TRUE)) {        cat(msg, file = outFile)        .Internal(printDeferredWarnings())    }    invisible(structure(msg, class = "try-error", condition = e))})
 7: try(fit.variogram(experimental_variogram, model = vgm(psill = psill,     model = model, range = range, nugget = nugget, kappa = kappa),     fit.ranges = c(fit_range), fit.sills = c(fit_nugget, fit_sill),     debug.level = 0), TRUE)
 8: getModel(initial_sill - initial_nugget, m, initial_range, k,     initial_nugget, fit_range, fit_sill, fit_nugget, verbose = verbose)
 9: autofitVariogram(lmResids ~ 1, obsDf, model = "Mat", kappa = c(0.05,     seq(0.2, 2, 0.1), 3, 5, 10, 15), fix.values = c(NA, NA, NA),     start_vals = c(NA, NA, NA), verbose = F)
10: main_us(obsDf[obsDf$class == "rural" | obsDf$class == "rural-nearcity" |     obsDf$class == "rural-regional" | obsDf$class == "rural-remote",     ], grd_alt, grd_pop, lm_us, fitvar_us, logTransform, plots,     "RuralSt", period, preds)
11: doTryCatch(return(expr), name, parentenv, handler)
12: tryCatchOne(expr, names, parentenv, handlers[[1L]])
13: tryCatchList(expr, classes, parentenv, handlers)
14: tryCatch(main_us(obsDf[obsDf$class == "rural" | obsDf$class ==     "rural-nearcity" | obsDf$class == "rural-regional" | obsDf$class ==     "rural-remote", ], grd_alt, grd_pop, lm_us, fitvar_us, logTransform,     plots, "RuralSt", period, preds), error = function(e) e)
15: eval(.doSnowGlobals$expr, envir = .doSnowGlobals$exportenv)
16: eval(.doSnowGlobals$expr, envir = .doSnowGlobals$exportenv)
17: doTryCatch(return(expr), name, parentenv, handler)
18: tryCatchOne(expr, names, parentenv, handlers[[1L]])
19: tryCatchList(expr, classes, parentenv, handlers)
20: tryCatch(eval(.doSnowGlobals$expr, envir = .doSnowGlobals$exportenv),     error = function(e) e)
21: (function (args) {    lapply(names(args), function(n) assign(n, args[[n]], pos = .doSnowGlobals$exportenv))    tryCatch(eval(.doSnowGlobals$expr, envir = .doSnowGlobals$exportenv),         error = function(e) e)})(quote(list(timeIndex = 255L)))
22: do.call(msg$data$fun, msg$data$args, quote = TRUE)
23: doTryCatch(return(expr), name, parentenv, handler)
24: tryCatchOne(expr, names, parentenv, handlers[[1L]])
25: tryCatchList(expr, classes, parentenv, handlers)
26: tryCatch(do.call(msg$data$fun, msg$data$args, quote = TRUE),     error = handler)
27: doTryCatch(return(expr), name, parentenv, handler)
28: tryCatchOne(expr, names, parentenv, handlers[[1L]])
29: tryCatchList(expr, classes, parentenv, handlers)
30: tryCatch({    msg <- recvData(master)    if (msg$type == "DONE") {        closeNode(master)        break    }    else if (msg$type == "EXEC") {        success <- TRUE        handler <- function(e) {            success <<- FALSE            structure(conditionMessage(e), class = c("snow-try-error",                 "try-error"))        }        t1 <- proc.time()        value <- tryCatch(do.call(msg$data$fun, msg$data$args,             quote = TRUE), error = handler)        t2 <- proc.time()        value <- list(type = "VALUE", value = value, success = success,             time = t2 - t1, tag = msg$data$tag)        msg <- NULL        sendData(master, value)        value <- NULL    }}, interrupt = function(e) NULL)
31: slaveLoop(makeSOCKmaster(master, port, timeout, useXDR))
32: parallel:::.slaveRSOCK()
An irrecoverable exception occurred. R is aborting now ...

这个问题可能是集群出了问题,而不是代码(或R语言)的问题吗?我不知道它是否相关,但自从一段时间以来,我们一直收到如下错误消息:

Message from syslogd@master1 at Mar  8 13:51:37 ...
 kernel:[Hardware Error]: MC4 Error (node 1): DRAM ECC error detected on the NB.

Message from syslogd@master1 at Mar  8 13:51:37 ...
 kernel:[Hardware Error]: Error Status: Corrected error, no action required.

Message from syslogd@master1 at Mar  8 13:51:37 ...
 kernel:[Hardware Error]: CPU:4 (15:2:0) MC4_STATUS[-|CE|MiscV|-|AddrV|-|-|CECC]: 0x9c08400067080a13

Message from syslogd@master1 at Mar  8 13:51:37 ...
kernel:[Hardware Error]: MC4_ADDR: 0x000000048f32b490

Message from syslogd@master1 at Mar  8 13:51:37 ...
 kernel:[Hardware Error]: cache level: L3/GEN, mem/io: MEM, mem-tx: RD, part-proc: RES (no timeout)

我尝试按照这个问题的建议,卸载并重新安装包,但没有帮助。

最好在集群中的每个系统上运行内存检查。 - Gerard H. Pille
5个回答

14

问题在于当前安装的共享库与安装R或软件包时构建的库不匹配。

今天我第一次遇到了这个错误。如下所示。我已经解决了这个问题,可以解释一下情况。

这是一个Ubuntu系统,最近从17.10升级到18.04,运行R-3.4.4。许多C和C++库被替换了,但并非所有程序都被替换。立即注意到许多程序出现分段错误。任何涉及tidyverse的都失败了。stringi包找不到与其编译的共享库。无论如何,这里的例子有点有趣,因为它发生在运行包的“R CMD check”时,至少在理论上应该是安全的。我发现解决方法是删除“RCurl”和“url”软件包并重新构建它们。

以下是症状:

* checking for file ‘kutils.gitex/DESCRIPTION’ ... OK
* preparing ‘kutils’:
* checking DESCRIPTION meta-information ... OK
* installing the package to build vignettes
* creating vignettes ... OK
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* looking to see if a ‘data/datalist’ file should be added
* re-saving image files
* building ‘kutils_1.40.tar.gz’
Warning: invalid uid value replaced by that for user 'nobody'
Warning: invalid gid value replaced by that for user 'nobody'

Run check: OK? (y or n)y
* using log directory ‘/home/pauljohn/GIT/CRMDA/software/kutils/package/kutils.Rcheck’
* using R version 3.4.4 (2018-03-15)
* using platform: x86_64-pc-linux-gnu (64-bit)
* using session charset: UTF-8
* using option ‘--as-cran’
* checking for file ‘kutils/DESCRIPTION’ ... OK
* checking extension type ... Package
* this is package ‘kutils’ version ‘1.40’
* checking CRAN incoming feasibility ...
 *** caught segfault ***
address 0x68456, cause 'memory not mapped'

Traceback:
 1: curlGetHeaders(u)
 2: doTryCatch(return(expr), name, parentenv, handler)
 3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
 4: tryCatchList(expr, classes, parentenv, handlers)
 5: tryCatch(curlGetHeaders(u), error = identity)
 6: .fetch(u)
 7: .check_http_A(u)
 8: FUN(X[[i]], ...)
 9: lapply(urls[pos], .check_http)
10: do.call(rbind, lapply(urls[pos], .check_http))
11: check_url_db(url_db_from_package_sources(dir), remote = !localOnly)
12: doTryCatch(return(expr), name, parentenv, handler)
13: tryCatchOne(expr, names, parentenv, handlers[[1L]])
14: tryCatchList(expr, classes, parentenv, handlers)
15: tryCatch(check_url_db(url_db_from_package_sources(dir), remote = !localOnly),     error = identity)
16: .check_package_CRAN_incoming(pkgdir, localOnly)
17: check_CRAN_incoming(!check_incoming_remote)
18: tools:::.check_packages()
An irrecoverable exception occurred. R is aborting now ...
Segmentation fault

那我们应该怎么做呢? - Patafikss

7

虽然这并不是一个解决问题或令人满意的答案,但我更加仔细地检查了代码,并发现在第一个示例中,使用reshape2包中的acast时会出现问题。 在这种情况下,我删除了它,因为我意识到它实际上不需要,但可以用reshape包中的reshape替换(如 另一个问题所示):reshape(input, idvar="x", timevar="y", direction="wide")[-1]

至于第二个示例,很难找到问题的确切原因,但在我的情况下,将并行计算使用的核心数设置为较小的值有所帮助 - 集群有48个核心,我只使用了15个,因为即使在此问题出现之前,R在使用所有48个核心运行代码时也会耗尽内存。当我将核心数减少到10时,它突然像以前一样开始工作了。


1
我按照您的建议减少了核心数量,这是唯一有效的方法。非常感谢! - Kim

1

除了 @pauljohn32 的回答之外,如果您使用 sourceRcpp 来源于一个 C++ 代码,例如 A.cpp,它依赖于 C++ 代码,例如 B.cppC.cpp,这些代码是针对旧/不同库编译的,也会发生这种情况。

在 Linux 中,一个简单的解决方案是在运行 sourceRcpp("A.cpp") 之前删除 B.oC.o 文件。假设您在 A.cpp 中包含了头文件,则似乎也会自动重新编译相关文件。


EDIT:为了回应Matt Nolan提出的更多细节,关于原始问题,问题很可能类似,共享库已经编译为旧版本的操作系统或不同的系统。我在这里说的是,即使您自己编写和编译了整个项目,如果您忘记清理过时的文件,仍然可能会发生这种情况。
为了给出与问题相关的比喻: 深入研究问题中引用的ncdf4包的源代码,我们在src\ncdf.c中找到以下片段。
#include <stdio.h>
#include <netcdf.h>
#include <string.h>
#include <stdlib.h>

#include <Rdefines.h>
#include <R_ext/Rdynload.h>

假设文件R_ext/Rdynload.hmicrosof-r-open项目的一部分。这是一个头文件,相应的Rdynload.c可以在这里找到。
假设ncdf4microsof-r-open都是单个项目的一部分,并且您已经编译了open/blob/master/source/src/main中的文件,其中包括生成的目标文件Rdynload.o等。然后,在编译src\ncdf.c之前,您升级了操作系统(不确定是否会导致问题),或将整个源代码(包括到目前为止创建的对象文件)复制到另一台机器上。这可能是无意中发生的。
例如,您正在进行自动同步,并且目录与另一台机器同步。然后在这台不同的机器上尝试编译和链接src\ncdf.c。编译器/链接器不会重新编译Rdynload.c,因为对象文件Rdynload.o已经存在。它将src\ncdf.c编译为src\ncdf.o,然后将其与Rdynload.o链接以构建最终可执行文件。
我在这里不是专家,但由于Rdynload可能是动态链接库,因此链接没有错误。但在运行时,由于已编译库Rdynload的对象代码与ncdf的对象代码不匹配,所以会出现分段错误(?)。有更好的低级机器执行知识的人可以在这里纠正我。
解决方案是清除所有对象文件,即所有源目录中扩展名为*.o的文件,并让编译器从头开始重新编译所有内容。扩展名*.o假定您在Linux机器上。其他操作系统可能使用不同的扩展名。
如果涉及到你不拥有的项目,也许解决方案是重新安装相关库(假设它们没有预编译,在新机器上安装时需要重新编译)。

请您能否举些与问题直接相关的例子来扩展说明一下?例如,B.o和C.o是什么?(如果对您来说这很明显,那我道歉) - Matt Nolan
1
@MattNolan,添加了更多细节。 - passerby51

0
对我来说,问题在于引号类型不一致。我使用了一个,但是R需要一个"。修复这个问题解决了这个问题。

-5

强烈建议清理工作区,很可能是核心问题:

unlink(".RData")


你能否澄清一下我应该在什么时候清理工作区?我从不保存我的工作区。我使用终端运行脚本,命令为 R --no-save < script.R - Janina
你应该能够在终端上完成这个任务。 - ecp
抱歉,这个程序完全没用……但我认为我已经追踪到了问题所在的reshape2包,我会进一步调查。 - Janina
1
段错误“根据定义”是联系软件包维护者的原因。 - IRTFM
2
即使问题无法重现,我是否应该提交@42?对于第二个例子,在我通过减少并行计算的核心数来解决问题的情况下,我应该联系哪个软件包的维护者? :-) - Janina
在我的情况下(使用BLINK或rMVP软件包),这很有帮助。看起来确实是.RData引起了这个问题。 - boczniak767

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接