R语言NMF包调用核心异常的代码修复
我-独立
编辑于 2025年10月21日 21:28
收录于文集
共3篇

最近在整理与我自己的代码库,然后练习函数式编程。由于很早就使用Rproject的方式进行各个项目的处理与管理,在测试使用source()+指定新环境导入包含函数的R脚本后,一天内就又转换到使用Rstudio创建Rpackage devtool的R环境的方式。同时我是在我的R项目内嵌套该R包,因此项目中所有引用的函数,我可以通过ctrl+左键双击的方式,直接打开对应的R脚本文件(我搜索了一下,似乎没有任何人报告这种Rstudio中对相关文件的打开方式),便于修订与更改。

AI给的提示信息

在了解相关架构后,也是修订代码遇到的问题,就是NMF包。我不知道有多少人遇到这个问题,其在28版本的核心数量,是无论你设置什么都被强制改为2,非常恶心。很多人的做法是强制回退到25版本,但是有时候R包更新,又强制依赖更新回去,这个来来回回总不是个事。因此今天我把28的源码下载下来,然后查看了github上的20源码,也强制更新了25版本,也看了一下源码。用AI判断了一下,28版本就是强制锁定所有的核心都是2,无论你在设置全局变量'cores'的数值,还是每一个调用时设置的nmf.getOption('cores'),全部都被强制修改为2,所以无论怎么修改都是这样子。

不知道26版本开始,经过了谁的手,恶意非常重,因为他不仅仅修改了getMaxCores 函数,还修改了 setupBackend,getmaxcores修改如下所有,然后对于setupbackend,就是直接修改参数即可。 在文档中找到 if( spec > 2L ),你会看到他甚至注释了Limit number of cores to 2,真的该死呦。我是将对应的数值直接替换为了 getMaxCores(limit=T),测试后我的电脑能够跑满CPU。之前只是修改了getmaxcores,没想到还要修改setupBackend。

他还直接加了相应代码,对比图如下,真不知道他遭遇了什么,这么恨。。。。

以下是这getmaxcores几个版本的源码以及我自己的测试

```bash 28版本

getAnywhere(getMaxCores)

A single object matching ‘getMaxCores’ was found

It was found in the following places

 namespace:NMF

with value

function (limit = TRUE) 

{

  nt <- n <- parallel::detectCores()

  if (n > 2) 

    n <- 2

  if (n > 2 && isCHECK()) {

    message("# NOTE - CRAN check detected: limiting maximum number of cores [2/", 

      nt, "]")

    n <- 2L

  }

  n

}

<bytecode: 0x000001ee17366130>

<environment: namespace:NMF>

> parallel::detectCores()

[1] 32

```

25版本

```bash

library(NMF)

NMF - BioConductor layer [OK] | Shared memory capabilities [NO: windows] | Cores 31/32

Attaching package: ‘NMF’

The following object is masked from ‘package:generics’:

  fit

getAnywhere(getMaxCores)

A single object matching ‘getMaxCores’ was found

It was found in the following places

 namespace:NMF

with value

function (limit = TRUE) 

{

  nt <- n <- parallel::detectCores()

  if (limit) {

    if (!is.null(nc <- getOption("cores"))) 

      n <- nc

    else if (!is.null(nc <- nmf.getOption("cores"))) 

      n <- nc

    else if (n > 2) 

      n <- n - 1L

  }

  if (n > 2 && isCHECK()) {

    message("# NOTE - CRAN check detected: limiting maximum number of cores [2/", 

      nt, "]")

    n <- 2L

  }

  n

}

<bytecode: 0x000001ee1fef5080>

<environment: namespace:NMF>

```

以下是我用AI进行修改的代码,

```bash

#' 智能核心数管理函数(增强版)

#' 

#' @param limit 是否应用限制逻辑(默认TRUE)

#' @return 推荐的可用核心数

getMaxCores <- function(limit = TRUE) {

  # 获取系统总核心数

  nt <- n <- parallel::detectCores()

  message("检测到系统总核心数: ", nt)

   

  # 记录初始核心数

  initial_n <- n

   

  # 仅在需要限制时应用智能策略

  if (limit) {

    message("应用核心数限制策略...")

     

    # 1. 优先检查全局选项

    if (!is.null(nc <- getOption('cores'))) {

      message("→ 使用全局选项 'cores' 设置: ", nc, " 核心")

      n <- nc

    }

    # 2. 检查NMF专用选项

    else if (!is.null(nc <- nmf.getOption('cores'))) {

      message("→ 使用NMF专用选项 'cores' 设置: ", nc, " 核心")

      n <- nc

    }

    # 3. 默认策略:保留一个空闲核心

    else if (n > 2) {

      message("→ 应用默认策略: 保留1个空闲核心 (", n, " → ", n-1, ")")

      n <- n - 1L

    }

    else {

      message("→ 未应用额外限制 (核心数 ≤ 2)")

    }

  }

  else {

    message("未应用任何限制策略 (limit = FALSE)")

  }

   

  # CRAN检查处理

  cran_check <- identical(Sys.getenv("_R_CHECK_LIMIT_CORES_"), "true")

  if (cran_check) {

    message("检测到CRAN检查环境 (_R_CHECK_LIMIT_CORES_ = true)")

  }

   

  # 应用CRAN限制

  if (n > 2 && cran_check) {

    message("→ CRAN限制生效: 最大核心数限制为2 (当前: ", n, " → 2)")

    n <- 2L

  }

   

  # 输出最终结果

  if (initial_n != n) {

    message("最终核心数: ", n, " (初始: ", initial_n, ", 总核心: ", nt, ")")

  } else {

    message("最终核心数: ", n, " (未改变)")

  }

   

  return(n)

}

```

文件路径是NMF,R,parallel.R,getMaxCores,如果不想麻烦,可以直接用25版本的源码替换,然后再添加回压缩文件,最后使用压缩包的方式进行安装。MD5检测肯定不会过,如果太在意就不要改了,可以去尝试用25版本的parallel.R替换,然后复制对应的MD5码。

修复完成后的调用