diff --git a/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md b/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md index 0079bcf90..b2699cae6 100644 --- a/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md +++ b/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md @@ -68,12 +68,10 @@ graph TD POD --> SCHED --> INJECT --> WEBHOOK --> CONTAINER --> ENFORCE DAEMON -. "loads libvgpu.so" .-> CONTAINER - style SCHED fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style INJECT fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style DAEMON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style CONTAINER fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937 - style ENFORCE fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 + class SCHED,INJECT kai + class WEBHOOK,DAEMON info + class CONTAINER run + class ENFORCE ok ``` The workflow has four phases: @@ -93,8 +91,8 @@ graph TD B2 --> B3["Cannot oversubscribe
hard isolation"] A3 ~~~ B1 - style A3 fill:#fee2e2,stroke:#b3261e,stroke-width:2px,color:#1f2937 - style B3 fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 + class A3 bad + class B3 ok ``` ### Deploy @@ -200,8 +198,8 @@ graph TD HAMI --> Kueue HAMI --> Koordinator - style HAMI fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 + class HAMI info + class KAI accent ``` ### It creates real value for users diff --git a/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md b/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md index 62b1b04f3..766cd8828 100644 --- a/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md +++ b/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md @@ -41,12 +41,10 @@ graph TD LIB -. "provides libvgpu.so" .-> RUN RUN -. "writes node-local cache" .-> MON - style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style LIB fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style RUN fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937 - style ENF fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 - style MON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 + class KAI accent + class WEBHOOK,LIB,MON info + class RUN run + class ENF ok ``` `CUDA_DEVICE_MEMORY_LIMIT` is the contract between scheduling and enforcement. KAI does not need to know how CUDA calls are intercepted, and HAMi-core does not need to know how the quota was calculated. KAI retains its own scheduling logic; it integrates with HAMi-core rather than replacing its scheduler with the full HAMi platform. diff --git a/blog/volcano-ascend-vnpu-soft-slicing/index.md b/blog/volcano-ascend-vnpu-soft-slicing/index.md index e786b57b2..961eadf03 100644 --- a/blog/volcano-ascend-vnpu-soft-slicing/index.md +++ b/blog/volcano-ascend-vnpu-soft-slicing/index.md @@ -124,10 +124,10 @@ graph TD VOL --> SCHD --> HOOK --> ENF HOOK -. "shared-memory accounting" .-> MON - style VOL fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style HOOK fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937 - style ENF fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 - style MON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 + class VOL accent + class HOOK run + class ENF ok + class MON info ``` The Pod contract is minimal: `schedulerName: volcano`, `runtimeClassName: ascend`, the annotation `huawei.com/vnpu-mode: hami-core`, and limits on the two extended resources. Without the annotation, the Pod falls back to the template-based path and can stay Pending on a soft-slicing node. diff --git a/docusaurus.config.js b/docusaurus.config.js index 11f4414e3..0fe3227aa 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -290,6 +290,9 @@ module.exports = { defaultMode: "dark", respectPrefersColorScheme: false, }, + mermaid: { + theme: { light: "default", dark: "dark" }, + }, announcementBar, navbar: { title: "HAMi", diff --git a/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md b/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md index da06580dc..b9d026f46 100644 --- a/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md +++ b/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md @@ -67,12 +67,10 @@ graph TD POD --> SCHED --> INJECT --> WEBHOOK --> CONTAINER --> ENFORCE DAEMON -. "加载 libvgpu.so" .-> CONTAINER - style SCHED fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style INJECT fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style DAEMON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style CONTAINER fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937 - style ENFORCE fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 + class SCHED,INJECT kai + class WEBHOOK,DAEMON info + class CONTAINER run + class ENFORCE ok ``` 工作流程分为四个阶段: @@ -92,8 +90,8 @@ graph TD B2 --> B3["无法超额
硬隔离"] A3 ~~~ B1 - style A3 fill:#fee2e2,stroke:#b3261e,stroke-width:2px,color:#1f2937 - style B3 fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 + class A3 bad + class B3 ok ``` ### 部署方式 @@ -199,8 +197,8 @@ graph TD HAMI --> Kueue HAMI --> Koordinator - style HAMI fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 + class HAMI info + class KAI accent ``` ### 为用户创造实际价值 diff --git a/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md b/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md index 35d4ec23e..8d53815b6 100644 --- a/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md +++ b/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md @@ -41,12 +41,10 @@ graph TD LIB -. "提供 libvgpu.so" .-> RUN RUN -. "写入节点本地缓存" .-> MON - style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style LIB fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 - style RUN fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937 - style ENF fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 - style MON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 + class KAI accent + class WEBHOOK,LIB,MON info + class RUN run + class ENF ok ``` `CUDA_DEVICE_MEMORY_LIMIT` 是调度层与隔离层之间的契约。KAI 不需要知道 CUDA 调用如何被拦截,HAMi-core 也不需要知道配额如何计算。KAI 保留自己的调度逻辑;它集成的是 HAMi-core,而不是用完整的 HAMi 平台替换自身调度器。 diff --git a/i18n/zh/docusaurus-plugin-content-blog/volcano-ascend-vnpu-soft-slicing/index.md b/i18n/zh/docusaurus-plugin-content-blog/volcano-ascend-vnpu-soft-slicing/index.md index 9e191ff25..11c88b99c 100644 --- a/i18n/zh/docusaurus-plugin-content-blog/volcano-ascend-vnpu-soft-slicing/index.md +++ b/i18n/zh/docusaurus-plugin-content-blog/volcano-ascend-vnpu-soft-slicing/index.md @@ -124,10 +124,10 @@ graph TD VOL --> SCHD --> HOOK --> ENF HOOK -. "共享内存记账" .-> MON - style VOL fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937 - style HOOK fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937 - style ENF fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937 - style MON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937 + class VOL accent + class HOOK run + class ENF ok + class MON info ``` Pod 侧的契约很简洁:`schedulerName: volcano`、`runtimeClassName: ascend`、注解 `huawei.com/vnpu-mode: hami-core`,以及对两个扩展资源的 limits。少了这个注解,Pod 会退回模板路径,在纯软切分节点上可能一直 Pending。 diff --git a/src/css/custom.css b/src/css/custom.css index d1a1ad269..1406a7c5d 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -145,6 +145,23 @@ rgba(241, 246, 250, 0.95) ); --hami-diagram-outcome-bg: rgba(255, 255, 255, 0.62); + + /* mermaid class roles: accent, info, run, ok, bad */ + --hami-mermaid-accent-fill: #d9f99d; + --hami-mermaid-accent-stroke: #4f7d00; + --hami-mermaid-accent-text: #1f2937; + --hami-mermaid-info-fill: #dbeafe; + --hami-mermaid-info-stroke: #1a5fb4; + --hami-mermaid-info-text: #1f2937; + --hami-mermaid-run-fill: #fef3c7; + --hami-mermaid-run-stroke: #b45309; + --hami-mermaid-run-text: #1f2937; + --hami-mermaid-ok-fill: #dcfce7; + --hami-mermaid-ok-stroke: #0b6b3c; + --hami-mermaid-ok-text: #1f2937; + --hami-mermaid-bad-fill: #fee2e2; + --hami-mermaid-bad-stroke: #b3261e; + --hami-mermaid-bad-text: #1f2937; } :root[data-theme="dark"] { @@ -247,6 +264,22 @@ ); --hami-diagram-outcome-bg: rgba(255, 255, 255, 0.04); + --hami-mermaid-accent-fill: #365314; + --hami-mermaid-accent-stroke: #a3e635; + --hami-mermaid-accent-text: #ecfccb; + --hami-mermaid-info-fill: #1e3a5f; + --hami-mermaid-info-stroke: #60a5fa; + --hami-mermaid-info-text: #dbeafe; + --hami-mermaid-run-fill: #78350f; + --hami-mermaid-run-stroke: #fbbf24; + --hami-mermaid-run-text: #fef3c7; + --hami-mermaid-ok-fill: #14532d; + --hami-mermaid-ok-stroke: #4ade80; + --hami-mermaid-ok-text: #dcfce7; + --hami-mermaid-bad-fill: #7f1d1d; + --hami-mermaid-bad-stroke: #f87171; + --hami-mermaid-bad-text: #fee2e2; + --ifm-navbar-search-input-icon: url("data:image/svg+xml;utf8,"); } @@ -408,17 +441,17 @@ body.hami-lightbox-open { align-items: center; justify-content: center; overflow: hidden; - background: #ffffff; + background: var(--ifm-background-color); border-radius: 12px; box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45); padding: 16px; cursor: zoom-out; } -/* Mermaid renders a dark-theme variant in dark mode (light text, dark - fills), so the zoom card must follow the color mode or contrast breaks. */ -html[data-theme="dark"] .hami-lightbox__svg { - background: var(--ifm-background-surface-color); +.hami-lightbox__svg .docusaurus-mermaid-container { + width: 100%; + height: 100%; + cursor: zoom-out; } .docusaurus-mermaid-container { @@ -426,6 +459,78 @@ html[data-theme="dark"] .hami-lightbox__svg { text-align: center; } +.docusaurus-mermaid-container svg { + background: transparent !important; +} + +/* mermaid leaves subgraph titles / edge labels dark even on the dark theme */ +.docusaurus-mermaid-container .cluster-label, +.docusaurus-mermaid-container .cluster-label span, +.docusaurus-mermaid-container .cluster span, +.docusaurus-mermaid-container .edgeLabel, +.docusaurus-mermaid-container .edgeLabel span, +.docusaurus-mermaid-container .edgeLabel p { + color: var(--ifm-font-color-base) !important; +} + +.docusaurus-mermaid-container .cluster-label text, +.docusaurus-mermaid-container .edgeLabel text { + fill: var(--ifm-font-color-base) !important; +} + +.docusaurus-mermaid-container .edgeLabel, +.docusaurus-mermaid-container .edgeLabel p, +.docusaurus-mermaid-container .labelBkg { + background-color: var(--ifm-background-color) !important; +} + +.docusaurus-mermaid-container .edgeLabel rect { + background-color: var(--ifm-background-color) !important; + fill: var(--ifm-background-color) !important; +} + +.docusaurus-mermaid-container .accent { + --hami-mermaid-node-fill: var(--hami-mermaid-accent-fill); + --hami-mermaid-node-stroke: var(--hami-mermaid-accent-stroke); + --hami-mermaid-node-text: var(--hami-mermaid-accent-text); +} + +.docusaurus-mermaid-container .info { + --hami-mermaid-node-fill: var(--hami-mermaid-info-fill); + --hami-mermaid-node-stroke: var(--hami-mermaid-info-stroke); + --hami-mermaid-node-text: var(--hami-mermaid-info-text); +} + +.docusaurus-mermaid-container .run { + --hami-mermaid-node-fill: var(--hami-mermaid-run-fill); + --hami-mermaid-node-stroke: var(--hami-mermaid-run-stroke); + --hami-mermaid-node-text: var(--hami-mermaid-run-text); +} + +.docusaurus-mermaid-container .ok { + --hami-mermaid-node-fill: var(--hami-mermaid-ok-fill); + --hami-mermaid-node-stroke: var(--hami-mermaid-ok-stroke); + --hami-mermaid-node-text: var(--hami-mermaid-ok-text); +} + +.docusaurus-mermaid-container .bad { + --hami-mermaid-node-fill: var(--hami-mermaid-bad-fill); + --hami-mermaid-node-stroke: var(--hami-mermaid-bad-stroke); + --hami-mermaid-node-text: var(--hami-mermaid-bad-text); +} + +.docusaurus-mermaid-container + :is(.accent, .info, .run, .ok, .bad) + > :is(rect, polygon, circle, ellipse, path) { + fill: var(--hami-mermaid-node-fill) !important; + stroke: var(--hami-mermaid-node-stroke) !important; + stroke-width: 2px !important; +} + +.docusaurus-mermaid-container :is(.accent, .info, .run, .ok, .bad) :is(.nodeLabel, span) { + color: var(--hami-mermaid-node-text) !important; +} + .mermaid-figure { margin: 0 0 1.5rem; text-align: center; diff --git a/src/theme/utils/useImageLightbox.js b/src/theme/utils/useImageLightbox.js index 46646c155..e72d05eef 100644 --- a/src/theme/utils/useImageLightbox.js +++ b/src/theme/utils/useImageLightbox.js @@ -116,13 +116,21 @@ function ensureLightbox() { const clone = svg.cloneNode(true); // Mermaid caps the inline SVG at its rendered size; lift the cap and let // it scale to fit the lightbox box in both dimensions (the viewBox keeps - // the aspect ratio), so the whole diagram is visible without scrolling. + // the aspect ratio), so the whole diagram is always visible without scrolling. clone.style.maxWidth = "none"; clone.style.width = "100%"; clone.style.height = "100%"; clone.removeAttribute("height"); clone.removeAttribute("width"); - svgHost.replaceChildren(clone); + + // Node colors are CSS under .docusaurus-mermaid-container. Keep the clone + // in that same host so the zoomed view matches the page. + const wrap = document.createElement("div"); + const source = svg.closest(MERMAID_CONTAINER); + wrap.className = source?.className || "docusaurus-mermaid-container"; + wrap.appendChild(clone); + + svgHost.replaceChildren(wrap); svgHost.hidden = false; lightboxImage.hidden = true; lightboxImage.removeAttribute("src");