构建 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)”检查包时注意的主要内容,如果未能解决你的问题,请参考以下文章