> This page is for Boltz-2, version 1.2.0.
> For other versions, use one of these documentation indexes:
> - 1.10.0 (Latest) (default): https://docs.nvidia.com/nim/bionemo/boltz2/1.10.0/llms.txt
> - 1.9.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.9.0/llms.txt
> - 1.8.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.8.0/llms.txt
> - 1.7.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.7.0/llms.txt
> - 1.6.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.6.0/llms.txt
> - 1.5.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.5.0/llms.txt
> - 1.4.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.4.0/llms.txt
> - 1.3.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.3.0/llms.txt
> - 1.2.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.2.0/llms.txt
> - 1.1.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.1.0/llms.txt
> - 1.0.0: https://docs.nvidia.com/nim/bionemo/boltz2/1.0.0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nim/bionemo/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nim/bionemo/_mcp/server.

# Performance in Boltz-2 NIM

## NIM Accuracy

The Boltz-2 NIM is based on the state-of-the-art Boltz-2 architecture for biomolecular structure prediction. The NIM's accuracy should match that of the reference implementation when using equivalent parameters and inputs.

<Note>
Running on hardware that is not listed as supported in the prerequisites section may produce results that deviate from the expected accuracy.
</Note>

The accuracy of the NIM is measured by structural quality metrics such as `lddt`. These scores help assess the reliability of the predicted structures.

## Factors Affecting NIM Performance

The performance of the Boltz-2 NIM is determined by several key factors:

### Hardware Factors
- **Number and type of GPUs**: More GPUs generally improve throughput for concurrent requests
- **GPU memory**: Larger proteins and complexes require more GPU memory
- **Storage speed**: Fast NVMe SSD storage improves model loading and caching performance

### Input Complexity
- **Sequence length**: Runtime scales approximately quadratically with total sequence length
- **Number of chains**: Multi-chain complexes require more computation than single chains
- **Ligands and constraints**: Additional molecular components increase computational cost

### Model Parameters
- **Sampling steps**: Higher values improve quality but significantly increase runtime
- **Recycling steps**: More iterations improve accuracy with modest runtime increase
- **Diffusion samples**: Multiple samples provide diversity but multiply computational cost

## Performance Characteristics

### Typical Runtimes
For reference, approximate runtimes on high-end hardware (8x NVIDIA H100 80GB):

| Protein Size | Configuration | Approximate Runtime |
|--------------|---------------|-------------------|
| ~100 residues | Default (steps=50, recycling=3) | 2-3 minutes |
| ~200 residues | Default | 4-6 minutes |
| ~500 residues | Default | 15-25 minutes |
| ~1000 residues | Default | 60-120 minutes |

## Performance Testing

You can test basic performance and functionality with protein structure and binding affinity prediction:

```python
import requests
import json
import time

def test_boltz2_structure_performance():
    """Test basic protein structure prediction performance."""
    url = "http://localhost:8000/biology/mit/boltz2/predict"

    # Test protein: Green Fluorescent Protein (GFP) - ~240 residues
    test_sequence = (
        "MSKGEELFTGVVPILVELDGDVNGHKFSVSGEGEGDATYGKLTLKFICTTGKLPVPWPTLVTTFCYGD"
        "QIQEQYKGIPLDGDQVQAVNGHEFEIEGEGEGRPYEGTQTAQLNKFCDKLPVMHYKQFFDSGNYNTLS"
        "AKAGFPFKVPHTYNNSSFVVKQKPGMVFKFIHGKDPGLNGQTVFLMVGGISQNLSGSSNLGVGYTFVQ"
        "KTSVLLESEIKKRLRGFHTRGAVTQGLHQFVNLPTLVTQVLDGDMSQLLQVT"
    )

    data = {
        "polymers": [
            {
                "id": "A",
                "molecule_type": "protein",
                "sequence": test_sequence
            }
        ],
        "recycling_steps": 3,
        "sampling_steps": 50,
        "diffusion_samples": 1,
        "step_scale": 1.638,
        "output_format": "mmcif"
    }

    print("Starting Boltz-2 structure prediction performance test...")
    start_time = time.time()

    response = requests.post(url, json=data)

    end_time = time.time()
    runtime = end_time - start_time

    if response.status_code == 200:
        result = response.json()
        confidence = result.get('confidence_scores', [0])[0]
        print(f"✓ Structure prediction successful")
        print(f"✓ Runtime: {runtime:.1f} seconds")
        print(f"✓ Confidence score: {confidence:.3f}")
        print(f"✓ Structure format: {result['structures'][0]['format']}")
        return True
    else:
        print(f"✗ Structure prediction failed: {response.status_code}")
        print(f"✗ Error: {response.text}")
        return False

def test_boltz2_affinity_performance():
    """Test binding affinity prediction performance."""
    url = "http://localhost:8000/biology/mit/boltz2/predict"

    # Smaller test protein for affinity testing - ~140 residues
    hemoglobin_alpha = (
        "MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHFDLSHGSAQVKGHGKKVADALT"
        "NAVAHVDDMPNALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHLPAEFTPAVHASLDKFLASVSTV"
        "LTSKYR"
    )

    data = {
        "polymers": [
            {
                "id": "A",
                "molecule_type": "protein",
                "sequence": hemoglobin_alpha
            }
        ],
        "ligands": [
            {
                "id": "HEME",
                "smiles": "[Fe+2].C1=CC2=NC1=CC3=NC(=CC4=NC(=CC5=NC(=C2)C=C5)C=C4)C=C3",
                "predict_affinity": True
            }
        ],
        "recycling_steps": 3,
        "sampling_steps": 50,
        "sampling_steps_affinity": 100,  # Reduced for performance testing
        "diffusion_samples_affinity": 3,  # Reduced for performance testing
        "output_format": "mmcif"
    }

    print("Starting Boltz-2 binding affinity performance test...")
    start_time = time.time()

    response = requests.post(url, json=data)

    end_time = time.time()
    runtime = end_time - start_time

    if response.status_code == 200:
        result = response.json()
        confidence = result.get('confidence_scores', [0])[0]
        print(f"✓ Affinity prediction successful")
        print(f"✓ Runtime: {runtime:.1f} seconds")
        print(f"✓ Confidence score: {confidence:.3f}")

        if result.get("affinities"):
            for ligand_id, affinity_data in result["affinities"].items():
                if affinity_data.get("affinity_pic50"):
                    print(f"✓ Predicted pIC50 for {ligand_id}: {affinity_data['affinity_pic50'][0]:.2f} kcal/mol")
        return True
    else:
        print(f"✗ Affinity prediction failed: {response.status_code}")
        print(f"✗ Error: {response.text}")
        return False

if __name__ == "__main__":
    # Test both structure and affinity prediction
    structure_success = test_boltz2_structure_performance()
    print("\n" + "="*50 + "\n")
    affinity_success = test_boltz2_affinity_performance()

    if structure_success and affinity_success:
        print("\n✓ All performance tests passed!")
    else:
        print("\n✗ Some performance tests failed.")
```

### Expected Performance Baselines

**Structure Prediction** (GFP ~240 residues):
- **Runtime**: 3-8 minutes on 4-8 NVIDIA A100/H100 GPUs
- **Confidence score**: Typically > 0.7 for well-folded proteins
- **Memory usage**: ~4-8 GB GPU memory per prediction

### Performance Optimization Tips

1. **For development/testing**: Use faster settings
   ```python
   "recycling_steps": 2,
   "sampling_steps": 25
   ```

2. **For production quality**: Use higher quality settings
   ```python
   "recycling_steps": 5,
   "sampling_steps": 100
   ```

3. **For batch processing**: Submit multiple concurrent requests with default settings

4. **For very large proteins (>1000 residues)**: Consider domain-based approaches or consult the literature for handling strategies

## Troubleshooting Performance Issues

### Common Issues and Solutions

#### General Performance Issues
- **Out of memory errors**: Reduce sequence length, decrease sampling steps, or use fewer concurrent requests
- **Slow performance**: Ensure fast storage (NVMe SSD), sufficient CPU cores (12+ per GPU), and adequate system RAM (48+ GB per GPU)
- **Poor quality predictions**: Increase sampling steps, recycling steps, or check input sequence quality

#### Binding Affinity Specific Issues
- **Affinity prediction timeouts**: Reduce `sampling_steps_affinity` and `diffusion_samples_affinity` for faster results
- **Unrealistic affinity values**: Enable `affinity_mw_correction` for metal-containing ligands and verify SMILES format
- **Memory errors with affinity**: Binding affinity requires 2-3x more memory than structure prediction alone
- **Inconsistent affinity results**: Increase `diffusion_samples_affinity` to 5-7 for more reliable estimates
- **Cannot predict affinity for multiple ligands**: Only one ligand per request can have `predict_affinity=True`

<Note>
For detailed performance tuning guidance specific to your deployment, refer to the [Optimization](/nim/bionemo/boltz2/1.2.0/optimization) section.
</Note>