Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .readthedocs.yaml

This file was deleted.

198 changes: 198 additions & 0 deletions build_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#!/usr/bin/env python3
"""Discover and build Sphinx docsets in this monorepo.

A "docset" is any folder in the repo that contains a ``conf.py`` (searched
recursively, so docsets may be nested e.g. ``reference-architecture/MI3XX``).
This script finds them automatically, so adding a new docset folder requires
no changes to tasks.json or to this script.

Usage:
python build_docs.py --list
Print every discovered docset (name + path), one per line.

python build_docs.py --all [--clean]
Build every discovered docset.

python build_docs.py --docset <name> [--clean]
Build a single docset by folder name (e.g. "docs").

python build_docs.py --file <path> [--clean]
Build whichever docset the given file lives in. Used by the VS Code
"Build Docs" task with ${file} so Ctrl+B builds the docset you're
currently editing.

Each docset builds into its own namespaced output + doctree cache under
<repo>/.vscode/build/<docset>/{html,doctrees}
so docsets never clobber each other or share a (project-specific) doctree
cache.

Exit codes:
0 success
1 usage / discovery error (e.g. file not under any docset)
N the underlying sphinx-build exit code on build failure
"""

from __future__ import annotations

import argparse
import os
import shutil
import subprocess
import sys
from pathlib import Path


# Repo root = the directory containing this script.
REPO_ROOT = Path(__file__).resolve().parent
BUILD_ROOT = REPO_ROOT / ".vscode" / "build"

# Folders that can never be docsets even if they somehow contain a conf.py.
IGNORE_DIRS = {".git", ".vscode", ".venv", "venv", "node_modules", "__pycache__"}


def _docset_name(src: Path, taken: set[str]) -> str:
"""Pick a unique docset name for a source dir.

Prefer the folder's own basename (e.g. "docs", "MI3XX"). If that collides
with an already-claimed name, fall back to the repo-relative path with the
OS separator replaced by "-" (e.g. "reference-architecture-MI3XX") so every
docset stays addressable on the CLI and gets its own build output dir.
"""
name = src.name
if name not in taken:
return name
return "-".join(src.relative_to(REPO_ROOT).parts)


def discover_docsets() -> dict[str, Path]:
"""Return {docset_name: source_dir} for every folder holding a conf.py.

Walks the repo recursively (not just top-level children) so docsets may be
nested, e.g. ``reference-architecture/MI3XX/conf.py``. Ignored folders are
pruned, and once a folder is identified as a docset we do not descend into
it (a docset never contains another docset). Sorted for stable ordering.
"""
docsets: dict[str, Path] = {}
for dirpath, dirnames, filenames in os.walk(REPO_ROOT):
# Prune ignored dirs in place so os.walk never descends into them.
dirnames[:] = sorted(d for d in dirnames if d not in IGNORE_DIRS)
if "conf.py" in filenames:
src = Path(dirpath)
docsets[_docset_name(src, set(docsets))] = src
# Don't look for docsets nested inside this one.
dirnames[:] = []
return dict(sorted(docsets.items()))


def docset_for_file(file_path: Path, docsets: dict[str, Path]) -> str | None:
"""Return the docset name that ``file_path`` belongs to, or None."""
try:
resolved = file_path.resolve()
except OSError:
return None
for name, src in docsets.items():
try:
resolved.relative_to(src.resolve())
return name
except ValueError:
continue
return None


def build_one(name: str, src: Path, clean: bool) -> int:
"""Build a single docset with Sphinx. Returns the sphinx-build exit code."""
out_html = BUILD_ROOT / name / "html"
out_doctrees = BUILD_ROOT / name / "doctrees"

if clean:
target = BUILD_ROOT / name
if target.exists():
print(f"[clean] removing {target}")
shutil.rmtree(target, ignore_errors=True)

out_html.mkdir(parents=True, exist_ok=True)
out_doctrees.mkdir(parents=True, exist_ok=True)

cmd = [
sys.executable, "-m", "sphinx",
"-j", "auto",
"-T",
"-b", "html",
"-d", str(out_doctrees),
"-D", "language=en",
str(src),
str(out_html),
]
print(f"[build] {name}: {' '.join(cmd)}")
result = subprocess.run(cmd, cwd=str(REPO_ROOT))
if result.returncode == 0:
print(f"[build] {name}: OK -> {out_html}")
else:
print(f"[build] {name}: FAILED (exit {result.returncode})", file=sys.stderr)
return result.returncode


def main(argv: list[str]) -> int:
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--list", action="store_true", help="List discovered docsets and exit.")
group.add_argument("--list-names", action="store_true",
help="Print 'all' then each docset name, one per line (for pickers).")
group.add_argument("--all", action="store_true", help="Build every docset.")
group.add_argument("--docset", metavar="NAME", help="Build a single docset by folder name.")
group.add_argument("--file", metavar="PATH", help="Build the docset containing this file.")
parser.add_argument("--clean", action="store_true", help="Remove the docset's build output first.")
args = parser.parse_args(argv)

docsets = discover_docsets()

if args.list_names:
print("all")
for name in docsets:
print(name)
return 0

if args.list:
if not docsets:
print("(no docsets found — no top-level folder contains a conf.py)")
return 0
for name, src in docsets.items():
print(f"{name}\t{src}")
return 0

if not docsets:
print("Error: no docsets found (no top-level folder contains a conf.py).", file=sys.stderr)
return 1

if args.all:
rc = 0
for name, src in docsets.items():
rc = build_one(name, src, args.clean) or rc
return rc

if args.docset:
if args.docset == "all":
rc = 0
for name, src in docsets.items():
rc = build_one(name, src, args.clean) or rc
return rc
if args.docset not in docsets:
print(f"Error: '{args.docset}' is not a docset. Known: {', '.join(docsets) or '(none)'}",
file=sys.stderr)
return 1
return build_one(args.docset, docsets[args.docset], args.clean)

if args.file:
name = docset_for_file(Path(args.file), docsets)
if name is None:
print(f"Error: '{args.file}' is not inside any docset.\n"
f"Open a file under one of: {', '.join(docsets)}", file=sys.stderr)
return 1
return build_one(name, docsets[name], args.clean)

return 0 # unreachable (group is required)


if __name__ == "__main__":
raise SystemExit(main(sys.argv[1:]))
30 changes: 30 additions & 0 deletions docs/.readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

build:
os: ubuntu-22.04
tools:
python: "3.10"
jobs:
post_checkout:
# Monorepo guard: cancel the build unless this change touched docs/
- git fetch origin develop --depth 1 || true
- |
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ]; then
BASE=origin/develop # PR build: compare against the develop base
else
BASE=HEAD^ # branch/tag build (latest): compare against previous commit
fi
if git diff --quiet "$BASE" HEAD -- docs/; then
exit 183
fi
python:
install:
- requirements: docs/sphinx/requirements.txt

sphinx:
configuration: docs/conf.py

formats: [htmlzip]
Binary file not shown.
Binary file not shown.
18 changes: 17 additions & 1 deletion docs/_static/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,20 @@ table.rdma-errors td:nth-child(1) {
table.rdma-errors th:nth-child(2),
table.rdma-errors td:nth-child(2) {
width: 60% !important;
}
}

/* Remove white background from topology diagrams in dark mode */
html[data-theme=dark] .bd-content img {
background-color: transparent !important;
}

/* Restore normal brightness for images in dark mode */
html[data-theme=dark] .bd-content img:not(.only-dark,.dark-light) {
filter: brightness(1) contrast(1) !important;
}

/* Add neutral grey background for images in light mode */
html:not([data-theme=dark]) .bd-content img {
background-color: #777 !important;
}

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
36 changes: 15 additions & 21 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@
Cluster network performance validation for AMD Instinct accelerators
********************************************************************

When running HPC and AI applications in a cluster network environment,
performance is only as fast as the slowest individual node in the network. To
achieve optimal performance, each server must be configured for maximum data
transfer rates and bandwidth utilization based on the available hardware. It is
crucial to validate both host and device performance in single-node and
multi-node environments using the appropriate benchmarking tools.

Refer to the relevant networking guides for step-by-step instructions on
validating network configurations in single-node and multi-node environments.
These guides cover system settings, device configurations, networking tools, and
performance tests to ensure AMD Instinct™-powered GPU clusters achieve
optimal speed and bandwidth during operation.
When running HPC and AI applications in a cluster network environment, performance is only as fast as the slowest
individual node in the network. To achieve optimal performance, each server must be configured for maximum data transfer
rates and bandwidth utilization based on the available hardware. It is crucial to validate both host and device
performance in single-node and multi-node environments using the appropriate benchmarking tools.

Refer to the relevant networking guides for step-by-step instructions on validating network configurations in
single-node and multi-node environments. These guides cover system settings, device configurations, networking tools,
and performance tests to ensure AMD Instinct™-powered GPU clusters achieve optimal speed and bandwidth during operation.

.. grid:: 2
:gutter: 3
Expand All @@ -32,15 +28,13 @@ optimal speed and bandwidth during operation.

.. grid-item-card:: Reference

* :doc:`Hardware support <reference/hardware-support>`
* :doc:`Cluster design <reference/cluster-design>`
* :doc:`Hardware support <reference/hardware-support>`


.. note::

AMD Instinct systems vary in form and configuration, and cluster design
adds additional layers of complexity. The guidelines in this
documentation are written at a high level for broad applicability across
diverse environments. While certain scenarios may include specific hardware
examples, your setup will likely differ in terms of GPUs and CPUs per server,
firmware versions, and network interconnects. Adjustments might be necessary
to align with your particular configuration.
AMD Instinct systems vary in form and configuration, and cluster design adds additional layers of complexity. The
guidelines in this documentation are written at a high level for broad applicability across diverse environments.
While certain scenarios may include specific hardware examples, your setup will likely differ in terms of GPUs and
CPUs per server, firmware versions, and network interconnects. Adjustments might be necessary to align with your
particular configuration.
17 changes: 2 additions & 15 deletions docs/reference/cluster-design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,5 @@
Cluster architecture and network design
************************************************************************************************************************

.. grid:: 2
:gutter: 2

.. grid-item-card:: Reference Cluster Design Architecture MI300X/MI325

* `128-1028 GPU Reference Cluster Design <../_static/cluster/128-1024-gpu-reference-cluster-design.pdf>`_
* `1024-8192 GPU Reference Cluster Design <../_static/cluster/1024-8192-gpu-reference-cluster-design.pdf>`_

.. grid-item-card:: Reference Network Design Architecture 3XX

* `3XX-2K Reference Network Design <../_static/network/3XX-2K-reference-network-design.pdf>`_
* `3XX-4K Reference Network Design <../_static/network/3XX-4K-reference-network-design.pdf>`_
* `3XX-6K Reference Network Design <../_static/network/3XX-6K-reference-network-design.pdf>`_
* `3XX-8K Reference Network Design <../_static/network/3XX-8K-reference-network-design.pdf>`_
* `355-4MW Reference Network Design <../_static/network/355-4MW-PPT-reference-network-design.pdf>`_
Cluster architecture and network design materials have been collated and moved to a dedicated page. Please see the `AMD
Instinct MI3XX Reference Design <https://instinct.docs.amd.com/projects/MI3XX-reference/latest/overview.html>`_.
1 change: 0 additions & 1 deletion docs/sphinx/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ subtrees:
title: RoCE network configuration
- file: how-to/troubleshooting
title: Network troubleshooting

- caption: Reference
entries:
- file: reference/hardware-support
Expand Down
1 change: 0 additions & 1 deletion docs/sphinx/_toc.yml.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ subtrees:
title: RoCE network configuration
- file: how-to/troubleshooting
title: Network troubleshooting

- caption: Reference
entries:
- file: reference/hardware-support
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/requirements.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
rocm-docs-core==1.35.0
rocm-docs-core==1.35.0
31 changes: 31 additions & 0 deletions reference-architecture/MI3XX/.readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

build:
os: ubuntu-22.04
tools:
python: "3.10"
jobs:
post_checkout:
# Monorepo guard: cancel the build unless this change touched reference-architecture/MI3XX/
- git fetch origin develop --depth 1 || true
- |
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ]; then
BASE=origin/develop # PR build: compare against the develop base
else
BASE=HEAD^ # branch/tag build (latest): compare against previous commit
fi
if git diff --quiet "$BASE" HEAD -- reference-architecture/MI3XX/; then
exit 183
fi
python:
install:
# Shared across all docsets; dependabot tracks this single file (.github/dependabot.yml)
- requirements: docs/sphinx/requirements.txt

sphinx:
configuration: reference-architecture/MI3XX/conf.py

formats: [htmlzip]
Loading
Loading