Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 通过延迟/性能测量确定NUMA布局_C_Performance_Caching_Prefetch_Numa - Fatal编程技术网

C 通过延迟/性能测量确定NUMA布局

C 通过延迟/性能测量确定NUMA布局,c,performance,caching,prefetch,numa,C,Performance,Caching,Prefetch,Numa,最近,我一直在观察我无法解释的内存密集型工作负载对性能的影响。为了弄清这一点,我开始运行几个微基准点,以确定常见的性能参数,如缓存线大小和一级/二级/三级缓存大小(我已经知道了,我只是想看看我的测量是否反映了实际值) 对于缓存线测试,我的代码大致如下(Linux C,但其概念与Windows等类似): 当我开始将数组大小增加到大于L3大小的值时,我得到了大量不可靠的数字,即使大量重复也无法平衡。我无法通过这种方式确定可用于性能评估的模式,更不用说确定NUMA条带的起始、结束或位置了 然后,我发现

最近,我一直在观察我无法解释的内存密集型工作负载对性能的影响。为了弄清这一点,我开始运行几个微基准点,以确定常见的性能参数,如缓存线大小和一级/二级/三级缓存大小(我已经知道了,我只是想看看我的测量是否反映了实际值)

对于缓存线测试,我的代码大致如下(Linux C,但其概念与Windows等类似):

当我开始将
数组大小增加到大于L3大小的值时,我得到了大量不可靠的数字,即使大量重复也无法平衡。我无法通过这种方式确定可用于性能评估的模式,更不用说确定NUMA条带的起始、结束或位置了

然后,我发现硬件预取器足够智能,可以识别我的简单访问模式,并在访问之前将所需的行提取到缓存中。在数组索引中添加一个随机数会增加每个元素的时间,但在其他方面似乎没有多大帮助,可能是因为每次迭代我都有一个
rand()
调用。对我来说,预先计算一些随机值并将它们存储在一个数组中似乎不是一个好主意,因为这个数组也会存储在一个热缓存中,从而扭曲我的测量结果。将
STEP
增加到4097或8193也没有多大帮助,预取程序一定比我聪明

我的方法是否明智/可行,或者我是否错过了大局?有可能观察到这样的NUMA潜伏期吗?如果是,我做错了什么? 我禁用了地址空间随机化只是为了确保并排除奇怪的缓存锯齿效应。在测量之前,是否还有其他操作系统需要调整

有可能观察到这样的NUMA潜伏期吗?如果是,我做错了什么

内存分配器是NUMA感知的,因此在默认情况下,除非明确要求在另一个节点上分配内存,否则不会观察到任何NUMA效果。实现此效果最简单的方法是numactl(8)。只需在一个节点上运行应用程序,并将内存分配绑定到另一个节点,如下所示:

numactl --cpunodebind 0 --membind 1 ./my-benchmark
另见numa_alloc_onnode(3)

在测量之前,是否还有其他操作系统需要调整

关闭CPU缩放功能,否则您的测量可能会有噪音:

find '/sys/devices/system/cpu/' -name 'scaling_governor' | while read F; do
        echo "==> ${F}"
        echo "performance" | sudo tee "${F}" > /dev/null
done
现在关于测试本身。当然,要测量延迟,访问模式必须是(伪)随机的。否则,您的测量将被快速缓存命中所污染

以下是您如何实现这一目标的示例:

数据初始化 用随机数填充数组:

static void random_data_init()
{
    for (size_t i = 0; i < ARR_SZ; i++) {
        arr[i] = rand();
    }
}

32K/64K(我的一级缓存~32K)、256K/512K(我的二级缓存~256K)和6144K/8192K(我的三级缓存~6M)之间有明显的步骤。

Re:预取器,英特尔预取器执行黑魔法。我听说它在你当前的步幅上应用了多重多项式拟合来神奇地预取,等等。你最好的办法可能是使用MTRRs来标记一个不可缓存的内存范围,然后在这个范围内进行基准测试。啊,我想用一个单独的随机数组来分散预取程序的注意力,但我认为它本身很热会污染我的缓存。使用随机值初始化数组本身并从本质上执行指针跟踪是一个好主意。我会试试的,谢谢。至于NUMA控制-我实际上在一个本身不是NUMA的系统上,但仍然表现出这样的特性(malloc不知道NUMA),因此我不能依赖numactl。当数组足够大时,即使不绑定它,是否也可以从不同的节点强制内存?@SonnyO'Rullivan如果您的系统不是NUMA,那么这实际上取决于这些页面如何交错。您可能会从NUMA0获得一个页面,然后从NUMA1获得几个页面。那么这样的方法真的会给你带来噪音。您可以尝试另一种方法,用相同的数据污染缓存,一次只交换一页。但是,可能很难发现如此微妙的变化。。。有一件事是肯定的:您应该将测试与页面大小对齐…@andriyberestovsky-我可以得到您编写的基准测试代码吗?这对我有很大帮助。
find '/sys/devices/system/cpu/' -name 'scaling_governor' | while read F; do
        echo "==> ${F}"
        echo "performance" | sudo tee "${F}" > /dev/null
done
static void random_data_init()
{
    for (size_t i = 0; i < ARR_SZ; i++) {
        arr[i] = rand();
    }
}
const size_t OPERATIONS = 1 * 1000 * 1000; // 1M operations per iteration

int random_step_sizeK(size_t size)
{
    size_t idx = 0;

    for (size_t i = 0; i < OPERATIONS; i++) {
        arr[idx & (size - 1)]++;
        idx += arr[idx & (size - 1)] * 64; // assuming cache line is 64B
    }
    return 0;
}
----------------------------------------------------------------
Benchmark                         Time           CPU Iterations
----------------------------------------------------------------
random_step_sizeK/4         4217004 ns    4216880 ns        166
random_step_sizeK/8         4146458 ns    4146227 ns        168
random_step_sizeK/16        4188168 ns    4187700 ns        168
random_step_sizeK/32        4180545 ns    4179946 ns        163
random_step_sizeK/64        5420788 ns    5420140 ns        129
random_step_sizeK/128       6187776 ns    6187337 ns        112
random_step_sizeK/256       7856840 ns    7856549 ns         89
random_step_sizeK/512      11311684 ns   11311258 ns         57
random_step_sizeK/1024     13634351 ns   13633856 ns         51
random_step_sizeK/2048     16922005 ns   16921141 ns         48
random_step_sizeK/4096     15263547 ns   15260469 ns         41
random_step_sizeK/6144     15262491 ns   15260913 ns         46
random_step_sizeK/8192     45484456 ns   45482016 ns         23
random_step_sizeK/16384    54070435 ns   54064053 ns         14
random_step_sizeK/32768    59277722 ns   59273523 ns         11
random_step_sizeK/65536    63676848 ns   63674236 ns         10
random_step_sizeK/131072   66383037 ns   66380687 ns         11