我希望能够将自己的内存分配函数用于R中的某些数据结构(实值向量和数组)。原因是我需要将数据对齐为64位并且我想使用numa library用于控制使用哪个内存节点(我正在使用四个12核AMD Opteron 6174 CPU的计算节点上工作)。
现在我有两个分配和释放内存的功能:numa_alloc_onnode
和numa_free
(由this thread提供)。我使用R版本3.1.1,因此我可以访问函数allocVector3
(src/main/memory.c
),这在我看来是添加自定义内存分配器的预期方式。我还在R_allocator
src/include/R_ext
然而,我不清楚如何把这些碎片放在一起。让我们说,在R中,我想要评估的结果res
,例如
res <- Y - mean(Y)
要保存在分配有我自己的功能的内存区域中,我该怎么做?我可以直接在R级别集成allocVector3
吗?我假设我必须通过R-C接口。据我所知,我不能只返回指向已分配区域的指针,但必须将结果作为参数传递。所以在R中我称之为
n <- length(Y)
res <- numeric(length=1)
.Call("R_allocate_using_myalloc", n, res)
res <- Y - mean(Y)
和C
#include <R.h>
#include <Rinternals.h>
#include <numa.h>
SEXP R_allocate_using_myalloc(SEXP R_n, SEXP R_res){
PROTECT(R_n = coerceVector(R_n, INTSXP));
PROTECT(R_res = coerceVector(R_res, REALSXP));
int *restrict n = INTEGER(R_n);
R_allocator_t myAllocator;
myAllocator.mem_alloc = numa_alloc_onnode;
myAllocator.mem_free = numa_free;
myAllocator.res = NULL;
myAllocator.data = ???;
R_res = allocVector3(REALSXP, n, myAllocator);
UNPROTECT(2);
}
不幸的是,我无法超越variable has incomplete type 'R_allocator_t'
编译错误(我必须删除.data
行,因为我不知道我应该放在哪里)。以上任何代码是否有意义?有没有更容易实现我想要的方式?在R中分配一个小向量并在C中改变它的位置似乎有点奇怪,只是为了能够控制内存分配并使R中的向量可用...
我试图避免使用Rcpp,因为我正在修改一个相当大的包并且不想转换所有C调用,并且认为混合不同的C接口可以执行次优。
非常感谢任何帮助。
答案 0 :(得分:1)
我在解决问题方面取得了一些进展,我想分享一下其他人遇到类似情况的情况。感谢Kevin的评论。我错过了他提到的包含声明。不幸的是,这只是众多问题中的一个。
dyn.load("myAlloc.so")
size <- 3e9
myBigmat <- .Call("myAllocC", size)
print(object.size(myBigmat), units = "auto")
rm(myBigmat)
#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rallocators.h>
#include <numa.h>
typedef struct allocator_data {
size_t size;
} allocator_data;
void* my_alloc(R_allocator_t *allocator, size_t size) {
((allocator_data*)allocator->data)->size = size;
return (void*) numa_alloc_local(size);
}
void my_free(R_allocator_t *allocator, void * addr) {
size_t size = ((allocator_data*)allocator->data)->size;
numa_free(addr, size);
}
SEXP myAllocC(SEXP a) {
allocator_data* my_allocator_data = malloc(sizeof(allocator_data));
my_allocator_data->size = 0;
R_allocator_t* my_allocator = malloc(sizeof(R_allocator_t));
my_allocator->mem_alloc = &my_alloc;
my_allocator->mem_free = &my_free;
my_allocator->res = NULL;
my_allocator->data = my_allocator_data;
R_xlen_t n = asReal(a);
SEXP result = PROTECT(allocVector3(REALSXP, n, my_allocator));
UNPROTECT(1);
return result;
}
为了编译c代码,我使用R CMD SHLIB -std=c99 -L/usr/lib64 -lnuma myAlloc.c
。据我所知,这很好用。如果有人提供改进/更正,我很乐意将其包括在内。
原始问题中尚未解决的一个要求是对齐问题。 numa_alloc_local
返回的内存块已正确对齐,但新VECTOR_SEXPREC
的其他字段(例如sxpinfo_struct
标头)会推回数据数组的开头。是否有可能对齐此起始点(REAL()
返回的地址)?
答案 1 :(得分:0)
R,memory.c
:
main/memory.c
84:#include <R_ext/Rallocators.h> /* for R_allocator_t structure */
所以我认为您需要包含该标头以获取自定义分配器(RInternals.h
仅声明它,而不定义struct
或包含该标头)