event-trade登录编辑
📝 官方博客Hugging FaceDoubao · 实盘不做把握 9/10不做原因:风险收益比不佳
北京时间·🕒 发布 00:04:43(美东 10-21 12:04)时区推断·⟳ 抓取 00:04:53·⚡ 决策 10-22 01:57:03 +1h52m·5.6 天前

Hugging Face 发布 AWS Trainium/TorchNeuron 性能分析教程,未包含可交易商业增量

这是一篇开发者教育型技术博客,核心内容为既有 AWS Neuron/TorchNeuron 工具的 profiling 方法和单个小算子优化演示;缺少产品发布、商业采用、订单、指引或供需变化,不能形成可交易的正期望。

📄 原文Hugging Face↗ 原文
Profiling TorchNeuron (Part 1): System-level profiling on AWS Trainium.
Many ML practitioners have some intuition about how to make models run fast, but fewer know how to analyze why a model…
不做 Amazon.com, Inc.(AMZN.US)
技术教程仅介绍既有 Trainium/TorchNeuron profiling 方法,没有新增商业事实或财务量级;相对 Amazon 市值不构成可交易催化。
展开详情(成交明细 / 研究档案 / 原文全文 / 决策记录链)

研究档案

结论摘要

文章展示 Trainium 上 TorchNeuron 的算子 profiling 与融合优化,属于生态/教程内容而非新增商业催化。对 Amazon 或 NVIDIA 均无可量化的短期收入、份额或估值影响,因此不做。

🔎 新鲜度:最早出现 2026-10-21 · 扩散 low · price-in 风险 low ↗

关键理由

  • 教程只证明既有 Trainium/TorchNeuron 工具链可用,并未披露新客户、采购金额、服务 GA、代际性能突破或管理层指引。
  • RMSNorm 微基准的样本极小且非端到端模型对比,无法外推到 Trainium 需求、云收入或 GPU 份额变化。

主要风险

  • 若市场将 AWS 自研芯片生态内容作为主题情绪交易,AMZN 或相关供应链可能出现短期波动,但该情绪不由本文的新增基本面支撑。
  • 系列第二部分若同时披露新硬件能力、客户采用或 benchmark,才可能构成新事件;当前不能提前交易。

反向证据

  • 做多前查反向 · 来源 web · 影响 invalidates
    当前正文未提供新客户、订单、GA、收入或可与替代方案比较的端到端 benchmark;没有足以支持做多 Amazon 的新增事实。
    检索:AWS Trainium TorchNeuron new customer order GA revenue benchmark October 2026 原文 ↗
  • 做空前查反向 · 来源 web · 影响 invalidates
    单个 RMSNorm 算子的教学实验不能证明 NVIDIA GPU 客户流失或份额下降,缺乏做空所需的实质负面催化。
    检索:TorchNeuron profiling Trainium NVIDIA customer migration share loss 原文 ↗

先例如何影响了这次决策

对本次决策的影响:先例缺口不影响 AVOID 结论,原因是事件本身先验上已缺乏可交易 materiality。

方向:未使用历史先例;此类开发者教程没有明确证券级事件身份,也缺少可量化的公司经营变化。

涨幅量级:不足以校准止盈止损,因为本文没有产品发布、订单、业绩指引或竞争格局变化。

形态:不适用;没有可定义的市场反应锚点。

工具执行结果 · 成功 1 · 降级 0 · 失败 0 · 取消 0
  1. search_processed_events 成功 stock_tools HTTP · 2,657 ms
    {"result": "search_processed_events:agent query=`hugging face aws trainium torchneuron profiling blog | neuronconfig neuronprofiler rmsnorm torch.compile | torch-neuronx profiling trainium part 1 system level`;结构化索引覆盖完整 72 小时;旧记录兼容扫描近 71.9/72 小时、26089 条本臂决策(完整),返回 0 条候选。未命中只表示这些 agent query 表达式没有召回候

原文全文

展开原文 · 12,193 字
Many ML practitioners have some intuition about how to make models run fast, but fewer know how to analyze why a model is slow. In Part 1 of this series, you will learn how to systematically analyze inference performance and identify where the time is spent.
This post starts from scratch and assumes no prior profiling experience. The walkthrough uses AWS Trainium, a purpose-built AI chip for deep learning training and inference workloads, and TorchNeuron, its open source native PyTorch backend. TorchNeuron supports standard PyTorch workflows on Trainium, including eager execution, torch.compile, and standard PyTorch APIs, with minimal code changes. Additionally, TorchNeuron integrates with Neuron Kernel Interface (NKI) to enable custom operators and performance optimization for Trainium hardware. By the end, you should know:
- How to configure torch.profiler with the Neuron backend and capture a clean trace.
- How to read the key_averages() table to identify which operations consume Neuron device time and compare their Self CPU time.
- How to follow one operation through Neuron Explorer, from framework dispatch through runtime scheduling to hardware execution on a NeuronCore.
- How these signals change across three implementations of the same operation.
Before you profile a workload, it helps to understand how Neuron integrates with PyTorch.
The Neuron backend uses PyTorch's PrivateUse1 extension point. This mechanism lets an accelerator integrate with the framework without adding a dedicated dispatch key such as cuda. The torch_neuronx package works with upstream PyTorch to register Neuron as a native backend for PyTorch code. For details about this extension mechanism, see Facilitating New Backend Integration by PrivateUse1.
You use two objects to profile a Neuron workload:
- NeuronConfig controls which Neuron data streams and NeuronCores to capture and where to write the output. You pass it totorch.profiler.profile asexperimental_config .
- NeuronProfiler takes aNeuronConfig and provides anexport_trace callback. The callback writes the framework trace,trace.json , alongside the Neuron system traces.
nc = NeuronConfig(
modes=[ProfileMode.DEVICE, ProfileMode.RUNTIME],
profile_output_dir=OUTPUT_DIR,
capture_enabled_for_nc='0',
correlate_device_time=True,
)
exporter = NeuronProfiler(nc)
The modes parameter selects the data streams to capture, such as device instructions and runtime traces. The capture_enabled_for_nc parameter selects the NeuronCores to trace. Setting correlate_device_time=True propagates device time from the trace into the key_averages() table, where you can compare CPU and Neuron device time. For the complete parameter reference and available ProfileMode values, see the NeuronConfig Profile Modes documentation.
Neuron Explorer is a browser-based viewer for the system trace, device timeline, and per-engine breakdown. You can access it through an SSH tunnel or the Visual Studio Code extension. In this post, you use Explorer to confirm what key_averages() reports numerically and inspect what happens between dispatches.
After profiling, the output directory contains the system trace and, when you capture device data, matched .neff and .ntff files. The Neuron Executable File Format (NEFF) contains the compiled Neuron executable, while the matching NTFF contains its hardware instruction trace. The files share a numeric hash that identifies them as a pair. To open the profile in Neuron Explorer, upload the complete output directory for a system or combined profile. For a device-only profile, upload the matching .neff and .ntff files individually. See Step 5: Upload your profile for the UI and command-line instructions.
For this first analysis, you profile RMSNorm, a small operation with a clear sequence of arithmetic and reduction operations.
You profile three implementations of the same operation:
- Naive RMSNorm with individual PyTorch operations: multiply, mean, add, reciprocal square root, and multiply.
- torch.rms_norm() , the PyTorch built-in lowered to a single fused Neuron kernel.
- Naive RMSNorm with torch.compile , using the same operations as the first implementation.
The scripts use the same inputs, profiler configuration, and schedule so the results are directly comparable.
All scripts to reproduce this work are available in the torch-neuronx examples directory.
Start by writing RMSNorm with individual PyTorch operations. Each line maps to one or more ATen operations and can create intermediate tensors.
device = torch.device('neuron')
x = torch.randn(4, 512, dtype=torch.bfloat16, device=device)
weight = torch.ones(512, dtype=torch.bfloat16, device=device)
def rms_norm_fn(t):
x_sq = t * t # square
mean_sq = x_sq.mean(dim=-1, keepdim=True) # mean of squares
rms = torch.rsqrt(mean_sq + 1e-6) # 1 / sqrt(mean_sq + eps)
return t * rms * weight # normalize + scale
Call the profiler with two arguments required for the Neuron backend:
- Include ProfilerActivity.PrivateUse1 to collect activity from the Neuron device.
- Pass NeuronConfig asexperimental_config to enable the Neuron-specific Kineto features.
The schedule uses wait=2, warmup=1, and active=1 across four prof.step() calls. This records one warm iteration without including initial setup overhead.
Call torch.neuron.synchronize() inside the profiler loop. Without this synchronization, the profiler can export before the device finishes and leave the Neuron time column empty.
with torch.profiler.profile(
activities=[ProfilerActivity.CPU, ProfilerActivity.PrivateUse1],
experimental_config=nc,
record_shapes=False,
on_trace_ready=exporter.export_trace,
schedule=torch.profiler.schedule(wait=2, warmup=1, active=1),
) as prof:
for step in range(4):
with torch.no_grad():
_ = rms_norm_fn(x)
torch.neuron.synchronize()
prof.step()
After profiling finishes, inspect the key_averages() table. Sort by self_privateuse1_time_total to place the operations with the highest device cost first. The table shown here is filtered to the RMSNorm operations that report Neuron device time. The full key_averages() output also includes CPU-side events such as allocations and host-to-device transfers.
print(prof.key_averages().table(sort_by="self_privateuse1_time_total", row_limit=4))
The key averages table shows that three aten::mul calls account for the largest share of Neuron device time.
The table shows which ATen operations ran, how often they ran, and how much time they spent on the CPU and Neuron device. aten::mul has the highest total device time because the function performs three multiplications.
| Name | # Calls | Self CPU | Self NEURON | % NEURON |
|---|---|---|---|---|
| aten::mul | 3 | 60.9 μs | 1,164.5 μs | 49.5% |
| aten::add | 1 | 26.6 μs | 434.6 μs | 18.5% |
| aten::rsqrt | 1 | 15.6 μs | 415.0 μs | 17.6% |
| aten::mean | 1 | 21.1 μs | 340.8 μs | 14.5% |
Self NEURON total: 2.355 ms
Each row maps directly to the function. aten::mul runs for x * x, x * rms, and the final multiplication by weight. aten::mean reduces the last dimension. aten::add adds the epsilon value and triggers a host-to-device copy because the scalar starts on the CPU. aten::rsqrt computes the reciprocal square root.
Neuron Explorer follows an aten::mul operation from framework dispatch through runtime scheduling to execution on the Neuron hardware lanes.
In Explorer, time flows from left to right and the event lifecycle flows from top to bottom. Each ATen operation follows the same pattern: creation in the framework lane, scheduling in the runtime lane as nrta_execute_schedule, and device execution in the hardware lane as nc_exec_running.
The system trace view organizes events into lanes. In the Default grouping mode, labels follow the pattern instance/PID/subsystem/identifier:
| Lane | Label suffix | What it shows |
|---|---|---|
| Framework dispatch | framework/TID:<id> | Operator dispatch events (PrivateUse1 runtime), grouped by thread ID. |
| Framework device | framework/Stream:<n> | Device interaction events (PrivateUse1 driver), grouped by stream number. |
| Neuron Runtime | neuron_rt/NC:<n> | Neuron Runtime API calls, grouped by logical NeuronCore. |
| Neuron Hardware | neuron_hw/NC<n>:<id> | Hardware execution events, grouped by physical NeuronCore. |
In eager mode, each operation runs independently. Use the dependency chain viewer to follow aten::mul.Tensor from the framework layer through runtime scheduling to device execution.
The dependency chain viewer highlights the lifecycle of one operation across the framework, runtime, and hardware lanes.
Replace the individual operations with PyTorch's built-in rms_norm function. Neuron lowers the operation to one fused kernel:
def rms_norm_fn(t):
return torch.rms_norm(t, [512], weight)
The fused RMSNorm appears as one device operation in the key averages table.
| Name | # Calls | Self CPU | Self NEURON | % NEURON |
|---|---|---|---|---|
| aten::_fused_rms_norm | 1 | 47.6 μs | 403.3 μs | 100% |
Self NEURON total: 403.3 μs
The fused RMSNorm follows one framework-to-hardware path instead of dispatching each arithmetic operation separately.
In the naive implementation, each operation crosses the dispatch boundary independently and follows its own framework-to-runtime-to-hardware path. In the fused implementation, one Python call covers the complete computation. The trace contains one dispatch and one hardware event, with no gaps between component operations.
For the final example, compile the original naive RMSNorm function with torch.compile.
With @torch.compile(backend="neuron"), TorchDynamo captures the Python bytecode as an FX graph and AOTAutograd lowers it to ATen operations. The Neuron backend receives the complete graph instead of dispatching each operation separately. It fuses the operations, optimizes memory access, and compiles the graph into a single NEFF artifact. The artifact runs as one hardware dispatch.
@torch.compile(backend='neuron', fullgraph=True)
def naive_compiled(t):
x_sq = t * t
mean_sq = x_sq.mean(dim=-1, keepdim=True)
rms = torch.rsqrt(mean_sq + 1e-6)
return t * rms * weight
The compiled function appears as one Torch-Compiled Region in the key averages table.
| Name | # Calls | Self CPU | Self NEURON | % NEURON |
|---|---|---|---|---|
| Torch-Compiled Region: 0/0 | 1 | 98.4 μs | 375.5 μs | 100% |
Self NEURON total: 375.5 μs
The compiled graph follows one path through runtime scheduling and hardware execution.
The table shows one device execution, as in Profile 2, but the code takes a different path. Instead of calling a purpose-built fused operation, the compiler discovers the fusion from the original Python function. In this run, the Neuron time is comparable to torch.rms_norm, at 375 μs compared with 403 μs.
| Variant | NEURON time | Self CPU time | Operator calls |
|---|---|---|---|
| Naive ops | 2,355 µs | ~125 µs | 6 |
| torch.rms_norm | 403 µs | ~48 µs | 1 |
| Naive + torch.compile | 376 µs | ~98 µs | 1 |
Both torch.rms_norm and torch.compile fuse RMSNorm into one kernel dispatch. In these runs, either approach takes about one-sixth of the naive implementation's device time. Fusion removes the gaps between hardware executions and avoids materializing intermediate values such as x_sq and mean_sq between separately dispatched operations.
key_averages() shows which operations consume device time, while its full output also reveals CPU-side setup and transfers. Explorer provides the corresponding visual trace. You can follow one operation from framework dispatch through runtime scheduling to hardware execution and see the gaps that fusion removes.
You can use the same workflow on larger models: find a hotspot in the table, verify it in the trace, and then determine whether a fused operation or torch.compile can reduce its cost.
In Part 2, we will move into the device-level profile. You open the NEFF, inspect the TensorEngine, VectorEngine, and direct memory access (DMA) breakdown, and place the kernel on the roofline to determine whether it is compute-bound or memory-bound.
Special thanks to Aritra Roy Gosthipaty for the inspiration to begin this series, and to my peers Pinak Panigrahi, Samir Araujo, Akhil Azhikodan, Esha Lakhotia and the rest for reviewing!

决策记录链 · 只追加

每次领取产生一条记录,重新决策追加一条并以 supersedes 指向被替代的记录(ADR 0014)。

  1. 977faee4e2 · 2026-10-22 01:57 · doubao / doubao-seed-evolving-latest-version · 策略包 658c0c1e2ba5当前