构建 R 包:“找到 'rand',可能来自 'rand' (C)”检查包时注意

Posted

技术标签:

【中文标题】构建 R 包:“找到 \'rand\',可能来自 \'rand\' (C)”检查包时注意【英文标题】:Building R package: "Found 'rand', possibly from 'rand' (C)" NOTE when checking package构建 R 包:“找到 'rand',可能来自 'rand' (C)”检查包时注意 【发布时间】:2014-11-02 10:10:11 【问题描述】:

我正在构建一个包含 C++ 代码的 R 包。其中,我使用 rand() 函数。该软件包在我的 Linux 机器上检查和构建时没有任何异常。但是,当我尝试使用 Windows builder 检查 Windows 构建时,我收到以下警告:

* checking compiled code ... NOTE
File 'tagcloud/libs/i386/tagcloud.dll':
  Found 'rand', possibly from 'rand' (C)
    Object: 'overlap.o'
  Found 'srand', possibly from 'srand' (C)
    Object: 'overlap.o'
File 'tagcloud/libs/x64/tagcloud.dll':
  Found 'rand', possibly from 'rand' (C)
    Object: 'overlap.o'
  Found 'srand', possibly from 'srand' (C)
    Object: 'overlap.o'

Compiled code should not call entry points which might terminate R nor
write to stdout/stderr instead of to the console, nor the C RNG.

下面是一些示例代码:

#include "Rcpp.h"
#include <cstdlib>
#include <time.h>

using namespace Rcpp;

RcppExport SEXP test(  ) 
  double x ;
  srand( (unsigned) time(NULL) );
  x = rand();
  return( 1 );

我不明白有关 rand() 的抱怨。我也没有看到我在代码中的哪个位置“调用可能终止 R 的入口点”或“写入 stdout/stderr”,但是,如果我删除对 rand/srand 的调用,这条消息就会消失。

Google 在其检查日志中显示了许多似乎具有相同注释的软件包。你看到了吗?有没有办法摆脱它?

【问题讨论】:

我认为这是你应该担心的最后一个——编译后的代码不应该调用 C RNG。 我很困惑。为什么我不应该使用 C 随机数生成器?我应该改用什么? 我不知道你第一个问题的答案,但可能与种子管理有关,但Rcpp has full access to R style p/d/r/q distributional functions via syntactic sugar。 很好,但我不需要那个;我没有做任何统计计算,我只需要一点随机性来生成视觉标签云。 好吧,你没有使用以这种方式生成的随机数进行统计计算。 【参考方案1】:

cmets 中的讨论已经达到了关键点:R(最近)抱怨使用 rand()srand()。 [请注意,这是一个 R 问题,而不是 Rcpp 问题。 ]

原因是在过去的某些时候,rand() 在某些系统上确实很糟糕。所以警告仍然存在。参见例如来自this page at cppreference.com:

我们无法保证生成的随机序列的质量。过去,rand() 的一些实现在产生的序列的随机性、分布和周期方面存在严重缺陷(在一个众所周知的例子中,低位位在调用之间简单地在 1 和 0 之间交替)。

rand() 不推荐用于严重的随机数生成需求,例如密码学。建议使用 C++11 的随机数生成工具来替换 rand()。 (C++11 起)

对于 R 和 Rcpp 包,您没有任何理由依赖rand(),因为R 带有几个高质量的生成器。请参阅编写 R 扩展手册如何从 C 代码访问它们,以及关于如何通过 Rcpp 从 C++ 访问它们的众多 Rcpp 示例(此处为 Rcpp 文档、Rcpp Gallery)。

【讨论】:

R-devel 列表中还给了我另一个重要原因:R set.seed() 函数不会影响 C seed(),因此使用 C RNG 用户无法可靠地复制结果。也就是说,当然可能有理由依赖 C RNG - (i) 它是标准 C (ii) 当我为现有 C 程序或库构建接口时,我不想过多干预在程序的内部,并且 (iii) 它明显更快,并且对于某些目的,即使是糟糕的随机化也绰绰有余。 那是一回事。 R 的 RNG 是独立的,因此 set.seed() 不会转到 rand() - 因为你会拥有 srand()。这与使用 Boost 中的 RNG 没有什么不同。现在,如果您想要更快的 RNG,您可以简单地在 R 本身内切换或使用不同的 RNG。请参阅我的 RcppZiggurat 包,它提供更快的 N(0,1) 绘制。 具体Rcpp (gallery.rcpp.org/articles/random-number-generation),请使用runif(), rnorm(), rt()...

以上是关于构建 R 包:“找到 'rand',可能来自 'rand' (C)”检查包时注意的主要内容,如果未能解决你的问题,请参考以下文章

R基于H2O包构建深度学习模型实战

无法构建 R 包“png”Fedora 20

R使用gbm包构建gbdt模型进行回归分析实战

无法 conda 构建 R 包

R语言neuralnet包构建神经网络模型:基于乳腺癌数据集

R语言igraph 包-构建网络图