<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
</head>
<body>
<br>
A tiny bit more about noise for Neil, since its a bit subtle and I had never heard of it before working in HPC.&nbsp; Sorry if this is old news.<br>
<br>
Noise here means differences in execution time. A typical HPC Job consists of thousands of processes running across a large system.&nbsp; The basic model is they all run a compute step, then they all communicate part of their results (generally to some neighboring
 subset of processes, not all-to-all).&nbsp; The results which are communicated are then used as part of the input to the next compute step.&nbsp; As you can see, effectively, everyone must finish each step before anyone can continue (or at least, continue very far).<br>
<br>
So if everyone finishes every step in the same amount of time, great.&nbsp; But if theres jitter in the completion time for a step for a particular process - as can be introduced by a scheduler with ideas that dont quite line up with your job priorities - it delays
 the completion of the step overall.&nbsp; This is compounded at each step of the job and so can be quite serious.&nbsp; (Job steps can be quite short - double digit microseconds is not unusual - so relatively small jitter can really add up.)<br>
<br>
So HPC users are really fussy about affinity and placement control.&nbsp; Which isnt to say Lustre gets it all right, but its why we care so much.<br>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> lustre-devel &lt;lustre-devel-bounces@lists.lustre.org&gt; on behalf of James Simmons &lt;jsimmons@infradead.org&gt;<br>
<b>Sent:</b> Thursday, July 5, 2018 7:20:37 PM<br>
<b>To:</b> Weber, Olaf (HPC Data Management &amp; Storage)<br>
<b>Cc:</b> Lustre Development List<br>
<b>Subject:</b> Re: [lustre-devel] [PATCH v3 07/26] staging: lustre: libcfs: NUMA support</font>
<div>&nbsp;</div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText"><br>
&gt; NeilBrown [<a href="mailto:neilb@suse.com">mailto:neilb@suse.com</a>] wrote:<br>
&gt; <br>
&gt; To help contextualize things: the Lustre code can be decomposed into three parts:<br>
&gt; <br>
&gt; 1) The filesystem proper: Lustre.<br>
&gt; 2) The communication protocol it uses: LNet.<br>
&gt; 3) Supporting code used by Lustre and LNet: CFS.<br>
&gt; <br>
&gt; Part of the supporting code is the CPT mechanism, which provides a way to<br>
&gt; partition the CPUs of a system. These partitions are used to distribute queues,<br>
&gt; locks, and threads across the system. It was originally introduced years ago, as<br>
&gt; far as I can tell mainly to deal with certain hot locks: these were converted into<br>
&gt; read/write locks with one spinlock per CPT.<br>
&gt; <br>
&gt; As a general rule, CPT boundaries should respect node and socket boundaries,<br>
&gt; but at the higher end, where CPUs have 20&#43; cores, it may make sense to split<br>
&gt; a CPUs cores across several CPTs.<br>
&gt; <br>
&gt; &gt; Thanks everyone for your patience in explaining things to me.<br>
&gt; &gt; I'm beginning to understand what to look for and where to find it.<br>
&gt; &gt; <br>
&gt; &gt; So the answers to Greg's questions:<br>
&gt; &gt; <br>
&gt; &gt;&nbsp;&nbsp; Where are you reading the host memory NUMA information from?<br>
&gt; &gt; <br>
&gt; &gt;&nbsp;&nbsp; And why would a filesystem care about this type of thing?&nbsp; Are you<br>
&gt; &gt;&nbsp;&nbsp; going to now mirror what the scheduler does with regards to NUMA<br>
&gt; &gt;&nbsp;&nbsp; topology issues?&nbsp; How are you going to handle things when the topology<br>
&gt; &gt;&nbsp;&nbsp; changes?&nbsp; What systems did you test this on?&nbsp; What performance<br>
&gt; &gt;&nbsp;&nbsp; improvements were seen?&nbsp; What downsides are there with all of this?<br>
&gt; &gt; <br>
&gt; &gt; <br>
&gt; &gt; Are:<br>
&gt; <br>
&gt; &gt;&nbsp;&nbsp; - NUMA info comes from ACPI or device-tree just like for every one<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else.&nbsp; Lustre just uses node_distance().<br>
&gt; <br>
&gt; Correct, the standard kernel interfaces for this information are used to<br>
&gt; obtain it, so ultimately Lustre/LNet uses the same source of truth as<br>
&gt; everyone else.<br>
&gt; <br>
&gt; &gt;&nbsp;&nbsp; - The filesystem cares about this because...&nbsp; It has service<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; thread that does part of the work of some filesystem operations<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; (handling replies for example) and these are best handled &quot;near&quot;<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; the CPU the initiated the request.&nbsp; Lustre partitions<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; all CPUs into &quot;partitions&quot; (cpt) each with a few cores.<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; If the request thread and the reply thread are on different<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; CPUs but in the same partition, then we get best throughput<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; (is that close?)<br>
&gt; <br>
&gt; At the filesystem level, it does indeed seem to help to have the service<br>
&gt; threads that do work for requests run on a different core that is close to<br>
&gt; the core that originated the request. So preferably on the same CPU, and<br>
&gt; on certain multi-core CPUs there are also distance effects between cores.<br>
&gt; That too is one of the things the CPT mechanism handles.<br>
<br>
Their is another very important aspect to why Lustre has a CPU partition <br>
layer. At least at the place I work at. While the Linux kernel manages all<br>
the NUMA nodes and CPU cores Lustre adds the ability for us to specify a <br>
subset of everything on the system. The reason is to limit the impact of<br>
noise on the compute nodes. Noise has a heavy impact on large scale HP<br>
work loads that can run days or even weeks at a time. Lets take an <br>
example system:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------------|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------------|<br>
&nbsp;&nbsp; |-------|&nbsp;&nbsp; | NUMA&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; | NUMA&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |-------|<br>
&nbsp;&nbsp; | eth0&nbsp; | - |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | --- |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | - | eth1&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp; |_______|&nbsp;&nbsp; | CPU0&nbsp; CPU1&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; | CPU2&nbsp; CPU3&nbsp; |&nbsp;&nbsp; |_______|<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_____________|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_____________|<br>
<br>
In such a system it is possible with the right job schedular to start a <br>
large parallel application on NUMA 0/ (CPU0 and CPU1). Normally such<br>
large parallel applications will communicate between nodes using MPI,<br>
such as openmpi, which can be configured to use eth0 only. Using the<br>
CPT layer in lustre we can isolate lustre to NUMA 1 and use only eth1.<br>
This greatly reducess the noise impact on the application running.<br>
<br>
BTW this is one of the reasons ko2iblnd for lustre doesn't use the<br>
generic RDMA api. The core IB layer doesn't support such isolation.<br>
At least to my knowledge.<br>
<br>
&gt; &gt;&nbsp;&nbsp; - Not really mirroring the scheduler, maybe mirroring parts of the<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; network layer(?)<br>
&gt; <br>
&gt; The LNet code, which is derived from Portals 3.x, is mostly an easier-to-use<br>
&gt; abstraction of RDMA interfaces provided by Infiniband and other similar<br>
&gt; hardware. It can also use TCP/IP, but that's not the primary use case.<br>
&gt; <br>
&gt; As a communication layer that builds on top of RDMA-capable hardware,<br>
&gt; LNet cares about such things as whether the CPU driving communication<br>
&gt; is close to the memory used, and also whether it is close to the interface<br>
&gt; used. Even in a 2-socket machine, there are measurable performance<br>
&gt; differences depending on whether the memory an interface connect<br>
&gt; to the same socket or to different sockets. On bigger hardware, like a<br>
&gt; 32-socket machine, the penalties are much more pronounced. At the<br>
&gt; time we found that the QPI links between sockets were a bottleneck<br>
&gt; and that performance cratered if they had to handle too much traffic.<br>
&gt; <br>
&gt; UPI, the successor to QPI is better -- has more bandwidth -- but with<br>
&gt; the CPUs having more and more cores I expect the scaling issues to<br>
&gt; remain similar.<br>
&gt; <br>
&gt; &gt;&nbsp;&nbsp; - We don't handle topology changes yet except in very minimal ways<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; (cpts *can* become empty, and that can cause problems).<br>
&gt; <br>
&gt; Yes, this is a known deficiency.<br>
&gt; <br>
&gt; &gt;&nbsp;&nbsp; - This has been tested on .... great big things.<br>
&gt; <br>
&gt; The basic CPT mechanism predates my involvement with Lustre. I did<br>
&gt; work on making it more NUMA-aware. A 32-socket system was one of<br>
&gt; the primary test beds.<br>
&gt; <br>
&gt; &gt;&nbsp;&nbsp; - When multi-rails configurations are used (like ethernet-bonding,<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; but for RDMA), we get ??? closer to theoretical bandwidth.<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; Without these changes it scales poorly (??)<br>
&gt; <br>
&gt; The basic idea behind muti-rail configurations is that we use several<br>
&gt; Infiniband interfaces and LNet presents them as a single logical interface<br>
&gt; to Lustre. For each message, LNet picks the IB interface it should go across<br>
&gt; using several criteria, including NUMA distance of the interface and how<br>
&gt; busy it is.<br>
&gt; <br>
&gt; With these changes we could get pretty much linear scaling of LNet<br>
&gt; throughput by adding more interfaces.<br>
&gt; <br>
&gt; &gt;&nbsp;&nbsp; - The down-sides primarily are that we don't auto-configure<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; perfectly.&nbsp; This particularly affects hot-plug, but without<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; hotplug the grouping of cpus and interfaces are focussed<br>
&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; on .... avoiding worst case rather than achieving best case.<br>
&gt; <br>
&gt; Without hotplug the CPT grouping should be tuned to achieve a best<br>
&gt; case in a static configuration.<br>
&gt; <br>
&gt; Adding simple-minded hotplug tolerance (let's not call it support) would<br>
&gt; focus on avoiding truly pathological behaviour.<br>
&gt; <br>
&gt; &gt; I've made up a lot of stuff there.&nbsp; I'm happy not to pursue this further at the<br>
&gt; &gt; moment, but if anyone would like to enhance my understanding by<br>
&gt; &gt; correcting the worst errors in the above, I wouldn't object :-)<br>
&gt; &gt; <br>
&gt; &gt; Thanks,<br>
&gt; &gt; NeilBrown<br>
&gt; <br>
&gt; PS: the NUMA effects I've mentioned above have been making the news<br>
&gt; lately under other names: they are part of the side channels used in various<br>
&gt; timing based attacks.<br>
&gt; <br>
&gt; Olaf<br>
&gt; <br>
&gt; _______________________________________________<br>
&gt; lustre-devel mailing list<br>
&gt; lustre-devel@lists.lustre.org<br>
&gt; <a href="http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org">http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org</a><br>
&gt; <br>
_______________________________________________<br>
lustre-devel mailing list<br>
lustre-devel@lists.lustre.org<br>
<a href="http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org">http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org</a><br>
</div>
</span></font></div>
</body>
</html>