Skip to content

Commit e8a280a

Browse files
committed
added more explanations and changed some graphs
1 parent cc2945c commit e8a280a

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

src/supercomputers/polaris/index.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,131 @@ html`<div style="display: flex; gap: 1rem; margin-top: 1rem; flex-wrap: wrap;">
328328
</div>`
329329
```
330330

331+
## GPU Bandwidth Performance
332+
333+
GPU bandwidth is measured using the
334+
[gpu-margo-p2p-bw](https://github.com/mochi-hpc-experiments/mochi-tests/blob/main/perf-regression/gpu-margo-p2p-bw.cu)
335+
benchmark, which runs on two processes located on distinct nodes, and transfers data using RDMA between CPU and/or GPU memory.
336+
337+
### Latest GPU Bandwidth Results
338+
339+
340+
```js
341+
// Get unique dates from GPU bandwidth data and sort chronologically
342+
const gpuBandwidthDates = [...new Set(bandwidthDataGPU.map(d => String(d.date)))]
343+
.sort((a, b) => new Date(a) - new Date(b));
344+
const latestGPUBandwidthDateInput = Inputs.select(gpuBandwidthDates, {
345+
label: "Date",
346+
value: gpuBandwidthDates[gpuBandwidthDates.length - 1]
347+
});
348+
const selectedGPUBandwidthDate = Generators.input(latestGPUBandwidthDateInput);
349+
```
350+
351+
```js
352+
// Filter data for selected date
353+
const gpuBandwidthForDate = bandwidthDataGPU.filter(d => String(d.date) === selectedGPUBandwidthDate);
354+
355+
// Create data for all memory combinations and operations
356+
const memCombinations = [
357+
{hostA: "GPU", hostB: "GPU"},
358+
{hostA: "GPU", hostB: "CPU"},
359+
{hostA: "CPU", hostB: "GPU"},
360+
{hostA: "CPU", hostB: "CPU"}
361+
];
362+
363+
const ops = ["PULL", "PUSH"];
364+
const gpuBandwidthBarData = [];
365+
366+
for (const mem of memCombinations) {
367+
for (const op of ops) {
368+
const entry = gpuBandwidthForDate.find(d =>
369+
d.op === op &&
370+
d.hostA_mem === mem.hostA &&
371+
d.hostB_mem === mem.hostB
372+
);
373+
// Arrow direction: → for PULL (A pulls from B), ← for PUSH (A pushes to B)
374+
const arrow = op === "PULL" ? "" : "";
375+
gpuBandwidthBarData.push({
376+
category: `${mem.hostA}${arrow}${mem.hostB}`,
377+
throughput: entry ? entry["MiB/s"] / 1024 : 0
378+
});
379+
}
380+
}
381+
```
382+
383+
The following graph shows the GPU bandwidth for different memory locations on each host.
384+
HostA and HostB refer to the two processes on distinct nodes.
385+
Host A is always the sender of an RPC to Host B. The latter issues the RDMA transfer (PUSH or PULL). Hence "GPU←CPU" means that Host B issues a PUSH from its CPU memory to Host A's GPU memory. "GPU→CPU" means that Host B issues a PULL from Host A's GPU memory to Host B's CPU memory.
386+
387+
```js
388+
html`<div style="margin-bottom: 1rem;">
389+
${latestGPUBandwidthDateInput}
390+
</div>`
391+
```
392+
393+
```js
394+
Plot.plot({
395+
marks: [
396+
Plot.barY(gpuBandwidthBarData, {x: "category", y: "throughput", fill: "category"})
397+
],
398+
x: {label: null, tickFormat: () => ""},
399+
y: {label: "Throughput (GiB/s)", grid: true},
400+
color: {legend: true},
401+
width: 800,
402+
height: 400,
403+
marginLeft: 60,
404+
marginBottom: 60
405+
})
406+
```
407+
408+
### GPU Bandwidth Over Time
409+
410+
```js
411+
// Create input widgets for GPU bandwidth filtering
412+
const gpuOperationInput = Inputs.select(["PULL", "PUSH"], {label: "Operation", value: "PULL"});
413+
const gpuOperation = Generators.input(gpuOperationInput);
414+
const hostAMemInput = Inputs.select(["CPU", "GPU"], {label: "Host A Memory", value: "GPU"});
415+
const hostA_mem = Generators.input(hostAMemInput);
416+
const hostBMemInput = Inputs.select(["CPU", "GPU"], {label: "Host B Memory", value: "GPU"});
417+
const hostB_mem = Generators.input(hostBMemInput);
418+
```
419+
420+
```js
421+
// Filter GPU bandwidth data based on selected inputs
422+
const filteredGPUBandwidthData = bandwidthDataGPU.filter(d =>
423+
d.op === gpuOperation &&
424+
d.hostA_mem === hostA_mem &&
425+
d.hostB_mem === hostB_mem
426+
);
427+
428+
// Calculate 30-day range ending at latest date
429+
const latestGPUBandwidthDate = bandwidthDataGPU.length > 0
430+
? new Date(Math.max(...bandwidthDataGPU.map(d => new Date(d.date))))
431+
: new Date();
432+
const thirtyDaysAgoGPUBandwidth = new Date(latestGPUBandwidthDate);
433+
thirtyDaysAgoGPUBandwidth.setDate(thirtyDaysAgoGPUBandwidth.getDate() - 30);
434+
```
435+
436+
```js
437+
Plot.plot({
438+
marks: [
439+
Plot.rectY(filteredGPUBandwidthData, {x: "date", y: d => d["MiB/s"] / 1024, fill: "purple", interval: "day"})
440+
],
441+
x: {type: "utc", label: "Date", domain: [thirtyDaysAgoGPUBandwidth, latestGPUBandwidthDate]},
442+
y: {label: "Throughput (GiB/s)", grid: true},
443+
width: 800,
444+
height: 400,
445+
marginLeft: 60,
446+
marginBottom: 40
447+
})
448+
```
449+
450+
```js
451+
// Display the input widgets
452+
html`<div style="display: flex; gap: 1rem; margin-top: 1rem; flex-wrap: wrap;">
453+
${gpuOperationInput}
454+
${hostAMemInput}
455+
${hostBMemInput}
456+
</div>`
457+
```
458+

0 commit comments

Comments
 (0)