我已经使用valloc分配了内存,假设数组A的大小为15*sizeof(double)。现在,我将它分成三个部分,并希望将每个部分(长度为5)绑定到三个NUMA节点(假设为0、1和2)。目前,我正在做以下工作:
double* A=(double*)valloc(15*sizeof(double));
piece=5;
nodemask=1;
mbind(&A[0],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
nodemask=2;
mbind(&A[5],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
nodemask=4;
mbind(&A[10],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);第一个问题是我做得对吗?例如,与页面大小对齐有什么问题吗?目前数组A的大小为15,它运行得很好,但是如果我将数组大小重置为6156000和piece=2052000之类的值,然后调用mbind三次,分别以&A、&A2052000和&A4104000开头,那么我就会得到一个分段错误(有时它会挂在那里)。为什么它在小尺寸下运行得很好,而在大尺寸下却给了我段错误?谢谢。
发布于 2013-01-26 03:12:19
为此,您需要处理至少与页面大小相同且与页面对齐的内存块-这意味着在大多数系统中为4KB。在您的例子中,我怀疑页面被移动了两次(可能是三次),这是因为您调用了mbind()三次。
numa内存的定位方式是CPU插槽0的范围是0..X-1MB,插槽1的范围是X..2X-1,插槽3的范围是2X-3X-1,等等。当然,如果您在插槽0旁边粘贴4 4GB的ram棒,在插槽1中粘贴16 4GB的内存,那么分布就不均匀。但原则仍然是,根据内存的实际位置,为每个插槽分配一大块内存。
由于内存的定位方式,您正在使用的内存的物理位置必须通过页面映射放在线性(虚拟)地址空间中。
因此,对于较大的内存块,移动它是可以的,但是对于较小的内存块,它就不能很好地工作-您肯定不能将一个页面“拆分”成与两个不同的CPU插槽相关联的东西。
编辑:
要拆分数组,首先需要找到页面对齐的大小。
page_size = sysconf(_SC_PAGESIZE);
objs_per_page = page_size / sizeof(A[0]);
// We should be an even number of "objects" per page. This checks that that
// no object straddles a page-boundary
ASSERT(page_size % sizeof(A[0]));
split_three = SIZE / 3;
aligned_size = (split_three / objs_per_page) * objs_per_page;
remnant = SIZE - (aligned_size * 3);
piece = aligned_size;
mbind(&A[0],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
mbind(&A[aligned_size],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
mbind(&A[aligned_size*2 + remnant],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);显然,您现在需要根据需要使用对齐的大小和残差以类似的方式拆分这三个线程。
https://stackoverflow.com/questions/14528588
复制相似问题