我在Linux下用python3.6/Numpy开发的并行代码中观察到一个奇怪的行为:在两个内核上运行它比在单个内核上运行快大约3倍。我不确定我是否了解确切的问题,但我设法找到了一些线索:
1芯
57414.449252 task-clock:u (msec) # 1.000 CPUs utilized
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
22,583,368 page-faults:u # 0.393 M/sec
115,569,738,160 cycles:u # 2.013 GHz
22,655,695,268 stalled-cycles-frontend:u # 19.60% frontend cycles idle
32,251,136,400 stalled-cycles-backend:u # 27.91% backend cycles idle
189,041,318,733 instructions:u # 1.64 insn per cycle
# 0.17 stalled cycles per insn
38,298,469,811 branches:u # 667.053 M/sec
654,389,291 branch-misses:u # 1.71% of all branches
83,343,166,583 L1-dcache-loads:u # 1451.606 M/sec
318,284,548 L1-dcache-load-misses:u # 0.38% of all L1-dcache hits
25,589,478,853 L1-icache-loads:u # 445.698 M/sec
2,560,674,130 L1-icache-load-misses:u # 10.01% of all L1-icache hits
83,377,552,384 dTLB-loads:u # 1452.205 M/sec
216,145,062 dTLB-load-misses:u # 0.26% of all dTLB cache hits
25,626,979,550 iTLB-loads:u # 446.351 M/sec
55,847,490 iTLB-load-misses:u # 0.22% of all iTLB cache hits
222,176 L1-dcache-prefetches:u # 0.004 M/sec
220,870 L1-dcache-prefetch-misses:u # 0.004 M/sec
2芯
111569.269846 task-clock:u (msec) # 1.837 CPUs utilized
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
4,415,116 page-faults:u # 0.040 M/sec
330,750,606,867 cycles:u # 2.965 GHz
69,517,418,862 stalled-cycles-frontend:u # 21.02% frontend cycles idle
104,365,888,484 stalled-cycles-backend:u # 31.55% backend cycles idle
609,338,385,634 instructions:u # 1.84 insn per cycle
# 0.17 stalled cycles per ins
125,341,622,204 branches:u # 1123.442 M/sec
1,860,702,685 branch-misses:u # 1.48% of all branches
261,941,396,767 L1-dcache-loads:u # 2347.792 M/sec
935,372,306 L1-dcache-load-misses:u # 0.36% of all L1-dcache hits
79,306,212,694 L1-icache-loads:u # 710.825 M/sec
7,337,551,130 L1-icache-load-misses:u # 9.25% of all L1-icache hits
261,578,594,355 dTLB-loads:u # 2344.540 M/sec
425,510,820 dTLB-load-misses:u # 0.16% of all dTLB cache hits
79,008,997,415 iTLB-loads:u # 708.161 M/sec
102,332,385 iTLB-load-misses:u # 0.13% of all iTLB cache hits
944,223 L1-dcache-prefetches:u # 0.008 M/sec
945,497 L1-dcache-prefetch-misses:u # 0.008 M/sec
运行perf top表示大约35%的时间花在内核中,这些函数是最主要的贡献者:
^{pr3}$。你知道吗我觉得至少有一部分问题是在复制大约15×3500个浮点数的Numpy数组时产生的,但不是每次都是。该代码基本上是在物理参数的笛卡尔网格上计算模型,并对包含几个Numpy数组的对象进行频繁复制。现在,对于该对象的某些副本(但不是所有副本),我假设由于页面错误,这个~15×3500 Numpy数组的副本需要花费~15倍的时间。代码经常创建/删除这些对象,但是与每个进程相关联的总体内存变化缓慢(结果被写入一个共享的RawArray),因此我认为通常应该重新分配内存(在销毁前一个对象之后不久创建一个新对象)。这只发生在使用单个内核时,而不是在使用更多内核时。
我试着在同一时间用一个内核启动两个独立的运行,它们都有大量的页面错误。因此,它似乎与同时运行多个进程无关。
在单核上运行时,我尝试了使用多处理(spawn和fork)和不使用多处理(spawn和fork)两种方法,结果是相同的,页面错误的数量很高。所以这似乎没有关系
这在Archlinux python包和Anaconda包中都会发生。
这发生在AMD EPYC 7351(512 GB或RAM)和Intel Core i7 6700K(64 GB RAM)(均运行Linux)上。该代码使用~10gb的RAM,主要以rawrarray的形式存储结果。每个对象中使用的RAM应该是~500kb,并且在任何给定时刻RAM中不应该有超过7-8个。
我有点搞不懂为什么在单核上运行时会出现如此多的页面错误,而在2+核上运行时却没有。你知道会发生什么吗?有什么办法可以解决吗?我试图衡量代码如何随着内核数量的增加而扩展,因此我希望在单个内核上运行时有一个可靠的数据点。同样,使用2个内核比在单个内核上运行快3倍。你知道吗
目前没有回答
相关问题 更多 >
编程相关推荐