R如何在Linux上获得R可用的内存量

R如何在Linux上获得R可用的内存量,r,linux,R,Linux,我知道,我可以通过以下方式查询/proc/meminfo: memfree <- tryCatch( as.numeric(system("/usr/bin/awk '/MemAvailable/ {print $2}' /proc/meminfo", intern=TRUE))*1024, error = function(e) 0) memfree这是一个有趣的问题,我认为您可以通过使用Rcpp来解决它。下面是一个可能的解决方案(代码中的注释): 编辑:这里有一个稍微

我知道,我可以通过以下方式查询
/proc/meminfo

memfree <- tryCatch(
    as.numeric(system("/usr/bin/awk '/MemAvailable/ {print $2}' /proc/meminfo", intern=TRUE))*1024,
    error = function(e) 0)

memfree这是一个有趣的问题,我认为您可以通过使用
Rcpp
来解决它。下面是一个可能的解决方案(代码中的注释):

编辑:这里有一个稍微简单的单文件版本,简化为所需的标题,并使用普通C++:

#include <Rcpp.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/sysinfo.h>

// [[Rcpp::export]]
long mem_used_bytes(int pid) {
    long rss = 0L;
    FILE* fp = NULL;
    char filepath[128];
    snprintf(filepath, 127, "/proc/%d/statm", pid);
    if ( (fp = fopen(filepath, "r" )) == NULL )
        return (size_t)0L;      /* Can't open? */
    if ( fscanf( fp, "%*s%ld", &rss ) != 1 ) {
        fclose( fp );
        return (size_t)0L;      /* Can't read? */
    }
    fclose( fp );
    return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
}

// [[Rcpp::export]]
long mem_limit_bytes(int pid_int) {
    long res;
    struct rlimit tmp;
    pid_t pid=pid_int;
    prlimit(pid, RLIMIT_AS, NULL, &tmp);
    if (tmp.rlim_cur==-1L) {
        //there is no memory limit for the current process (should be default)
        Rcpp::Rcout << "No limit detected\n";
        struct sysinfo tmp2;
        sysinfo(&tmp2);
        res = tmp2.mem_unit * tmp2.totalram;
    } else {
        //memory limit set
        Rcpp::Rcout << "Limit detected\n";
        res=tmp.rlim_cur;
    }
    return res;
}

/*** R
## memory without limit set; returns total system memory
mem_limit_bytes(Sys.getpid())/1e6

## try out the `mem_used_bytes` function
## first some garbage collection
gc()
old_mem_mb <- mem_used_bytes(Sys.getpid())/1e6

## allocate a matrix with approx 800MB
NN <- 1e4
expected_memory_mb <- NN^2 * 8 / 1e6
A <- matrix(runif(NN**2),NN,NN)

##garbage collection, again
gc()

## query used memory again
new_mem_mb <- mem_used_bytes(Sys.getpid())/1e6

## the following value should be close to 1
(new_mem_mb - old_mem_mb)/expected_memory_mb

*/
#包括
#包括
#包括
#包括
//[[Rcpp::导出]]
长内存已用字节(整数pid){
长rss=0L;
FILE*fp=NULL;
char文件路径[128];
snprintf(文件路径,127,“/proc/%d/statm”,pid);
if((fp=fopen(文件路径,“r”))==NULL)
退货(尺码)0L;/*无法打开*/
如果(fscanf(fp,%*s%ld,&rss)!=1){
fclose(fp);
返回(大小)0L;/*无法读取*/
}
fclose(fp);
返回(大小)rss*(大小)sysconf(_SC_PAGESIZE);
}
//[[Rcpp::导出]]
长内存限制字节(整型pid整型){
长余弦;
结构限制tmp;
pid_t pid=pid_int;
prlimit(pid、RLIMIT_AS、NULL和tmp);
如果(tmp.rlim_cur==-1L){
//当前进程没有内存限制(应为默认值)

Rcpp::Rcout在Linux上,R将获取它所能获取的所有内存。@HongOoi这是否意味着,Linux上的R基本上不知道内存限制?不确定我是否真的理解你的问题,因为我不是你所描述问题的专家,但我通过
sar-R 1
独立于R监控可用内存,然后通过管道输出
sar-r1
命令定期执行(每秒一次)通过一个bash脚本。我不使用R读取输出文件,整个过程有一点滞后,但也许类似的东西可以帮助您解决…@cryo111这种技术肯定可以解决第一个问题。但是当R进程有内存限制时,它并不能解决问题(我认为这在Linux上是一个很好的实践)只是看了一下你的bug报告。有趣的是,我进行此监视的全部原因与你的完全相同。你在bug报告中提到的包非常有趣,也可能对我有所帮助。但我认为你在bug报告中要求的是R如何管理的核心,并且不会在任何时候实现很好的回答。我会编辑一点。我们可以在Rcpp画廊发一篇帖子吗?@DirkEddelbuettel谢谢(也谢谢编辑)!Re Rcpp Gallery:是的,当然-只要告诉我我必须做什么。看一看--然后可能发送一个请求?使用Rcpp进行系统级C呼叫显然没有得到充分的重视和记录。我们应该写这个页面。@DirkEddelbuettel好的,可以。不过可能需要一些时间,因为我将在接下来的两周内出差。但我会想办法解决的。
#first some garbage collection
gc()
old_mem_mb=mem_used_bytes(Sys.getpid())/1e6

#allocate a matrix with approx 800MB
NN=1e4
expected_memory_mb=NN^2*8/1e6
A=matrix(runif(NN**2),NN,NN)

#garbage collection, again
gc()

#query used memory again
new_mem_mb=mem_used_bytes(Sys.getpid())/1e6

#the following value should be close to 1
(new_mem_mb-old_mem_mb)/expected_memory_mb
#include <Rcpp.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/sysinfo.h>

// [[Rcpp::export]]
long mem_used_bytes(int pid) {
    long rss = 0L;
    FILE* fp = NULL;
    char filepath[128];
    snprintf(filepath, 127, "/proc/%d/statm", pid);
    if ( (fp = fopen(filepath, "r" )) == NULL )
        return (size_t)0L;      /* Can't open? */
    if ( fscanf( fp, "%*s%ld", &rss ) != 1 ) {
        fclose( fp );
        return (size_t)0L;      /* Can't read? */
    }
    fclose( fp );
    return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
}

// [[Rcpp::export]]
long mem_limit_bytes(int pid_int) {
    long res;
    struct rlimit tmp;
    pid_t pid=pid_int;
    prlimit(pid, RLIMIT_AS, NULL, &tmp);
    if (tmp.rlim_cur==-1L) {
        //there is no memory limit for the current process (should be default)
        Rcpp::Rcout << "No limit detected\n";
        struct sysinfo tmp2;
        sysinfo(&tmp2);
        res = tmp2.mem_unit * tmp2.totalram;
    } else {
        //memory limit set
        Rcpp::Rcout << "Limit detected\n";
        res=tmp.rlim_cur;
    }
    return res;
}

/*** R
## memory without limit set; returns total system memory
mem_limit_bytes(Sys.getpid())/1e6

## try out the `mem_used_bytes` function
## first some garbage collection
gc()
old_mem_mb <- mem_used_bytes(Sys.getpid())/1e6

## allocate a matrix with approx 800MB
NN <- 1e4
expected_memory_mb <- NN^2 * 8 / 1e6
A <- matrix(runif(NN**2),NN,NN)

##garbage collection, again
gc()

## query used memory again
new_mem_mb <- mem_used_bytes(Sys.getpid())/1e6

## the following value should be close to 1
(new_mem_mb - old_mem_mb)/expected_memory_mb

*/