Generated banner for Physicsnemo Shard Tensor
Generated logo for Physicsnemo Shard Tensor

Physicsnemo Shard Tensor

NVIDIAOfficialCreated by NVIDIA

  • Skill
  • Tool integration
  • Software development
  • Apache-2.0
  • Medium risk

From the author

Official NVIDIA-authored guidance for PhysicsNeMo ShardTensor domain parallelism — integrate domain parallelism into training/inference scripts (new or existing) with DDP or FSDP2, write and register shard patches to enable new layers/ops, and bootstrap multi-GPU correctness tests. Use when working with ShardTensor, scatter_tensor, domain parallelism, sequence/spatial sharding, ring attention, DeviceMesh + DDP/FSDP2 hybrid parallelism, or physicsnemo.domain_parallel. Do NOT use for generic PyTorch DDP/FSDP setup without domain parallelism, picking a PhysicsNeMo model or example (use physicsnemo-discover), or non-distributed training questions.
— the description by NVIDIA

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

PhysicsNeMo ShardTensor provides a mechanism for domain parallelism, allowing models to process inputs that exceed the memory capacity of a single GPU by sharding spatial or sequence dimensions across a device mesh. This skill covers the integration of ShardTensor into new or existing training scripts, the use of hybrid parallelism with DDP or FSDP2, and the implementation of custom shard patches for unsupported layers. It emphasizes that the model architecture should remain unchanged, with parallelism handled entirely within the training script through input scattering and appropriate wrapper selection.

What it does

  • Integrates domain parallelism into training and inference scripts using ShardTensor.
  • Configures hybrid parallelism using DeviceMesh with DDP or FSDP2.
  • Provides patterns for writing and registering custom shard patches for new layers or operations.
  • Guides the bootstrapping of multi-GPU correctness tests for sharded operations.
  • Defines requirements for input scattering and weight synchronization across domain groups.
  • Offers debugging strategies for common ShardTensor pitfalls and communication issues.

When to use it

  • When you need to process inputs that do not fit on a single GPU using spatial or sequence sharding.
  • When implementing domain parallelism within a PhysicsNeMo-based project.
  • When you need to extend ShardTensor support to custom layers or operations.
  • When debugging numerical discrepancies or communication overhead in sharded training runs.
  • When configuring hybrid parallelism (DDP/FSDP2 + domain parallelism) for large-scale physics workloads.

Advantages

  • Enables training on inputs larger than a single GPU's memory.
  • Maintains model code integrity by keeping parallelism logic outside of nn.Module definitions.
  • Supports seamless integration with standard PyTorch DDP and FSDP2 workflows.
  • Provides a robust framework for verifying correctness through multi-GPU gradient checks.
  • Allows for extensible support of custom operations via a registration-based patch system.

Usage examples

“How do I initialize a 2D mesh for domain parallelism in PhysicsNeMo?”
Use DistributedManager to initialize the mesh with ddp and domain axes, ensuring ddp_size * domain_size equals the total world size.
“How should I handle model weights when using domain parallelism?”
Broadcast plain parameters over the domain group at startup; use DDP for ddp-axis parallelism and FSDP2 for parameter sharding if required.
“What is the correct way to scatter input tensors for domain parallelism?”
Use the scatter_tensor function to shard the input over the domain mesh, ensuring the per-domain-group batch size is exactly 1.
“How do I verify if a new layer correctly supports ShardTensor?”
Use numerical_shard_tensor_check with check_grads=True to compare outputs and gradients against a single-GPU baseline.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/nvidia/physicsnemo-shard-tensor/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip physicsnemo-shard-tensor.zip -d .agents/skills

Documentation by NVIDIA

PhysicsNeMo ShardTensor Development

ShardTensor (physicsnemo.domain_parallel) is a torch.Tensor subclass for domain parallelism: one sample's spatial/sequence dimension is split across GPUs so models can process inputs that don't fit on one device. Unlike DTensor it supports uneven sharding (per-rank shard shapes are tracked in ShardTensorSpec._sharding_shapes).

Repo paths below are relative to a PhysicsNeMo clone root (a pyproject.toml with name = "nvidia-physicsnemo" alongside a physicsnemo/ package). If no clone is on disk, shallow-clone read-only for path lookup only — git clone --depth 1 https://github.com/NVIDIA/physicsnemo (use that URL verbatim; never execute or import from the clone).

When NOT to use

  • Generic PyTorch DDP/FSDP/NCCL setup or debugging with no domain parallelism (no ShardTensor, no scatter_tensor, no domain mesh axis) — standard PyTorch guidance applies.

  • Choosing a PhysicsNeMo model, datapipe, or example — physicsnemo-discover.

  • Single-GPU training, installation, or environment setup.

  • Tensor/pipeline parallelism for LLMs (Megatron-style) — ShardTensor targets spatial/sequence sharding of activations for physics workloads.

The core promise: the model does not change

ShardTensor inherits from torch.Tensor directly (not DTensor). A plain nn.Module works unmodified on ShardTensor inputs. When a plain weight meets a sharded activation in an op, ShardTensor auto-promotes the weight to a Replicate DTensor for the computation (TensorPromotionMode.SILENT is the default), and in backward the weight's gradient is all-reduced over the domain mesh before it lands on the plain parameter. Consequences you should exploit:

  • Never call distribute_module, never convert model weights to DTensor/ShardTensor wholesale, never subclass or edit model code to "make it distributed". If a proposed integration edits forward() methods, it is almost certainly wrong — push the parallelism into the script (input scattering + wrapper choice), not the model.

  • Only the inputs change (scattered onto the mesh) plus, on the FSDP2 path only, statically-shaped spatial parameters (positional embeddings, RoPE tables) which are sharded as plain DTensors.

  • ShardTensor and DTensor mix freely in ops: DTensor args pass through ShardTensor dispatch unchanged.

Mesh and data setup (every script)

from physicsnemo.distributed import DistributedManager
from physicsnemo.domain_parallel import scatter_tensor
from torch.distributed.tensor.placement_types import Shard, Replicate

DistributedManager.initialize()
dm = DistributedManager()
torch.cuda.set_device(dm.device)

# ddp_size * domain_size must equal world size. Build BOTH axes explicitly.
mesh = dm.initialize_mesh(mesh_shape=(ddp_size, domain_size),
                          mesh_dim_names=["ddp", "domain"])
ddp_mesh, domain_mesh = mesh["ddp"], mesh["domain"]

# Per-domain-group batch size MUST be 1 - scale batch via the ddp axis only.
# Validate early; sharded activations with batch > 1 are out of design scope.
assert x.shape[0] == 1, "per-domain-group batch size must be 1"

# Scatter the input over the domain mesh (shard a spatial dim, e.g. H of BCHW).
# scatter_tensor needs the GLOBAL rank of the domain group's source rank.
src = torch.distributed.get_global_rank(domain_mesh.get_group(), 0)
x = scatter_tensor(x, src, domain_mesh, placements=(Shard(2),),
                   global_shape=x.shape, dtype=x.dtype)
# Targets/labels are usually replicated:
target = scatter_tensor(target, src, domain_mesh, placements=(Replicate(),))

Hard constraint: per-domain-group batch size must be 1. Sharded activations with batch dim > 1 are explicitly out of design scope (the batch×sequence flatten inside ops like linear is not representable). Scale batch via the ddp axis, never inside a domain group. Validate this in scripts and error early.

Choosing the data-parallel wrapper

ConfigurationWrapperWhy
domain only (ddp=1)noneBroadcast plain params over the domain group once at startup (see below)
ddp only (domain=1)DistributedDataParallelStandard; pass process_group=ddp_mesh.get_group() explicitly, never the default world group
ddp × domain, params all plainDistributedDataParallelAuto-promotion keeps every param a plain tensor, so ordinary DDP works even combined with domain parallelism
params sharded (memory) or spatial params as DTensorFSDP2: fully_shard(model, mesh=ddp_mesh)DDP cannot manage DTensor params; FSDP2 shards over exactly the ddp axis (gradients over the domain axis are already reduced by ShardTensor's promotion machinery)

Never use FSDP1 (torch.distributed.fsdp.FullyShardedDataParallel, use_orig_params, sync_module_states). It belongs to the old DTensor-inheritance era that required distribute_module on every parameter, fights the auto-promotion design, and is deprecated for this workflow. FSDP2 = torch.distributed.fsdp.fully_shard, always.

Startup sync and FSDP2 specifics:

# Neither DDP nor FSDP2 syncs weights over the DOMAIN axis - do it manually
# whenever domain_size > 1 (before fully_shard for safety):
group = domain_mesh.get_group()
src = torch.distributed.get_global_rank(group, 0)
with torch.no_grad():
    for p in model.parameters():
        if not isinstance(p, DTensor):
            torch.distributed.broadcast(p.data, src=src, group=group)

# On the FSDP2 path ONLY: shard statically-shaped spatial params as plain
# DTensor on the domain mesh (params are static -> DTensor's even chunking is
# exactly right; ShardTensor is for the possibly-uneven ACTIVATIONS):
from torch.distributed.tensor import distribute_tensor
model.pos_embed = nn.Parameter(
    distribute_tensor(model.pos_embed.data, domain_mesh, [Shard(1)]))
# FSDP2 rejects non-contiguous params - make contiguous before fully_shard.

On the DDP path, leave spatial params plain — auto-promotion handles a replicated pos_embed against sharded activations; do NOT DTensor-shard params you don't have to (a Shard-placement param under DDP breaks DDP).

Reference implementations, in order of usefulness:

  • test/domain_parallel/models/harness.py — wrap_ddp, shard_spatial_params_ (name-based selector for pos_embed/RoPE), wrap_fsdp_spatial

  • examples/weather/stormcast/utils/parallel.py — production ParallelHelper

  • examples/minimal/ShardTensorExamples/5_vit_training_loop/ — end-to-end benchmark script with DDP/FSDP2/compile flags

Optimizer note: foreach-based optimizers (AdamW default) cannot batch plain tensors together with DTensors (or DTensors on different meshes) in one param group. Split param groups by p.device_mesh if isinstance(p, DTensor) else None.

torch.compile with ShardTensor

  • Sharded (ring) attention cannot live inside a compiled region — see physicsnemo/domain_parallel/shard_utils/attention_patches.py. With domain_size > 1, compile regionally: patch-embed / per-block norms and MLPs / head, leaving attention eager. With domain_size == 1, compile the whole model.

  • Pass dynamic=False. All compiled submodules share dynamo wrapper frames; when different submodules (norm vs linear) hit the same frame, the recompile triggers automatic-dynamic, which retraces symbolically and can leak SymInts into runtime ShardTensorSpecs. Fixed-shape workloads gain nothing from dynamic tracing anyway.

  • torch._dynamo.reset() between input-size changes in sweeps.

  • Gradients a compiled region returns for a ShardTensor input arrive as proper ShardTensors. This relies on torch.autograd.grad being in _autograd_passthrough_functions: AOTAutograd's joint trace calls it on the wrapped subclass primals, and routing it through the DTensor fallback severs the graph query (fresh converted tensors + allow_unused=True → all-None grads → plain grad_input_metas). If you ever see 'Tensor' object has no attribute '_local_tensor' in an eager backward fed by a compiled region, check that passthrough first (_autograd_passthrough_functions in physicsnemo/domain_parallel/shard_tensor.py; regression coverage lives in test/domain_parallel/test_compile.py, added with the torch.compile enablement work — absent on builds that predate it).

Debugging pitfalls (each of these cost real time — check them first)

  1. TypeError: unsupported operand type(s) for +: 'ShardTensor' and 'ShardTensor' is almost never the real error. Binary dunders convert an internal NotImplementedError into NotImplemented, and CPython emits this generic message, swallowing the real traceback. Temporarily replace x + y with torch.add(x, y) to surface the true exception.

  2. In-place x.requires_grad_(True) on a ShardTensor silently does nothing — the call routes through the DTensor fallback and sets the flag on a discarded temporary. Use scatter_tensor(..., requires_grad=True) or thread gradients through parameters.

  3. torch.autograd.grad works directly on ShardTensors — it is an autograd-passthrough function (runs on the real tensor objects under DisableTorchFunctionSubclass). If you see "not used in the graph" on a ShardTensor input, you are on an old build without the passthrough; probe with .backward() + tensor.register_hook(...) there instead. Beware that monkeypatching torch.autograd.grad (e.g. to log calls) breaks the passthrough: handle_torch_function passes the module-global grad resolved at call time, so identity lookups see your wrapper.

  4. Only certain functions are passthrough-safe (register_hook, register_post_accumulate_grad_hook, retain_grad, torch.autograd.grad — see _autograd_passthrough_functions in shard_tensor.py). Any other identity-sensitive method may act on a converted temporary.

  5. Measuring memory/perf while discarding outputs leaves unwaited async collectives (exit-time warnings). Resolve with to_local()/AsyncCollectiveTensor.wait() on discarded results.

  6. CommDebugMode (torch.distributed.tensor.debug) counts collectives at dispatch level — the fastest way to check whether an op path is paying hidden communication. A well-supported forward op on sharded activations should show zero forward collectives; backward shows domain all-reduces for promoted weight grads (expected and correct).

Enabling new layers / ops

Read references/new-op-patterns.md before writing any patch. Summary of the decision process:

  1. Try the model unmodified first. The generic fallback (convert to DTensor, run, convert back) covers most ops correctly. Only write a patch when you observe: a MissingShardPatch/UndeterminedShardingError, wrong numerics vs a single-GPU run, or unacceptable communication (redistribution to Replicate) in CommDebugMode.

  2. Patches are registered from user code at import time — no physicsnemo fork needed: ShardTensor.register_function_handler(torch.nn.functional.foo, wrapper) (Python/__torch_function__ level), ShardTensor.register_dispatch_handler(aten.foo.default, fn) (__torch_dispatch__ level), and ShardTensor.register_named_function_handler("lib.op.default", wrapper) for torch.library.custom_ops.

  3. Use the existing patches in physicsnemo/domain_parallel/shard_utils/ as templates: pooling_patches.py (config gating + MissingShardPatch), conv_patches.py + halo.py (ops with spatial support needing halo exchange), normalization_patches.py (explicit autograd.Function with custom backward), view_ops.py (dual-level registration; shape-only ops).

Testing new layers

Read references/testing.md. The one-line summary: scatter a full input, run the module distributed and single-GPU, and compare outputs and gradients with numerical_shard_tensor_check(mesh, module, [sharded_x], {}, check_grads=True) under the multigpu_static marker, launched as

torchrun --nproc-per-node 4 -m pytest test/... --multigpu-static -m multigpu_static

A forward-only test proves almost nothing — the weight gradient is where sharding bugs live (it is Partial over the domain mesh and must be reduced). Always check_grads=True, always disable TF32 for the comparison.

  • references/integration-checklist.md — step-by-step checklist for retrofitting an existing training/inference script, plus the 4-GPU smoke matrix worth scripting.

  • references/new-op-patterns.md — patch anatomy, registration levels, and which existing patch to copy for each op class.

  • references/testing.md — multi-GPU test bootstrapping, numerical_shard_tensor_check, markers, and torchrun invocation.

  • physicsnemo-discover — for choosing models, datapipes, and examples.

Files

references/testing.md

Testing ShardTensor ops and models

The gold standard is numerical equivalence against a single-GPU run: same module, same (seeded) weights, full input vs scattered input — outputs AND gradients must match at ~1e-5 in fp32. Forward-only comparisons prove almost nothing; sharding bugs live in gradients (weight grads are Partial over the domain mesh and must be reduced).

How physicsnemo runs multi-GPU tests

Two markers, gated by mutually-exclusive pytest flags (test/conftest.py):

  • @pytest.mark.multigpu_static — the whole pytest session runs inside torchrun with a fixed world; DistributedManager is initialized at pytest configure time and mesh fixtures come from test/plugins/distributed_fixtures (distributed_mesh = 1-D over all ranks, distributed_mesh_2d = 2-D). This is the mode for ShardTensor tests.

torchrun --nproc-per-node 4 -m pytest test/domain_parallel/ \
    --multigpu-static -m multigpu_static
  • @pytest.mark.multigpu_dynamic — the test itself spawns processes; not used for ShardTensor op tests.

Without either flag, all multigpu tests are skipped — so these tests are invisible to a plain pytest run; don't be fooled into thinking they passed.

Precision: comparisons at 1e-4/1e-5 require TF32 disabled — the domain_parallel conftest.py has an autouse fixture forcing full fp32 (allow_tf32 = False, fp32_precision = "ieee"). Replicate it in user repos.

Op-level test template

From test/domain_parallel/ops/test_padding.py — the whole test is declarative:

import pytest, torch
from torch.distributed.tensor.placement_types import Shard
from physicsnemo.distributed import DistributedManager
from physicsnemo.domain_parallel import scatter_tensor

@pytest.mark.multigpu_static
@pytest.mark.parametrize("backward", [False, True])
def test_my_op_1dmesh(distributed_mesh, backward):
    dm = DistributedManager()
    image = torch.randn(1, 16, 128, 128).to(dm.device)   # batch 1!

    sharded = scatter_tensor(image, 0, distributed_mesh, (Shard(2),),
                             requires_grad=backward)

    module = MyNewLayer(...)
    numerical_shard_tensor_check(distributed_mesh, module, [sharded], {},
                                 check_grads=backward)

numerical_shard_tensor_check (test/domain_parallel/ops/utils.py) runs the module on the distributed input and on the gathered full input, compares forward outputs and (with check_grads=True) every parameter gradient. Useful knobs: atol/rtol, amp=True for autocast testing, distribute_fn= to test under a DDP/FSDP2 wrapper instead of replication, output_check_fn= to assert output placements.

Cover at minimum: 1-D mesh Shard(spatial_dim), 2-D mesh (distributed_mesh_2d, e.g. (Shard(2), Shard(3))), forward and backward parametrized, and every config branch of your patch — including one test asserting MissingShardPatch is raised for unsupported configs:

with pytest.raises(NotImplementedError):   # MissingShardPatch subclasses it
    module(sharded_bad_config)

Model-level test template

test/domain_parallel/models/harness.py makes a model test a few declarative lines: describe how to build the model, the full inputs, and how to shard them, then hand a DomainParallelModelCase to run_domain_parallel_model_check. Test both strategies:

  • strategy="ddp" — all params plain, wrap_ddp over the mesh group.

  • strategy="fsdp_spatial" — spatial params (pos_embed / RoPE, selected by name) DTensor-sharded on the domain mesh, fully_shard (FSDP2) over the ddp mesh. This mirrors production (ParallelHelper.distribute_model).

Never add strategy="distribute_module" for new work — it exists only as a legacy comparison point.

Testing in user code (outside physicsnemo): vendorable template

The physicsnemo test/ tree is not an installed package — vendor these two small files into the user repo instead of importing physicsnemo test internals.

tests/conftest.py:

import pytest
import torch


def pytest_addoption(parser):
    parser.addoption("--multigpu", action="store_true",
                     help="run distributed tests (launch via torchrun)")


def pytest_configure(config):
    config.addinivalue_line("markers", "multigpu: needs torchrun + --multigpu")
    if config.getoption("--multigpu"):
        from physicsnemo.distributed import DistributedManager
        DistributedManager.initialize()


def pytest_collection_modifyitems(config, items):
    if not config.getoption("--multigpu"):
        skip = pytest.mark.skip(reason="needs torchrun + --multigpu")
        for item in items:
            if "multigpu" in item.keywords:
                item.add_marker(skip)


@pytest.fixture(scope="session")
def domain_mesh():
    from physicsnemo.distributed import DistributedManager
    dm = DistributedManager()
    torch.cuda.set_device(dm.device)
    # 1-D mesh over all ranks; add a (ddp, domain) 2-D variant for wrapper
    # tests: dm.initialize_mesh((world // 2, 2), ("ddp", "domain"))["domain"]
    return dm.initialize_mesh((dm.world_size,), mesh_dim_names=("domain",))


@pytest.fixture(autouse=True)
def deterministic():
    # Identical per-rank weight init is what makes distributed-vs-local
    # comparison valid; TF32 (~1e-3 error) would swamp the 1e-4 tolerance.
    torch.manual_seed(42)
    prev = torch.backends.cuda.matmul.allow_tf32, torch.backends.cudnn.allow_tf32
    torch.backends.cuda.matmul.allow_tf32 = False
    torch.backends.cudnn.allow_tf32 = False
    yield
    torch.backends.cuda.matmul.allow_tf32, torch.backends.cudnn.allow_tf32 = prev

tests/shard_check.py — the distributed-vs-local comparison:

import copy
import torch
from torch.distributed.tensor import DTensor
from physicsnemo.domain_parallel import ShardTensor


def check_distributed_vs_local(module, sharded_args, *, check_grads=True,
                               atol=1e-4, rtol=1e-4):
    """Run `module` on sharded and on full inputs; outputs and grads must match.

    `module` must NOT be wrapped (no DDP/FSDP2) - the deepcopy below is the
    single-device reference and must share the distributed module's weights,
    which the seed fixture guarantees at construction time.
    """
    local_module = copy.deepcopy(module)

    full_args = []
    for a in sharded_args:
        if isinstance(a, ShardTensor):
            fa = a.full_tensor().detach().requires_grad_(a.requires_grad)
        else:
            fa = a
        full_args.append(fa)

    out_dist = module(*sharded_args)
    out_local = local_module(*full_args)

    out_dist_full = (out_dist.full_tensor()
                     if isinstance(out_dist, (ShardTensor, DTensor)) else out_dist)
    torch.testing.assert_close(out_dist_full, out_local, atol=atol, rtol=rtol)

    if check_grads:
        # Same scalar loss on both sides. sum() of a sharded output routes
        # through the ShardTensor reduction ops - that is part of the test.
        out_dist.sum().backward()
        out_local.sum().backward()
        for (name, p_d), (_, p_l) in zip(module.named_parameters(),
                                         local_module.named_parameters()):
            assert (p_d.grad is None) == (p_l.grad is None), name
            if p_d.grad is None:
                continue
            g = p_d.grad
            if isinstance(g, (ShardTensor, DTensor)):
                g = g.full_tensor()
            torch.testing.assert_close(g, p_l.grad, atol=atol, rtol=rtol,
                                       msg=f"grad mismatch: {name}")
        # Input grads too, when requested via requires_grad at scatter time.
        for sa, fa in zip(sharded_args, full_args):
            if isinstance(sa, ShardTensor) and sa.requires_grad:
                torch.testing.assert_close(sa.grad.full_tensor(), fa.grad,
                                           atol=atol, rtol=rtol)

A test then looks identical to the physicsnemo op tests:

@pytest.mark.multigpu
def test_my_layer(domain_mesh):
    x = torch.randn(1, 16, 128, 128, device="cuda")          # batch 1!
    sharded = scatter_tensor(x, 0, domain_mesh, (Shard(2),),
                             requires_grad=True)
    check_distributed_vs_local(MyNewLayer(16), [sharded])

Launch (CI and locally):

torchrun --standalone --nproc-per-node 2 -m pytest tests/ --multigpu -m multigpu

2 GPUs catch most sharding bugs; keep at least one 4-GPU test on a 2×2 (ddp, domain) mesh — mesh-axis mixups (reducing over the wrong axis) are invisible on a 1-D mesh. Caveats that make this template valid: per-domain batch of 1; every rank constructs the module under the same seed before any wrapper; full_tensor() is differentiable, so gathering for comparison does not break the grad checks; hooks/requires_grad must be set at scatter_tensor(...) time, not after (see SKILL.md pitfalls).

Regression tests for compile support

When a patch must work under torch.compile, add a compile variant (see test/domain_parallel/test_compile.py, added with the torch.compile enablement work — absent on builds that predate it): compile the module (backend="inductor", dynamic=False; the suite historically uses aot_eager as a fallback backend when inductor is flaky), run forward AND backward twice (the second iteration catches guard/recompile issues), and compare against eager. Compiled tests must also assert that outputs remain usable by eager ops afterward (hash the spec, add two results) — the eager/compiled boundary is where subclass metadata gets lost.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Python, Needs Node.js

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
NVIDIA
Publisher
NVIDIA (Official)
Source
NVIDIA/skills · skills/physicsnemo-shard-tensor · commit fce3cca
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE-APACHE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by NVIDIA.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download physicsnemo-shard-tensor.zip