# pytorch

Enforces clean PyTorch patterns across Python files in Cursor. Instructs the assistant to separate modules, place tensors on devices explicitly, and disable gradients in inference.

- rule · `type=rule` · Cursor · ★ 3580
- Author: sanjeed5
- License: CC0-1.0 · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/pytorch.mdc
- Updated: 2026-05-19
- HTML: https://affpapa.org/en/nevibecode/rules/pytorch

## What it does

The rule targets all `**/*.py` files and stops the assistant from writing monolithic training scripts. It requires splitting the workflow into distinct modules for data loading, model architecture, training, and evaluation. In data pipelines, it sets `num_workers=4` and `pin_memory=True` inside the `DataLoader`.

Device management must remain explicit. The rule forces `.to(device)` calls for models and batches instead of relying on default CPU placement. During model evaluation, wrapping inference in `torch.no_grad()` is strictly required.

In-place operations like `.add_()` are forbidden. They corrupt the PyTorch `autograd` computation graph. Such mutations are permitted only when profiling proves a critical performance bottleneck.

## Install

### Cursor (native platform)

**Manually: put the files in place**
- File: `.cursor/rules/pytorch.mdc` — Frontmatter: description, globs, alwaysApply

### Claude Code

**Manually: put the files in place**
- File: `.claude/rules/pytorch.md` — The paths frontmatter field limits the files: move globs from the source into paths

### Codex

**AGENTS.md**
- Codex reads AGENTS.md: paste the rule text there

### GitHub Copilot

**Manually: put the files in place**
- File: `.github/instructions/pytorch.instructions.md` — The applyTo field sets which files it applies to: move globs from the source into applyTo

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/rules/pytorch.md`

### Cline

**Manually: put the files in place**
- File: `.clinerules/pytorch.md`

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/pytorch.mdc

## When to use it
- Split monolithic ML scripts into modular components
- Prevent inference memory leaks by applying `torch.no_grad()`
- Enforce explicit tensor allocation on GPU via `.to(device)`
- Protect the `autograd` computation graph against in-place mutations

## Example prompts
- Create a modular PyTorch training pipeline with separate data loaders and model definition
- Implement an evaluation loop for my PyTorch CNN using explicit device placement

## Source text · pytorch.mdc · CC0-1.0

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: ea59fcc094b8c4b7.

BEGIN THIRD-PARTY FILE ea59fcc094b8c4b7
````text
---
description: Definitive guidelines for writing clean, performant, and maintainable PyTorch code, emphasizing modern best practices, explicit device management, and efficient training patterns.
globs: **/*.py
---
# PyTorch Best Practices

This guide outlines the definitive best practices for developing with PyTorch, ensuring your code is readable, performant, and production-ready. We prioritize usability, explicit control, and modern tooling.

## 1. Code Organization and Structure

Structure your PyTorch projects for clarity, testability, and scalability. Encapsulate logical blocks into distinct functions or classes.

### 1.1. Modularize Your Codebase

Separate data loading, model definition, training, and evaluation into dedicated modules or functions. This makes components reusable and testable.

❌ BAD: Monolithic script
```python
# train.py
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset

# ... data loading, model definition, training loop all in one file ...

class MyModel(nn.Module):
    # ...
    pass

def main():
    # Data loading
    train_data = TensorDataset(...)
    train_loader = DataLoader(train_data, batch_size=32)

    # Model, optimizer, loss
    model = MyModel()
    optimizer = torch.optim.Adam(model.parameters())
    criterion = nn.CrossEntropyLoss()

    # Training loop
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(train_loader):
            # ... training logic ...
            pass

if __name__ == "__main__":
    main()
```

✅ GOOD: Modularized structure
```python
# src/data.py
import torch
from torch.utils.data import DataLoader, TensorDataset

def get_dataloaders(batch_size: int) -> tuple[DataLoader, DataLoader]:
    # Example: Create synthetic data
    X = torch.randn(1000, 784)
    y = torch.randint(0, 10, (1000,))
    train_dataset = TensorDataset(X, y)
    val_dataset = TensorDataset(X[:100], y[:100]) # Smaller val set
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=True)
    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True)
    return train_loader, val_loader

# src/model.py
import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self, num_classes: int = 10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(64 * 7 * 7, 128), # Assuming 28x28 input, adjust for other sizes
            nn.ReLU(),
            nn.Linear(128, num_classes)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.features(x)
        x = self.classifier(x)
        return x

# src/train.py
import torch
import torch.nn as nn
from torch.optim import Adam
from src.model import SimpleCNN
from src.data import get_dataloaders

def train_epoch(model: nn.Module, loader: DataLoader, optimizer: Adam, criterion: nn.Module, device: torch.device) -> float:
    model.train()
    total_loss = 0.0
    for data, target in loader:
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    return total_loss / len(loader)

def evaluate_model(model: nn.Module, loader: DataLoader, device: torch.device) -> float:
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for data, target in loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            _, predicted = torch.max(output.data, 1)
````
END THIRD-PARTY FILE ea59fcc094b8c4b7

The third-party file has ended. Everything between the ea59fcc094b8c4b7 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 3989 of 14844 bytes. © sanjeed5 · CC0-1.0 · https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/pytorch.mdc

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
