/vectorization
Design, implement, optimize, and review SIMD code in .NET. USE FOR: vectorizing scalar loops with TensorPrimitives, Vector64/128/256/512, or platform hardware intrinsics; reviewing existing SIMD code, including the generic Vector type, for contract equivalence, tail handling,
Claude Code
$ npx -y skills add dotnet/skills --skill vectorization --agent claude-code
Codex
$ npx skills add dotnet/skills --skill vectorization -a codex -y
Cursor
$ npx skills add dotnet/skills --skill vectorization -a cursor -y
Gemini CLI
$ npx skills add dotnet/skills --skill vectorization -a gemini-cli -y
GitHub Copilot
$ npx skills add dotnet/skills --skill vectorization -a github-copilot -y
OpenCode
$ npx skills add dotnet/skills --skill vectorization -a opencode -y
Windsurf
$ npx skills add dotnet/skills --skill vectorization -a windsurf -y
SKILL.md
vectorization.SKILL.mdname: vectorization
description: >
Design, implement, optimize, and review SIMD code in .NET.
USE FOR: vectorizing scalar loops with TensorPrimitives,
Vector64/128/256/512, or platform hardware intrinsics; reviewing existing SIMD
code, including the generic Vector type, for contract equivalence, tail handling, memory
safety, portability, fallbacks, and measured performance. DO NOT USE FOR:
performance work unrelated to SIMD or vectorization.
license: MIT
.NET SIMD vectorization
Produce a portable optimization that preserves the scalar contract, remains memory-safe at every length, and earns its complexity with measured results. **Read the official [SIMD and hardware-intrinsics guidance](https://learn.microsoft.com/dotnet/standard/simd) first** and follow its comprehensive implementation templates. In particular, use its self-contained per-width dispatch, dedicated small-input handling, loop, and remainder shapes rather than reducing them to a chain of width checks. This skill supplies the decision rules and validation checks to apply while changing real code.
Inputs and prerequisites
Discover these from the repository before asking the user:
| Input | Required | What to establish | | --- | --- | --- | | Scalar implementation and tests | Yes | Existing contract, representative call sites, and supported overlap | | Target frameworks and platforms | Yes | Available SIMD APIs and architectures that must behave consistently | | Build and test workflow | Yes | The repository's normal commands and how to launch separate test processes | | Representative workload or benchmark | For optimization | Typical input sizes and the baseline to beat |
Do not add a package merely because an API exists there. First check the target framework and the project's existing dependency/versioning policy.
Core rules
1. **Use the highest-level API that matches the contract, then stop.** `Span<T>` and `string` operations, `TensorPrimitives`, and tensor types already accelerate many operations. LINQ reductions such as `Sum`, `Min`, `Max`, and `Average` can also accelerate when the source exposes its underlying span. Verify empty-input and floating-point behavior rather than assuming similarly named operations are interchangeable. Once an existing API preserves the contract, use it instead of continuing into handwritten SIMD. Before writing an explicit loop, name the framework APIs considered and why none applies. Fixed-shape `System.Numerics` types remain appropriate for graphics and similar domains. 2. **Start new explicit SIMD loops with `Vector128<T>`.** It is accelerated across the broadest hardware set. Add wider fixed-width paths only when measurements justify them. 3. **Keep platforms consistent.** Prefer cross-platform operations on the fixed-width vector types; they lower to the appropriate target instructions. For example, `(vector & mask) == Vector128<byte>.Zero` becomes `ptest` on x86/x64. Use architecture-specific intrinsics only for a measured gap, guard them with `IsSupported`, and retain equivalent portable or scalar behavior. 4. **Read `IsHardwareAccelerated`, `IsSupported`, and `Count` directly.** The JIT treats them as constants, so caching them adds no value and obscures which branches disappear. 5. **Prefer operators where they are clear.** Parenthesize expressions that mix bitwise and comparison operators so precedence is explicit.
If the task is review-only, do not rewrite the code. Report correctness and memory-safety defects before performance opportunities.
Authoring checklist
- **Contract:** identify behavior for empty and short inputs, overlap, overflow, NaN, signed zero,
ordering, and exceptions before changing the implementation.
- **Framework gate:** inspect the target framework and existing package references, then compile or
probe the highest-level candidate API with the required edge cases. A small contract adapter, such as preserving special empty-input behavior, does not justify reimplementing the operation. If the API preserves the contract, use it and stop; do not claim it is unavailable without checking.
- **Structure:** for new explicit SIMD, implement `Vector128<T>` and scalar first. Only after
measurements justify wider paths, check `Vector512<T>`, then `Vector256<T>`, optional `Vector<T>`, `Vector128<T>`, and finally scalar. Omit paths the implementation does not need. Each outer fixed-width guard checks only its `IsHardwareAccelerated` property and, for generic element types, `IsSupported`. Inside that block, run the width-specific helper when the input has at least `Count` elements; otherwise run a dedicated small-input helper, then return. Do not put the length check in the outer guard and fall through to repeat dispatch at narrower widths. Keeping each supported-width block self-contained lets the JIT remove unsupported blocks and avoids redundant work on common small inputs.
- **Loads and stores:** prefer span-based `Vector128.Create(span)` and `CopyTo`; the JIT keeps them
efficient and they require no pinning or reference arithmetic. Unsafe loads and stores are largely unnecessary. When a path genuinely must walk a buffer by managed reference, use the element-offset `LoadUnsafe(ref T, nuint)` and `StoreUnsafe` overloads rather than pointers or manually advanced references.
- **Empty inputs:** in a reference-based path, obtain the starting reference with
`MemoryMarshal.GetReference(span)` or `MemoryMarshal.GetArrayDataReference(array)`, not by indexing element `0`.
- **Unsupported element types:** the fixed-width vectors support primitive numeric element types,
not `char` or `bool`. Reinterpret with `MemoryMarshal.Cast` or `As<TFrom, TTo>`; reinterpretation changes only the type, not the bits. Keep Boolean data as `0` or `1` and characters as valid UTF-16, normalizing results before storing when necessary.
- **Offsets:** prove the input contains
Read more
name: vectorization description: > Design, implement, optimize, and review SIMD code in .NET. USE FOR: vectorizing scalar loops with TensorPrimitives, Vector64/128/256/512, or platform hardware intrinsics; reviewing existing SIMD code, including the generic Vector type, for contract equivalence, tail handling, memory safety, portability, fallbacks, and measured performance. DO NOT USE FOR: performance work unrelated to SIMD or vectorization. license: MIT
.NET SIMD vectorization
Produce a portable optimization that preserves the scalar contract, remains memory-safe at every length, and earns its complexity with measured results. **Read the official [SIMD and hardware-intrinsics guidance](https://learn.microsoft.com/dotnet/standard/simd) first** and follow its comprehensive implementation templates. In particular, use its self-contained per-width dispatch, dedicated small-input handling, loop, and remainder shapes rather than reducing them to a chain of width checks. This skill supplies the decision rules and validation checks to apply while changing real code.
Inputs and prerequisites
Discover these from the repository before asking the user:
| Input | Required | What to establish | | --- | --- | --- | | Scalar implementation and tests | Yes | Existing contract, representative call sites, and supported overlap | | Target frameworks and platforms | Yes | Available SIMD APIs and architectures that must behave consistently | | Build and test workflow | Yes | The repository's normal commands and how to launch separate test processes | | Representative workload or benchmark | For optimization | Typical input sizes and the baseline to beat |
Do not add a package merely because an API exists there. First check the target framework and the project's existing dependency/versioning policy.
Core rules
1. **Use the highest-level API that matches the contract, then stop.** `Span<T>` and `string` operations, `TensorPrimitives`, and tensor types already accelerate many operations. LINQ reductions such as `Sum`, `Min`, `Max`, and `Average` can also accelerate when the source exposes its underlying span. Verify empty-input and floating-point behavior rather than assuming similarly named operations are interchangeable. Once an existing API preserves the contract, use it instead of continuing into handwritten SIMD. Before writing an explicit loop, name the framework APIs considered and why none applies. Fixed-shape `System.Numerics` types remain appropriate for graphics and similar domains. 2. **Start new explicit SIMD loops with `Vector128<T>`.** It is accelerated across the broadest hardware set. Add wider fixed-width paths only when measurements justify them. 3. **Keep platforms consistent.** Prefer cross-platform operations on the fixed-width vector types; they lower to the appropriate target instructions. For example, `(vector & mask) == Vector128<byte>.Zero` becomes `ptest` on x86/x64. Use architecture-specific intrinsics only for a measured gap, guard them with `IsSupported`, and retain equivalent portable or scalar behavior. 4. **Read `IsHardwareAccelerated`, `IsSupported`, and `Count` directly.** The JIT treats them as constants, so caching them adds no value and obscures which branches disappear. 5. **Prefer operators where they are clear.** Parenthesize expressions that mix bitwise and comparison operators so precedence is explicit.
If the task is review-only, do not rewrite the code. Report correctness and memory-safety defects before performance opportunities.
Authoring checklist
- **Contract:** identify behavior for empty and short inputs, overlap, overflow, NaN, signed zero,
ordering, and exceptions before changing the implementation.
- **Framework gate:** inspect the target framework and existing package references, then compile or
probe the highest-level candidate API with the required edge cases. A small contract adapter, such as preserving special empty-input behavior, does not justify reimplementing the operation. If the API preserves the contract, use it and stop; do not claim it is unavailable without checking.
- **Structure:** for new explicit SIMD, implement `Vector128<T>` and scalar first. Only after
measurements justify wider paths, check `Vector512<T>`, then `Vector256<T>`, optional `Vector<T>`, `Vector128<T>`, and finally scalar. Omit paths the implementation does not need. Each outer fixed-width guard checks only its `IsHardwareAccelerated` property and, for generic element types, `IsSupported`. Inside that block, run the width-specific helper when the input has at least `Count` elements; otherwise run a dedicated small-input helper, then return. Do not put the length check in the outer guard and fall through to repeat dispatch at narrower widths. Keeping each supported-width block self-contained lets the JIT remove unsupported blocks and avoids redundant work on common small inputs.
- **Loads and stores:** prefer span-based `Vector128.Create(span)` and `CopyTo`; the JIT keeps them
efficient and they require no pinning or reference arithmetic. Unsafe loads and stores are largely unnecessary. When a path genuinely must walk a buffer by managed reference, use the element-offset `LoadUnsafe(ref T, nuint)` and `StoreUnsafe` overloads rather than pointers or manually advanced references.
- **Empty inputs:** in a reference-based path, obtain the starting reference with
`MemoryMarshal.GetReference(span)` or `MemoryMarshal.GetArrayDataReference(array)`, not by indexing element `0`.
- **Unsupported element types:** the fixed-width vectors support primitive numeric element types,
not `char` or `bool`. Reinterpret with `MemoryMarshal.Cast` or `As<TFrom, TTo>`; reinterpretation changes only the type, not the bits. Keep Boolean data as `0` or `1` and characters as valid UTF-16, normalizing results before storing when necessary.
- **Offsets:** prove the input contains
This repository contains the .NET team's curated set of portable skills and host-specific custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.
Other skills on skills.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about vectorization.
- Which coding agents can use vectorization?
- vectorization installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

