numa(3)
Linuxのライブラリについて頭を悩ませようとしています。
大きな配列が割り当てられています (何 GB ものメモリ)。ランダム NUMA ノードで実行されているスレッドは、ランダム NUMA メモリ ノード (デフォルトの NUMA ポリシー) でそのようなページに障害が発生するため、それに書き込みます。
スレッド計算の最後に、結果を合計するシングルスレッド ジョブがあります。そのために、最初に配列を圧縮して多くの要素を削除し、残りをマスター スレッドの NUMA ノードに移動します。
システムコールは、move_pages
ページごとに配列エントリを必要とするため、ジョブに適していません-オーバーヘッドが多すぎます。
numa_tonode_memory
ドキュメントは、障害のあるメモリを強制的に移動できるかどうか不明です。
したがって、私が見る唯一の方法はmbind
withを使用することですがMPOL_MF_MOVE
、適切な引数を作成することに頭を悩ませることはできませnodemask
ん (または他の何かが失敗しています)。これが私が得た限りです:
#define _GNU_SOURCE
#include <stdlib.h>
#include <sched.h>
#include <numa.h>
#include <numaif.h>
int master_node;
nodemask_t master_nodemask;
// initializer
// has to be called from master/main thread
void numa_lock_master_thread() {
int curcpu = sched_getcpu();
if (curcpu >= 0) {
// master_node = numa_node_of_cpu(curcpu);
numa_run_on_node(master_node = numa_node_of_cpu(curcpu));
if (master_node >= 0) {
struct bitmask * bindmask = numa_bitmask_alloc(numa_num_possible_nodes());
numa_bitmask_clearall(bindmask);
numa_bitmask_setbit(bindmask, master_node);
copy_bitmask_to_nodemask(bindmask, &master_nodemask);
numa_bitmask_free(bindmask);
}
} else { // has never failed before
perror("sched_getcpu");
}
}
static inline void numa_migrate_pages_to_master_node(void * addr, unsigned long len) {
if (master_node < 0)
return;
if ( mbind( addr
, len
, MPOL_BIND
, master_nodemask.n
, numa_max_node()
, MPOL_MF_MOVE)) {
perror("mbind");
}
}
から/usr/include/numa.h
:
typedef struct {
unsigned long n[NUMA_NUM_NODES/(sizeof(unsigned long)*8)];
} nodemask_t;
を取得することもあればmbind: Bad address
、呼び出しが成功することもありますが、その後のメモリ アクセスではSIGSEGV
.
addr
によって返される常に有効なポインターです。
mmap(NULL, (num_pages) * sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | (flags), -1, 0);
およびlen
ページ揃えです。
できるだけ少ないシステムコールで、大きなオーバーヘッドなしでこれを機能させるにはどうすればよいmove_pages
ですか?
nodemask
そして、引数を設定する適切な方法は何mbind
ですか?