fix: Rewrite Cisco and OnLogic docs

This commit is contained in:
tomnewton-mulga
2026-08-21 14:05:34 +10:00
parent 3bb35deea2
commit e22db02d24
5 changed files with 1535 additions and 1504 deletions
@@ -1,23 +1,26 @@
---
title: "Single-Node Spinifex on OnLogic HX401"
seoTitle: "Single-Node Spinifex on OnLogic HX401 — Spinifex Docs"
description: "Run a complete EC2, EBS, and S3 stack on one fanless OnLogic HX401 edge node, and measure what the platform layer costs compared with bare-metal baselines."
description: "EC2, EBS and S3 on a single fanless OnLogic HX401 — the full Spinifex service set on a passive-cooled industrial node for factory and remote edge deployments."
category: "Reference Architectures"
tags:
- onlogic
- hx401
- edge
- single-node
- benchmarks
- viperblock
- predastore
resources:
- title: "Installation"
- title: "Single-Node Install"
url: "/docs/install"
- title: "VPC Networking"
url: "/docs/vpc-networking"
- title: "Launching Instances"
url: "/docs/launching-instances"
- title: "OnLogic HX401"
url: "https://www.onlogic.com/hx401/"
- title: "Benchmark data and platform notes (OnLogic-refarch)"
url: "https://github.com/tomnewton-mulga/OnLogic-refarch"
sections:
- overview
- prerequisites
@@ -26,11 +29,9 @@ sections:
## Overview
Spinifex is an open-source infrastructure platform that brings core AWS services — EC2, EBS and S3 — to bare-metal, edge and on-prem environments. It exposes an EC2-compatible API, so tooling that works against AWS (the `aws` CLI, Terraform, SDKs) works against a Spinifex node unchanged, with a single profile swap.
The [OnLogic HX401](https://www.onlogic.com/hx401/) is a fanless, passive-cooled industrial edge computer that runs the complete Spinifex service set — EC2, EBS, S3 and VPC networking — in a form factor small enough to panel-mount inside a factory cabinet, attach to a DIN rail in a control room, or deploy unattended at a remote site without active cooling or rack infrastructure. Spinifex exposes EC2, EBS and S3-compatible APIs on the node, so the operational model is unchanged from AWS: use the `aws` CLI, SDKs, Terraform or OpenTofu, and CI/CD pipelines already used for cloud workloads. The change is the endpoint, not the workflow.
This document covers a node deployment of Spinifex on the OnLogic HX401. The OnLogic HX401 is a fanless industrial box with 12 physical cores and 31 GiB of RAM — enough to run the full service set and still host a meaningful guest.
The goal of this deployment is to measure what the platform costs against bare metal — CPU overhead from virtualisation, guest block storage throughput, and S3 data-path performance. The same benchmark suite was run against both Spinifex v1.15.0 and v1.16.0 on the same hardware, to help the team quantify the efficacy of the new releases's fixes and improvements.
Single-node removes the distributed-storage guarantees of a multi-node cluster — Predastore runs RS(1,0) on one disk, so there is no erasure-coded redundancy. For edge deployments where data is generated locally, processed on-node, and shipped upstream on a schedule, or where the box provides compute capacity next to a sensor or control network rather than acting as a primary data store, this is the expected and appropriate configuration.
<p align="center"><img src="../../../.github/assets/images/onlogic/HX401.png" alt="OnLogic HX401 fanless edge node"></p>
@@ -38,25 +39,33 @@ The goal of this deployment is to measure what the platform costs against bare m
| Component | Specification |
|---|---|
| **Bare-metal host** | OnLogic HX401 |
| **Bare-metal host** | [OnLogic HX401](https://www.onlogic.com/hx401/) — fanless, passive-cooled industrial edge computer |
| **CPU** | Intel i5-1250PE — 12 physical cores / 16 threads |
| **Memory** | 31 GiB |
| **Storage** | Transcend TS256GMTE652T2, 256 GB NVMe (PCIe Gen3 x4) |
| **Networking** | 2× Intel GbE (I210-IT + I219-LM) |
| **Host OS** | Debian 13 |
| **Orchestration** | Spinifex v1.16.0 — EC2-compatible bare-metal API |
| **Guest OS** | Ubuntu 26.04 LTS |
| **Instance type** | `c6i.2xlarge` — 8 vCPU, 16 GiB |
| **Block storage** | Viperblock — EBS-compatible, local NVMe-backed |
| **Object storage** | Predastore — S3-compatible, RS(1,0) on a single node |
| **Networking** | OVN, standalone NB/SB on the node itself |
| **Form factor** | Fanless, passive-cooled; DIN rail, wall and VESA mountable |
## Architecture
### AWS services exercised
| Service | Role |
|---|---|
| **EC2** | Guest instances on the host NVMe; no spread placement groups on a single node |
| **EBS (Viperblock)** | Local NVMe-backed block volumes per instance, surviving termination independently when `delete_on_termination = false` |
| **S3 (Predastore)** | RS(1,0) single-node object storage — no erasure-coding overhead, no distributed redundancy |
| **VPC (OVN)** | Standalone OVN northbound/southbound databases on the node itself |
## Prerequisites
- OnLogic HX401 (or comparable x86 node) running **Debian 13** or **Ubuntu 26.04 LTS**
- The WAN interface enslaved to a Linux bridge named `br-wan` — the host IP, default route and DHCP must live on the bridge, not the bare NIC
- A reserved range of addresses on your LAN for guest instances (this deployment uses `192.168.157.201-250`)
- AWS CLI installed
- A reserved range of addresses on your LAN for guest instances — this deployment uses `192.168.157.201-250`
- AWS CLI configured with `AWS_PROFILE=spinifex` pointing at the node's EC2-compatible endpoint (`https://<host>:9999`)
Verify the bridge before installing:
@@ -67,11 +76,11 @@ ip route
## Instructions
### 1. Install Spinifex and initialise the node
### 1. Install Spinifex and verify the node
Follow the [Single Node Install](/docs/install) guide, using `--nodes 1` to select the single-node templates — RS(1,0) storage and a one-member NATS.
Follow the [Single-Node Install](/docs/install) guide, using `--nodes 1` to select the single-node templates — RS(1,0) storage and a single-member NATS cluster.
**Set a static external pool.** `init` auto-detects the external network and will select `source = "dhcp"` when the host itself holds a DHCP lease. That does not work for guests on every network: the upstream server answers the host on `br-wan` but does not necessarily offer to guest ENI MAC addresses, and instance launches then fail with
**Set a static external pool.** `init` auto-detects the external network and selects `source = "dhcp"` when the host holds a DHCP lease. That does not work for guests on every network: the upstream DHCP server answers the host on `br-wan` but does not necessarily offer addresses to guest ENI MAC addresses, causing instance launches to fail with:
```text
PrepareRunInstances: public IP allocation failed — aborting launch
@@ -91,7 +100,7 @@ prefix_len = 24
dns_servers = ["1.1.1.1", "8.8.8.8"]
```
See the [VPC Networking](/docs/vpc-networking) guide for full configuration options. Then start the platform and verify:
See the [VPC Networking](/docs/vpc-networking) guide for full configuration options. Then start the platform and confirm the node is ready:
```bash
sudo systemctl start spinifex.target
@@ -103,187 +112,156 @@ NAME | STATUS | ROLES | IP | REGION | AZ
node1 | Ready | nats:leader | 192.168.157.134 | ap-southeast-2 | ap-southeast-2a | 0 | nats,predastore,viperblock,daemon,awsgw,vpcd,ui
```
### 2. Establish the bare-metal baseline
All services — Predastore, Viperblock, and the OVN databases — run on the single node. There is no Raft group to converge and no leader election to wait for.
Benchmark the host before launching anything, with the platform idle. Without this, a slow guest result cannot be attributed to the platform rather than the hardware.
### 2. Launch instances through the EC2-compatible API
This uses `spx-bench.sh` — the same script is run on the host and inside the guest so the two results diff directly. It measures CPU (sysbench), memory, and disk (fio: `randrw` 70/30 4k, `randread` 4k, `seqread` 1M, `seqwrite` 1M, all at 4 jobs / iodepth 32 / `direct=1`).
Point an existing AWS profile at the Spinifex endpoint and use the standard EC2 instance lifecycle:
```bash
export AWS_PROFILE=spinifex
aws ec2 run-instances \
--image-id "$AMI" --instance-type c6i.2xlarge \
--count 1 \
--subnet-id "$SUBNET" --security-group-ids "$SECURITY_GROUP" \
--key-name "$KEY_NAME"
```
`c6i.2xlarge` provisions 8 vCPU and 16 GiB from the host's 12 cores and 31 GiB, leaving headroom for the platform services. On a single node there are no spread placement groups — all instances land on the same physical host, which is expected.
### 3. Attach Viperblock volumes and access Predastore object storage
Create and attach a dedicated data volume. The default root volume on the stock Ubuntu AMI is 4 GiB — too small for most workloads. Attach a separate volume and benchmark or write data there:
```bash
VOLUME_ID=$(aws ec2 create-volume \
--availability-zone ap-southeast-2a \
--size 30 --volume-type gp2 \
--query VolumeId --output text)
aws ec2 attach-volume \
--volume-id "$VOLUME_ID" \
--instance-id "$INSTANCE_ID" \
--device /dev/sdf
```
Inside the guest, format and mount:
```bash
sudo mkfs.ext4 -q -L data /dev/vdb
sudo mkdir -p /mnt/data && sudo mount /dev/vdb /mnt/data
```
Setting `delete_on_termination = false` in Terraform keeps the volume alive across instance replacement — relaunching a terminated instance re-attaches the same volume rather than starting from empty storage:
```hcl
resource "aws_ebs_volume" "data" {
availability_zone = var.az
size = 30
type = "gp2"
}
resource "aws_volume_attachment" "data" {
device_name = "/dev/sdf"
volume_id = aws_ebs_volume.data.id
instance_id = aws_instance.worker.id
delete_on_termination = false
}
```
Predastore presents an S3-compatible endpoint — standard S3 tooling works without modification:
```bash
aws s3 mb s3://my-bucket
aws s3 cp ./data.tar.gz s3://my-bucket/
aws s3 sync ./results/ s3://my-bucket/results/
```
### 4. Storage benchmark
Run this after setup or hardware changes to confirm both storage services are performing as expected. The methodology: fio against an ext4-formatted Viperblock data volume (four jobs, iodepth 32, direct I/O, 30-second run), with a bare-metal host baseline run first so the two results diff directly using the same `spx-bench.sh` script.
**Host bare-metal baseline** (platform idle, no guests):
```bash
./spx-bench.sh --tag host-baremetal
```
```text
--- 2. CPU (sysbench, events/sec — higher is better) ------------
--- CPU (sysbench, events/sec) ---------------------------------
threads=1 1456.50 events/s 95th 0.70 ms
threads=16 12822.85 events/s 95th 2.00 ms
--- 3. Memory --------------------------------------------------
random write, 16 threads: 1555.84 MiB/sec
--- 4. Disk (file-backed, NVMe root) ---------------------------
randrw 70/30 4k read 66,169 IOPS 258 MiB/s p99 10.42 ms
randrw 70/30 4k write 28,426 IOPS 111 MiB/s p99 0.72 ms
randread 4k read 171,326 IOPS 669 MiB/s p99 2.06 ms
seqread 1M read 1,818 IOPS 1,818 MiB/s p99 128.45 ms
seqwrite 1M write 308 IOPS 308 MiB/s p99 1115.68 ms
--- Disk (fio, NVMe root) --------------------------------------
randrw 70/30 4k read 66,169 IOPS 258 MiB/s
randrw 70/30 4k write 28,426 IOPS 111 MiB/s
randread 4k read 171,326 IOPS 669 MiB/s
seqread 1M read 1,818 MiB/s
seqwrite 1M write 308 MiB/s
```
### 3. Launch a guest instance
```bash
aws ec2 run-instances \
--image-id "$AMI" --instance-type c6i.2xlarge \
--key-name onlogic --security-group-ids "$SG" --subnet-id "$SUBNET"
```
**Attach a data volume for the benchmark.** The stock `ubuntu-26.04-x86_64` AMI declares a 4 GiB root which fills just installing benchmark tools, and `run-instances` does not grow it without explicit `--block-device-mappings`. Every fio job fails with `ENOSPC` if you benchmark the root. Attach a gp3 volume instead, which is also the more representative target:
```bash
VOL=$(aws ec2 create-volume --availability-zone ap-southeast-2a \
--size 30 --volume-type gp3 --query VolumeId --output text)
aws ec2 attach-volume --volume-id "$VOL" --instance-id "$ID" --device /dev/vdb
```
```bash
# in the guest
sudo mkfs.ext4 -q -L bench /dev/vdb
sudo mkdir -p /mnt/bench && sudo mount /dev/vdb /mnt/bench
```
### 4. Measure the guest
**Guest** (`c6i.2xlarge`, 8 vCPU, attached gp2 volume):
```bash
BENCHDIR=/mnt/bench ./spx-bench.sh --tag guest --require-mount
```
```text
--- 2. CPU (sysbench, events/sec — higher is better) ------------
threads=1 1357.98 events/s 95th 0.75 ms
threads=8 8608.31 events/s 95th 1.06 ms
--- 3. Memory --------------------------------------------------
random write, 8 threads: 1133.25 MiB/sec
```
### 5. Measure the S3 data path
Predastore's S3 API listens on port `8443`. This is **not** the general AWS gateway endpoint on `9999`.
```bash
./s3-bench.sh 256 # 256 MB object, write + read + checksum verify
```
## Results
### CPU and memory
| | host | guest | guest/host |
|---|---|---|---|
| sysbench, 1 thread | 1,456 events/s | 1,358 events/s | **93.2%** |
| sysbench, all threads | 12,823 (16t) | 8,608 (8t) | not comparable |
| Memory random write | 1,556 MiB/s (16t) | 1,133 MiB/s (8t) | not comparable |
Single thread is the only directly comparable row, and **93.2% of bare metal** is the headline CPU number — roughly 7% single-thread virtualisation overhead. The multi-thread and memory rows use different thread counts (16 on the host, 8 in the guest) and are listed for completeness, not as ratios.
<p align="center"><img src="images/cpu-comparison.png" alt="sysbench single-thread: host 1,456 events/s vs guest 1,358 events/s (93.2%)"></p>
### Storage
Median of three runs. Guest measured on the attached gp3 volume.
| Test | host | guest | guest/host |
|---|---|---|---|
| randrw 70/30 4k read | 66,169 IOPS | 6,860 IOPS | 10.4% |
| randrw 70/30 4k write | 28,426 IOPS | 2,951 IOPS | 10.4% |
| Test | Host | Guest | Guest/Host |
|---|---:|---:|---:|
| sysbench single-thread | 1,456 events/s | 1,358 events/s | **93.2%** |
| randrw 4k read | 66,169 IOPS | 6,860 IOPS | 10.4% |
| randrw 4k write | 28,426 IOPS | 2,951 IOPS | 10.4% |
| randread 4k | 171,326 IOPS | 9,263 IOPS | 5.4% |
| seqread 1M | 1,818 MiB/s | 484 MiB/s | 26.6% |
| seqwrite 1M | 308 MiB/s | 73 MiB/s | 23.7% |
The block path is where virtualisation costs real throughput. Sequential work retains roughly a quarter of bare metal; small random I/O retains between a twentieth and a tenth.
<p align="center">
<img src="images/storage-iops-comparison.png" alt="Random I/O IOPS: host vs guest">
<img src="images/storage-seq-comparison.png" alt="Sequential throughput MiB/s: host vs guest">
<img src="images/cpu-comparison.png" alt="sysbench single-thread: host 1,456 events/s vs guest 1,358 events/s (93.2%)">
</p>
**Read the guest storage figures with their variance, not as point values.** Across three runs:
Guest CPU lands at **93.2% of bare metal** — roughly 7% single-thread virtualisation overhead, a result that reproduced on separate hardware. Block storage reflects the cost of the current single-queue virtio-blk path and unthreaded NBD backend sharing a single 256 GB NVMe between the host OS, platform services, and guest volumes; these are the same implementation constraints as on the Cisco cluster, expressed more sharply on constrained hardware.
| Test | run 1 | run 2 | run 3 | spread |
|---|---|---|---|---|
Variance across three runs is notable for two metrics:
| Test | Run 1 | Run 2 | Run 3 | Spread |
|---|---:|---:|---:|---:|
| randrw 4k read | 7,321 | 6,424 | 6,860 | 14% |
| randread 4k | 9,959 | **3,813** | 9,263 | **2.6×** |
| seqread 1M | 518 | 484 | 453 | 14% |
| seqwrite 1M | 83 | 73 | **31** | **2.7×** |
| seqwrite p99 | 7.95 s | 7.28 s | **15.90 s** | 2.2× |
<p align="center"><img src="images/storage-variance.png" alt="Guest storage variance across 3 runs: randread and seqwrite show bimodal behaviour"></p>
<p align="center">
<img src="images/storage-iops-comparison.png" alt="Random I/O IOPS: host vs guest">
<img src="images/storage-seq-comparison.png" alt="Sequential throughput MiB/s: host vs guest">
<img src="images/storage-variance.png" alt="Guest storage variance across 3 runs: randread and seqwrite show bimodal behaviour">
</p>
`randread` and `seqwrite` are bimodal rather than noisy around a mean — one run in three falls to roughly a third of its neighbours. The likely mechanism is a viperblock WAL flush or a Predastore compaction cycle landing inside some runs and not others. Anything below about a 3× change in those two metrics is not resolvable at this sample size.
`randread` and `seqwrite` are bimodal rather than noisy — one run in three falls to roughly a third of its neighbours, likely a Viperblock WAL flush or Predastore compaction cycle intersecting some runs but not others. Treat those two as directionally correct rather than stable point values at this sample size. The `seqwrite` p99 reaching 7–16 seconds is worth noting for write-heavy workloads.
`seqwrite` p99 reaching 7-16 seconds is worth attention before committing this platform to write-heavy edge workloads.
**Predastore S3 validation** (256 MiB objects, three runs, write + read + checksum verify):
## Release comparison: v1.15.0 vs v1.16.0
Both releases were built from their release tags and installed on the same machine, each with a full re-initialisation, an identical `c6i.2xlarge` guest, and an identical 30 GiB gp3 volume. Three runs each.
### S3 / Predastore
| | v1.15.0 | v1.16.0 | change |
|---|---|---|---|
| write | 77.7 / 75.5 / 72.0 → **75.5 MiB/s** | 146.6 / 142.0 / 148.2 → **146.6 MiB/s** | **1.94× faster** |
| read | 249.9 / 234.9 / 243.8 → **243.8 MiB/s** | 298.1 / 301.8 / 290.9 → **298.1 MiB/s** | **1.22× faster** |
Checksums matched on every run. Run-to-run spread is about 4%, so both differences are far outside the noise.
**The mechanism is a changed default, not a faster code path.** On a single node:
```text
v1.15.0 [rs] data = 2, parity = 1 6 host entries
v1.16.0 [rs] data = 1, parity = 0 1 host entry
```bash
./s3-bench.sh 256
```
v1.15.0 splits every object into two data shards plus a parity shard and writes all three to the same disk — 1.5× write amplification plus the erasure-coding cost, buying no redundancy, because there is only one machine to lose. v1.16.0 ships a single-node storage template that does none of that.
The write path gains most (1.94×), which is what removing amplification and parity computation predicts. Reads gain less (1.22×) because the read path never had to reconstruct anything, only reassemble shards.
Anyone still running v1.15.0 on a single node should note that this is a configuration change as much as a software one.
| | v1.15.0 | v1.16.0 | Change |
|---|---:|---:|---:|
| Write | 75.5 MiB/s | 146.6 MiB/s | **1.94×** |
| Read | 243.8 MiB/s | 298.1 MiB/s | **1.22×** |
<p align="center"><img src="images/s3-version-comparison.png" alt="S3 throughput: v1.15.0 vs v1.16.0 — 1.94× write, 1.22× read"></p>
### Guest block path
The v1.16.0 write improvement comes from the single-node storage template switching to RS(1,0): v1.15.0 split every object into two data shards plus a parity shard and wrote all three to the same disk, paying 1.5× write amplification for redundancy a single-node cluster cannot deliver. The read gain is smaller because the read path never had to reconstruct anything. All checksum validations passed on every run.
Medians of three runs, with the full range in brackets.
Raw fio output, S3 results, and the v1.15 / v1.16 annotated comparisons are in the
[benchmark repository](https://github.com/tomnewton-mulga/OnLogic-refarch).
| Test | v1.15.0 | v1.16.0 | v1.16 gain |
|---|---|---|---|
| randrw 70/30 4k read | **5,075** IOPS [4,104-6,236] | **6,860** IOPS [6,424-7,321] | 1.35× |
| randrw 70/30 4k write | **2,191** IOPS [1,771-2,684] | **2,951** IOPS [2,764-3,147] | 1.35× |
| randread 4k | **6,658** IOPS [4,881-6,813] | **9,263** IOPS [3,813-9,959] | 1.39× |
| seqread 1M | **387** MiB/s [370-402] | **484** MiB/s [453-518] | 1.25× |
| seqwrite 1M | **52** MiB/s [40-58] | **73** MiB/s [31-83] | 1.40× |
| seqwrite p99 | **13.89 s** [13.76-17.11] | **7.95 s** [7.28-15.90] | 1.75× lower |
## What this architecture unlocks
<p align="center"><img src="images/block-path-version-comparison.png" alt="Guest block path: v1.15.0 vs v1.16.0 with full run ranges"></p>
v1.16.0 is ahead on every median, by 1.25× to 1.40×. For `randrw` read, `randrw` write and `seqread` the two ranges **do not overlap at all**, so those differences are credible despite only three runs each. For `randread` and `seqwrite` the ranges do overlap — entirely because of v1.16.0's bimodal low outliers — so treat those two as directionally consistent rather than demonstrated.
This is the indirect effect of the storage template change. Viperblock's own code is unchanged between the releases, but it writes through Predastore, so removing the 1.5× write amplification and parity computation underneath reduces the work behind every guest block flush as well.
## Teardown
```bash
aws ec2 terminate-instances --instance-ids "$ID"
aws ec2 delete-volume --volume-id "$VOL" # after the instance is terminated
aws ec2 delete-security-group --group-id "$SG"
```
Terminate instances before deleting attached volumes — the volume detaches with the instance, not before it.
## Conclusion
A single OnLogic HX401 runs the complete Spinifex service set — EC2, EBS, S3, VPC networking and DNS — and hosts an 8 vCPU guest with room to spare. Guest CPU performance lands at **93.2% of bare metal**, a figure that reproduced on separate hardware.
The release comparison is the most actionable result here. Moving from v1.15.0 to v1.16.0 on identical hardware gave **1.94× S3 write throughput** and **1.25-1.40× on every guest block metric** — not because the data paths were rewritten, but because the single-node storage template stopped erasure-coding data across a machine that has only one disk. v1.15.0 wrote two data shards and a parity shard to the same NVMe, paying 1.5× write amplification and the encode cost for redundancy it could never deliver.
Every operation in this document used standard `aws ec2` and `aws s3api` calls against Spinifex's EC2-compatible endpoint. Teams already operating AWS tooling can point it at an edge node with a profile change.
- **Cloud tooling at the edge:** run EC2, EBS and S3 workflows on hardware that fits inside a panel, on a DIN rail, or in a small enclosure at a factory, retail site, branch or remote location — without a rack, a UPS, or active cooling.
- **No-moving-parts reliability:** the fanless passive-cooled design tolerates dusty, vibration-prone, or thermally variable environments where server-class hardware is impractical to operate or maintain.
- **Familiar operations:** keep AWS CLI profiles, Terraform or OpenTofu modules, SDKs and deployment pipelines rather than adopting a separate edge-only platform.
- **Local processing with S3 access:** workloads running in EC2-compatible instances read from and write to Predastore over the standard S3 API — sensor data, inference outputs and logs remain on-node until explicitly synced upstream.
- **A path back to cloud:** the same AWS API surface at the edge and on AWS makes workload movement, cloud burst, and consistent application packaging straightforward — the profile swap that points tooling at the HX401 is the same one that points it back at AWS.
@@ -18,12 +18,12 @@ resources:
url: "/docs/launching-instances"
- title: "GPU Passthrough"
url: "/docs/gpu-passthrough"
- title: "Platform benchmark (companion document)"
- title: "Cisco UCS: AWS-compatible cloud at the edge (companion document)"
url: "../cisco-ucs-platform-benchmark/README.md"
- title: "Vision pipeline (companion document)"
url: "../cisco-ucs-vision-pipeline/README.md"
- title: "cisco-ucs-llm-serving (benchmark scripts and results)"
url: "https://github.com/mulgadc/cisco-ucs-llm-serving"
- title: "Benchmark and workload materials (CISCO-refarch)"
url: "https://github.com/tomnewton-mulga/CISCO-refarch"
- title: "vLLM"
url: "https://docs.vllm.ai"
- title: "Qwen2.5-7B-Instruct"
@@ -45,7 +45,7 @@ cluster, comparing Intel AMX-accelerated CPU serving on an `m8i.2xlarge`-class i
against NVIDIA L4 GPU serving on a `g6.2xlarge`-class instance — a real,
production-representative LLM-serving stack, with the two accelerators measured independently at matched model, version, and serving configuration.
**Companion documents:** [Spinifex Platform Benchmark on Cisco UCS](../cisco-ucs-platform-benchmark/README.md) · [Spinifex Vision Pipeline on Cisco UCS](../cisco-ucs-vision-pipeline/README.md)
**Companion architectures:** [Cisco UCS: AWS-compatible cloud at the edge](../cisco-ucs-platform-benchmark/README.md) · [Spinifex Vision Pipeline on Cisco UCS](../cisco-ucs-vision-pipeline/README.md)
### Platform
@@ -1,14 +1,15 @@
---
title: "Spinifex Platform Benchmark on Cisco UCS (3-Node)"
seoTitle: "Spinifex Benchmark on 3-Node Cisco UCS — Spinifex Docs"
description: "Measured CPU, disk, network, and S3 performance of Spinifex on a 3-node Cisco Unified Edge cluster, comparing host against guest with Intel AMX confirmed."
title: "Cisco UCS: AWS-compatible cloud at the edge"
seoTitle: "Cisco UCS Edge Cloud with Spinifex — Spinifex Docs"
description: "Place EC2 instances, EBS volumes, S3 object storage and Kubernetes workloads on a resilient three-node Cisco UCS cluster, using familiar AWS APIs and tooling."
category: "Reference Architectures"
tags:
- cisco
- ucs
- edge
- aws-compatible
- xeon-6
- intel-amx
- benchmark
- predastore
- viperblock
- raft
@@ -21,12 +22,8 @@ resources:
url: "/docs/launching-instances"
- title: "GPU Passthrough"
url: "/docs/gpu-passthrough"
- title: "AWS: Accelerate CPU-based AI inference with Intel AMX on EC2"
url: "https://aws.amazon.com/blogs/compute/accelerate-cpu-based-ai-inference-workloads-using-intel-amx-on-amazon-ec2/"
- title: "cisco-ucs-platform-benchmark (benchmark scripts and results)"
url: "https://github.com/mulgadc/cisco-ucs-platform-benchmark"
- title: "Dell EMC PowerEdge R7525 Review (inspiration for methodology)"
url: "https://www.servethehome.com/dell-emc-poweredge-r7525-review-flagship-dell-dual-socket-server-amd-epyc/4/"
- title: "cisco-ucs-platform-benchmark (scripts and raw results)"
url: "https://github.com/tomnewton-mulga/CISCO-refarch"
sections:
- overview
- prerequisites
@@ -35,16 +32,14 @@ sections:
## Overview
Spinifex is an open-source infrastructure platform that brings core AWS services — EC2,
S3, EBS and EKS — to bare-metal, edge, and on-prem deployments, exposing a fully
AWS-compatible API.
This reference architecture turns three Cisco Unified Edge servers into a small,
resilient cloud that can run where data is produced: a factory, retail estate,
branch, lab, sovereign environment, or disconnected site. Spinifex exposes EC2,
EBS, S3 and EKS-compatible APIs on the cluster, so the operational model is
familiar: use the AWS CLI, SDKs, Terraform or OpenTofu, Kubernetes manifests and
CI/CD systems already used for AWS. The change is the endpoint, not the workflow.
This document characterizes the platform itself on a 3-node Cisco Unified Edge cluster,
independent of any specific application: CPU, disk, network, and S3 (Predastore)
throughput measured identically on bare metal and inside guest instances, and how many
concurrent worker processes each instance can sustain before latency degrades.
**Companion documents:** [Spinifex Vision Pipeline on Cisco UCS](../cisco-ucs-vision-pipeline/README.md) · [vLLM Serving on Cisco UCS: Intel AMX vs NVIDIA L4](../cisco-ucs-llm-serving/README.md)
**Companion architectures:** [Vision Pipeline on Cisco UCS](../cisco-ucs-vision-pipeline/README.md) shows a local AI pipeline that streams inputs from S3; [vLLM Serving on Cisco UCS](../cisco-ucs-llm-serving/README.md) shows CPU and GPU model serving on the same cluster.
### Platform
@@ -56,185 +51,243 @@ concurrent worker processes each instance can sustain before latency degrades.
| **ISA** | AVX-512 (F/DQ/BW/VL/VNNI/BF16/FP16), **Intel AMX** (tile/BF16/INT8), VT-x, VT-d |
| **Memory** | 499 GiB usable per node (≈1.5 TiB aggregate) |
| **GPU** | 1× NVIDIA L4 (23,034 MiB) via VFIO PCIe passthrough on one node; the other two nodes are CPU-only |
| **Storage** | 4× KIOXIA CD8P NVMe (1.92 TB each) per node, raw — Predastore/Viperblock claim these directly |
| **Storage** | 4× KIOXIA CD8P NVMe (1.92 TB each) per node, raw — Predastore and Viperblock claim these directly |
| **Boot** | Cisco SATA RAID VD (Marvell 88SE9230 controller) |
| **Network** | 2× Intel E825-C 25GbE ports per node, each its own bond: one for management/WAN (VLAN 1337, 1 Gbps upstream uplink), one dedicated to storage/cluster traffic (VLAN 1336, full 25GbE) |
| **Network** | 2× Intel E825-C 25GbE ports per node — one bond for management/WAN (VLAN 1337), one dedicated to storage/cluster traffic (VLAN 1336, full 25GbE) |
| **Aggregate** | 96 cores / 192 threads, ~1.5 TiB RAM, ~23 TiB raw NVMe, 1× L4 GPU |
Single-NUMA-per-node is a meaningful simplification versus a typical dual-socket
reference design — no vCPU/memory locality tuning required for VM placement. The GPU is
present on one node only — GPU-accelerated instances are bound to that node, while
CPU-only instances can schedule across all three.
Single-NUMA-per-node simplifies placement — no vCPU/memory locality tuning required.
GPU workloads schedule to the L4 node; CPU instances can use all three. Storage and
object data are distributed across the cluster rather than tied to the node that
launched an instance.
## Architecture
### AWS services exercised
| Service | Role |
|---|---|
| **EC2** | Guest instances across all three nodes; spread placement groups distribute across physical nodes |
| **EBS (Viperblock)** | Root and data volumes per instance, surviving termination independently when `delete_on_termination = false` |
| **S3 (Predastore)** | Cluster-wide object storage for datasets, model weights, artifacts and backups |
| **VPC (OVN)** | Overlay networking between instances |
| **EKS** | (Optional) Kubernetes control plane with pod rescheduling on node failure |
## Prerequisites
- 3-node Spinifex cluster installed and services healthy on all nodes — follow the [Multi-Node Install](/docs/install-multi-node) guide.
- VPC, network pool, SSH key pair, and security group configured — see [VPC Networking](/docs/vpc-networking) and [Launching Instances](/docs/launching-instances)
- GPU passthrough configured on the one node with the NVIDIA L4 — see [GPU Passthrough](/docs/gpu-passthrough):
- VPC, subnet, network address pool, SSH key pair, and security group configured — see [VPC Networking](/docs/vpc-networking) and [Launching Instances](/docs/launching-instances).
- GPU passthrough enabled on the L4 node when GPU instances are required — see [GPU Passthrough](/docs/gpu-passthrough):
```bash
sudo spx admin gpu setup # reboot required after this step
sudo spx admin gpu enable
```
- AWS CLI configured with `AWS_PROFILE=spinifex` pointing at the cluster's EC2-compatible endpoint
- AWS CLI configured with `AWS_PROFILE=spinifex` pointing at the cluster's EC2-compatible endpoint (`https://<host>:9999`).
## Instructions
Benchmark scripts and raw results for all sections below are available in the
[platform benchmark repository](https://github.com/mulgadc/cisco-ucs-platform-benchmark).
### 1. Verify the cluster and its control plane
### 1. Matched-width CPU
sysbench, identical thread counts, run on bare metal and inside a guest of the same vCPU
width:
| Scope | Target | Median events/s |
|---|---|---:|
| host | mulga-01 | 8,205.4 |
| host | mulga-02 | 8,209.3 |
| host | mulga-03 | 8,210.4 |
| guest | cpu1 | 8,168.4 |
| guest | cpu2 | 8,174.0 |
| guest | gpu | 8,160.8 |
Guests land within ~0.5% of host — virtualization overhead on this platform is
negligible for CPU-bound work.
### 2. Confirm Intel AMX is actually executing
Intel AMX (Advanced Matrix Extensions) is a relatively new instruction set available on
the Xeon 6543P-B, designed specifically to accelerate the matrix operations that dominate
AI inference workloads. CPUID flags alone don't prove it's actually in use — the proof
is oneDNN's own kernel-selection trace during a real inference run at each precision:
Before placing workloads, confirm all three nodes are ready and that the storage and
control-plane services are running on each:
```bash
ONEDNN_VERBOSE=1 python3 <any BF16-hinted inference workload> 2> onednn-verbose.log
grep -o 'avx10_1_512_amx[a-z_]*\|avx512_core[a-z_]*' onednn-verbose.log | sort -u
spx get nodes
systemctl is-active spinifex-predastore spinifex-viperblock spinifex-daemon
```
| Precision | Kernel selected |
|---|---|
| FP32 (forced, negative control) | `avx512_core` only — **zero** AMX kernel selections |
| BF16 | `avx10_1_512_amx` |
| INT8 | `avx10_1_512_amx` (+ one `avx512_core` fallback for an unquantized matmul) |
Predastore's Raft group and OVN's northbound/southbound databases are both distributed
across all three nodes — losing one node triggers a clean leader re-election among the
remaining two, and object storage and networking continue serving. Check that all three
nodes are contributing to the Raft group before exposing the cluster to workload traffic.
`avx10_1_512_amx` is the current kernel-naming scheme on this hardware generation — not
the older `brgemm_avx512_amx*` string some documentation still references. Confirmed by
direct trace inspection, not inferred from CPUID or throughput alone.
### 2. Launch instances through the EC2-compatible API
### 3. Disk — host versus guest
Point an existing AWS profile at the Spinifex endpoint and use the standard EC2
instance lifecycle. Terraform is the recommended path — Spinifex's spread placement
group implementation holds node reservations that are not always released on destroy,
so a fixed group name can cause a subsequent apply to hang. Using a per-deploy unique
name (via `random_id` or equivalent) avoids this:
fio, file-backed (non-destructive), identical parameters on bare metal and inside a
guest:
```hcl
resource "random_id" "suffix" {
byte_length = 4
}
| Metric | Host (mulga-01) | Guest (cpu1, idle) | Ratio |
|---|---:|---:|---:|
| Random 4K read | 4,460.8 MiB/s | 11.6 MiB/s | ~1/385 |
| Sequential 1M read | 7,122.6 MiB/s | 375.5 MiB/s | ~1/19 |
resource "aws_placement_group" "spread" {
name = "edge-spread-${random_id.suffix.hex}"
strategy = "spread"
}
<img src="../../../.github/assets/images/cisco-ucs-platform-benchmark/disk-host-vs-guest.png" alt="Host versus guest disk throughput, random 4K and sequential 1M read, log scale">
resource "aws_instance" "worker" {
count = 2
ami = var.ami_id
instance_type = "m8i.2xlarge"
subnet_id = var.subnet_id
key_name = var.key_name
placement_group = aws_placement_group.spread.name
vpc_security_group_ids = [var.security_group_id]
}
```
Guest I/O traverses Viperblock's NBD path; the random 4K gap is far larger than the sequential 1M gap because small requests pay the full per-request serialization overhead without amortizing it across a large transfer. This is a known area for improvement in upcoming Spinifex releases.
For a one-off launch via the CLI, use a unique group name each time for the same reason:
### 4. Network — physical fabric versus guest overlay
```bash
export AWS_PROFILE=spinifex
GROUP="edge-spread-$(openssl rand -hex 4)"
iperf3, matched methodology, on the physical storage fabric (bare metal) and between
guest instances over the OVN/Geneve overlay:
aws ec2 create-placement-group \
--group-name "$GROUP" \
--strategy spread
| Path | Streams | Median Gbit/s |
aws ec2 run-instances \
--image-id "$AMI" --instance-type m8i.2xlarge \
--count 2 \
--subnet-id "$SUBNET" --security-group-ids "$SECURITY_GROUP" \
--key-name "$KEY_NAME" \
--placement "{\"GroupName\":\"$GROUP\"}"
```
A `g6.2xlarge` instance type routes to the node with GPU passthrough configured;
`m8i` types schedule across all three nodes.
### 3. Attach Viperblock volumes and access Predastore object storage
Create and attach an EBS-compatible data volume to a running instance:
```bash
VOLUME_ID=$(aws ec2 create-volume \
--availability-zone "$AZ" \
--size 100 --volume-type gp2 \
--query VolumeId --output text)
aws ec2 attach-volume \
--volume-id "$VOLUME_ID" \
--instance-id "$INSTANCE_ID" \
--device /dev/sdf
```
Setting `delete_on_termination = false` in Terraform keeps the volume alive across
instance replacement — relaunching a terminated instance re-attaches the same volume
rather than starting from empty storage:
```hcl
resource "aws_ebs_volume" "data" {
availability_zone = var.az
size = 100
type = "gp2"
}
resource "aws_volume_attachment" "data" {
device_name = "/dev/sdf"
volume_id = aws_ebs_volume.data.id
instance_id = aws_instance.worker[0].id
delete_on_termination = false
}
```
Predastore presents an S3-compatible endpoint — standard S3 tooling works without
modification:
```bash
aws s3 mb s3://my-bucket
aws s3 cp ./dataset.tar.gz s3://my-bucket/
aws s3 sync ./results/ s3://my-bucket/results/
```
All three nodes share the same bucket over the cluster's internal storage fabric, so
datasets, model weights and pipeline outputs are accessible to any instance without
mounting a shared filesystem.
### 4. Optional: deploy Kubernetes workloads through the EKS-compatible API
Spinifex also exposes an EKS-compatible control plane — this was not part of the Cisco
exercise documented here, which used EC2, EBS and S3 directly. For workloads where
automatic pod rescheduling matters, Spinifex supports the same `kubectl` workflows as
a standard EKS cluster:
```bash
kubectl get nodes
kubectl apply -f deployment.yaml
kubectl get pods -n default
```
Kubernetes pod rescheduling is the platform's primary answer to node failure for
scheduled workloads. The companion [vision pipeline](../cisco-ucs-vision-pipeline/README.md)
and [vLLM serving](../cisco-ucs-llm-serving/README.md) architectures use raw EC2 instances;
EKS is the pattern to reach for when automatic rescheduling matters over manual placement.
### 5. Storage benchmark
Predastore and Viperblock — Spinifex's S3 and EBS implementations — represent the
most substantial engineering work in the platform. Implementing reliable erasure-coded
object storage and a distributed block device stack on commodity NVMe, while exposing
the AWS API surface that most workloads depend on, is where most of the hard problems
live. Both subsystems are under active development, and a production-grade environment
like this cluster is where integration-level issues surface before they reach users. Run this check after cluster setup or hardware
changes to confirm both services are performing as expected.
The methodology: one guest per physical node, fio against an ext4 Viperblock data
volume (four jobs, iodepth 32, direct I/O, 512 MiB file, 30-second run), three
sequential repetitions per guest.
| Guest | 16K mixed read/write | 16K random read | 128K mixed read/write | 128K random read |
|---|---:|---:|---:|---:|
| GPU | 75 / 32 MiB/s | 75 MiB/s | 210 / 91 MiB/s | 332 MiB/s |
| CPU1 | 74 / 32 MiB/s | 76 MiB/s | 218 / 94 MiB/s | 333 MiB/s |
| CPU2 | 69 / 30 MiB/s | 107 MiB/s | 226 / 98 MiB/s | 405 MiB/s |
The 128K guest random-read numbers (332–405 MiB/s) sit between the [AWS EBS gp3](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html)
baseline (125 MiB/s) and its provisioned maximum (1,000 MiB/s) — a meaningful result
given that gp3 baseline is what most AWS operators treat as the default floor for
general-purpose block storage. The 16K numbers (75–107 MiB/s) land near that baseline.
The gap to the raw NVMe host performance (the [KIOXIA CD8P](https://americas.kioxia.com/en-us/business/ssd/data-center-ssd/cd8p-r.html) delivers over 4,000 MiB/s
host-side at comparable queue depths) is not architectural — it is the current
single-queue virtio-blk attach path and unthreaded NBD backend, both of which have
a clear source-level fix. These numbers are the baseline to improve against in future
releases, not the ceiling.
128K mixed I/O improves throughput but carries a high p99 latency envelope (roughly
0.47–0.75 s); size queues and write patterns accordingly for latency-sensitive
applications.
Predastore S3 validation used 1 GiB objects with three sequential and three
distributed-concurrent repetitions per host:
| Workload | Write, median | Read, median |
|---|---:|---:|
| Physical storage fabric (bare metal) | 1 | 23.5 (≈94% of 25GbE line rate) |
| Guest↔guest | 1 | 13.4–20.0 |
| Guest↔guest | 2–4 | 14.5–19.0 |
| Guest↔guest | 16 | 10.3–13.3 |
| One host client | 121.9 MiB/s | 213.2 MiB/s |
| Three-host aggregate | 184.2 MiB/s | 381.7 MiB/s |
<img src="../../../.github/assets/images/cisco-ucs-platform-benchmark/network-guest-vs-fabric.png" alt="Guest-to-guest overlay throughput versus the physical storage fabric, by concurrent TCP stream count">
The single-host sequential read (213 MiB/s) is a credible result for a single-node
S3-compatible store at low-to-moderate concurrency with 1 GiB objects — throughput at
this scale is typically network- and per-request-latency-bound rather than disk-bound,
and 213 MiB/s uses roughly 17% of the 25GbE storage fabric. The three-node distributed read (381.7 MiB/s, 1.79× single-host) confirms
Predastore is distributing reads across the cluster. The write scaling ratio (184.2 vs
121.9 MiB/s, 1.51×) is narrower than read, so worth tracking as a leading indicator of
backend contention as the cluster grows and write load increases.
Guest-to-guest throughput lands 20–45% below the physical fabric depending on stream
count and pairing.
All sequential S3 checksum validations passed. Full methodology, raw fio JSON and S3
metrics are in the [benchmark repository](https://github.com/tomnewton-mulga/CISCO-refarch).
The gap is primarily single-queue virtio-net — `ethtool -l` on all three guest instances
reports `Combined: 1` with no guest-configurable multiqueue support, concentrating all
network work on a single core regardless of vCPU count. This explains why 16 concurrent
streams perform *worse* than 1: they compete for the same queue rather than
parallelizing. Geneve encapsulation reduces tenant MTU to 1408 (TCP MSS 1356), adding a
smaller compounding overhead on top.
## What this architecture unlocks
### 5. Predastore (S3) throughput
- **Cloud-to-edge placement:** run the same EC2, volume, S3 and Kubernetes patterns
at the site where latency, privacy, bandwidth or sovereignty requires it.
- **Familiar operations:** keep AWS CLI profiles, Terraform/OpenTofu modules, SDKs,
CI/CD pipelines and deployment tooling rather than introducing a separate
edge-only platform.
- **Local AI with shared data:** place GPU and AMX-capable CPU inference next to the
data source while keeping datasets and artifacts available to all instances through S3.
- **A resilient foundation:** distribute control and storage services across three
physical Cisco nodes instead of concentrating the site on one server. Kubernetes
rescheduling and Raft-based storage both tolerate a single node loss without
operator intervention.
- **A path back to cloud:** the same APIs at the edge and on AWS make workload
movement, burst strategies and consistent application packaging straightforward.
Three simultaneous clients per side, one per physical node, over HTTPS to the cluster's
S3 endpoint:
| Direction | Guest-aggregate | Host-aggregate |
|---|---:|---:|
| Read | 175.1 MiB/s | 299.0 MiB/s |
| Write | 293.1 MiB/s | 124.1 MiB/s |
Reads run 1.71x faster on the host aggregate than guest. Write reverses — guests
outperform the host (293.1 vs 124.1 MiB/s).
### 6. Worker concurrency per instance — how many processes can each node sustain
With one EC2 instance per physical node (3 instances fixed), we
scale the number of concurrent worker processes within each instance from 1 to N, until
p95 request latency exceeds 2x the single-worker baseline or aggregate throughput stops
improving. Load generator: OpenVINO/YOLO11m inference against Predastore (CPU workers) and
TensorRT/YOLO11m (GPU worker).
| Workers/instance | Total workers | Aggregate img/s | cpu1 p95 (ms) | cpu2 p95 (ms) | gpu p95 (ms) |
|---:|---:|---:|---:|---:|---:|
| 1 | 3 | 49.0 | 90.9 | 88.1 | 51.0 |
| 2 | 6 | 82.6 | 140.9 | 141.7 | 49.8 |
| 3 | 9 | 103.3 | 239.0 | 232.2 | 53.0 |
| 4 | 12 | 121.1 | 319.3 | 318.4 | 53.0 |
| 5 | 15 | 133.1 | 402.1 | 413.6 | 57.4 |
| 6 | 18 | 142.5 | 490.4 | 493.6 | 62.2 |
<img src="../../../.github/assets/images/cisco-ucs-platform-benchmark/consolidation-throughput.png" alt="Aggregate throughput versus concurrent workers per instance, by worker type and cluster total">
<img src="../../../.github/assets/images/cisco-ucs-platform-benchmark/consolidation-p95-latency.png" alt="p95 request latency versus concurrent workers per instance, by worker type">
Both CPU workers track each other closely across the entire sweep (e.g. 18.05 vs.
18.25 img/s at N=2, 490.4 vs. 493.6 ms p95 at N=6), consistent with identical hardware
on identical nodes.
**CPU workers' aggregate throughput peaks at 2 workers/instance (~18.1 img/s each) and
declines steadily from there** (~16.6 at N=4, ~14.8 at N=6), while p95 latency climbs
almost linearly with N (91–88 ms → ~490 ms, a ~5.4–5.6x increase over the sweep) — **the
2x-baseline SLA is breached at 3 workers/instance** (239.0 ms cpu1 / 232.2 ms cpu2 vs. a
181.8 ms / 176.2 ms threshold respectively) and never recovers. Both signals agree: **the
practical ceiling for this CPU-bound workload is 2 workers/instance (6/cluster)** if
throughput is the priority, or 2 if latency matters at all — by 3 it's already costing
more than it gains.
**The GPU worker shows no strain through the full sweep** — p95 stays essentially flat
(51.0–62.2 ms, well under its own 102.0 ms breach threshold) and aggregate throughput
keeps climbing almost linearly through 6 workers/instance (22.85 → 112.82 img/s, a ~4.9x
increase for 6x the load) — consistent with the L4 sitting at only 22–35% utilisation under a single worker. The sweep was capped at 6
workers/instance by design; the GPU's actual ceiling is higher and wasn't reached here.
**Predastore itself is not the limiting subsystem for this result.** mulga-01's
Predastore CPU% is already elevated (85.4%) at N=1, briefly exceeds 100% at N=2
(119.0%, multi-threaded process accounting), and settles at 93.2% by N=6 — it fluctuates
around a high baseline rather than climbing *with* N the way the observed CPU-worker
degradation does, and the other two nodes' Predastore CPU% (27–50%) never comes close.
The cause is CPU-compute contention rather than storage or network: inference latency
grows ~11x across the sweep while S3 read/write latency grows only ~24–40%, and each
OpenVINO worker consumes roughly 3.5 cores unpinned — oversubscribing the 8-vCPU guest
by N=3, which lines up exactly with the observed SLA breach.
### 7. Conclusion
On matched-width CPU work, guests cost virtually nothing versus bare metal (~0.5%), and
Intel AMX is confirmed executing at the kernel-selection level, not just present in
CPUID. Network and disk both show real overhead versus bare metal — guest network at 20–45% below the physical fabric, guest disk far more so,
currently the platform's clearest area for near-term improvement. The practical ceiling
for CPU-bound concurrent work is 2 worker processes per 8-vCPU instance before latency
degrades — confirmed as compute contention rather than a storage or network ceiling —
while the GPU instance shows no strain through the full sweep, consistent with the L4
sitting at 22–35% utilisation under a single worker.
All benchmark instances were provisioned through Spinifex's EC2-compatible endpoint using standard `aws ec2` CLI calls — the same instance types, placement groups, and security groups that work on AWS work here unchanged. Teams already operating AWS infrastructure can point their existing tooling at a Spinifex node with a single profile swap.
The raw measurements are evidence that the platform is functioning as designed; the
larger outcome is a portable, resilient operating model for workloads that need cloud
interfaces outside a public-cloud region.
@@ -14,8 +14,8 @@ tags:
- predastore
- terraform
resources:
- title: "cisco-ucs-vision-pipeline (Terraform workbook, scripts)"
url: "https://github.com/mulgadc/cisco-ucs-vision-pipeline"
- title: "Benchmark and workload materials (CISCO-refarch)"
url: "https://github.com/tomnewton-mulga/CISCO-refarch"
- title: "Multi-Node Install"
url: "/docs/install-multi-node"
- title: "VPC Networking"
@@ -24,7 +24,7 @@ resources:
url: "/docs/launching-instances"
- title: "GPU Passthrough"
url: "/docs/gpu-passthrough"
- title: "Platform benchmark (companion document)"
- title: "Cisco UCS: AWS-compatible cloud at the edge (companion document)"
url: "../cisco-ucs-platform-benchmark/README.md"
- title: "Ultralytics YOLO"
url: "https://docs.ultralytics.com"
@@ -48,7 +48,7 @@ cluster running Spinifex: real-time object detection plus a vision-language mode
producing plain-English scene descriptions, both streaming from the same shared Predastore
(S3-compatible) bucket as two entirely independent EC2-compatible instances.
**Companion documents:** [Spinifex Platform Benchmark on Cisco UCS](../cisco-ucs-platform-benchmark/README.md) · [vLLM Serving on Cisco UCS: Intel AMX vs NVIDIA L4](../cisco-ucs-llm-serving/README.md)
**Companion architectures:** [Cisco UCS: AWS-compatible cloud at the edge](../cisco-ucs-platform-benchmark/README.md) · [vLLM Serving on Cisco UCS: Intel AMX vs NVIDIA L4](../cisco-ucs-llm-serving/README.md)
### Platform
File diff suppressed because it is too large Load Diff