Performance Tuning Guide
This notebook covers optimization strategies for getting the best performance from Auto3D.
CLI Quick Reference (Recommended)
# Quick screening (fastest)
auto3d run input.smi --k=1 --engine=ANI2xt --gpu
# Standard workflow
auto3d run input.smi --k=1 --engine=AIMNET --gpu
# High accuracy (with ensemble)
AUTO3D_USE_ENSEMBLE=1 auto3d run input.smi --k=1 --engine=AIMNET --gpu
# With torch.compile optimization (ANI models)
AUTO3D_COMPILE_MODEL=1 auto3d run input.smi --k=1 --engine=ANI2x --gpu
# Multi-GPU processing
auto3d run large_dataset.smi --k=1 --gpu --gpu-idx="0,1,2,3"
# Generate preset configurations
auto3d config init -p quick -o quick.yaml # Fast screening
auto3d config init -p balanced -o balanced.yaml # Default settings
auto3d config init -p thorough -o thorough.yaml # High accuracy
# Run with configuration file
auto3d run input.smi -c quick.yaml
Optimal Settings by Use Case:
Use Case |
CLI Command |
|---|---|
Quick screening |
|
Standard workflow |
|
High accuracy |
|
Multi-GPU |
|
Python API Performance Guide
Below we explore performance optimization using the Python API:
[ ]:
import time
import torch
import Auto3D
from Auto3D import Auto3DOptions, smiles2mols, create_model
print(f"Auto3D: {Auto3D.__version__}")
print(f"PyTorch: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
1. Choosing the Right Engine
Speed comparison of available engines:
[ ]:
# Test molecules
test_smiles = ["c1ccc2c(c1)cccc2", "CCCCc1ccccc1", "O=C(NC)Nc1ccccc1"]
engines = ["ANI2xt", "ANI2x", "AIMNET"]
for engine in engines:
start = time.time()
config = Auto3DOptions(k=1, optimizing_engine=engine, use_gpu=False)
mols = smiles2mols(test_smiles, config)
elapsed = time.time() - start
print(f"{engine}: {elapsed:.2f}s")
Recommendations:
ANI2xt: Fastest, use for initial screening
ANI2x: Good balance of speed and accuracy
AIMNET: Most accurate, supports charged molecules
2. GPU Acceleration
GPU provides significant speedup for large batches:
[ ]:
if torch.cuda.is_available():
# CPU timing
start = time.time()
config = Auto3DOptions(k=1, use_gpu=False)
mols_cpu = smiles2mols(test_smiles, config)
cpu_time = time.time() - start
# GPU timing
start = time.time()
config = Auto3DOptions(k=1, use_gpu=True)
mols_gpu = smiles2mols(test_smiles, config)
gpu_time = time.time() - start
print(f"CPU: {cpu_time:.2f}s")
print(f"GPU: {gpu_time:.2f}s")
print(f"Speedup: {cpu_time/gpu_time:.1f}x")
else:
print("No GPU available for comparison")
3. Single Model vs Ensemble (AIMNET)
By default, Auto3D uses a single AIMNet2 model for ~35x faster optimization:
[ ]:
import os
# Single model (default, faster)
os.environ["AUTO3D_USE_ENSEMBLE"] = "0"
start = time.time()
config = Auto3DOptions(k=1, optimizing_engine="AIMNET", use_gpu=False)
mols = smiles2mols(test_smiles[:1], config)
single_time = time.time() - start
print(f"Single model: {single_time:.2f}s")
print("Use ensemble=True for highest accuracy (slower)")
4. TF32 Acceleration (Ampere+ GPUs)
Enable TensorFloat-32 for faster matrix operations on RTX 30xx, A100, H100:
[ ]:
if torch.cuda.is_available():
# Check GPU architecture
capability = torch.cuda.get_device_capability(0)
is_ampere_plus = capability[0] >= 8
if is_ampere_plus:
print(f"GPU supports TF32 (compute capability {capability[0]}.{capability[1]})")
# With TF32
config = Auto3DOptions(k=1, use_gpu=True, allow_tf32=True)
start = time.time()
mols = smiles2mols(test_smiles, config)
tf32_time = time.time() - start
print(f"With TF32: {tf32_time:.2f}s")
else:
print(f"GPU compute capability {capability[0]}.{capability[1]} - TF32 not available")
5. Batch Size Optimization
Tune batch size for your GPU memory:
[ ]:
# GPU memory recommendations:
# 8 GB: batchsize_atoms=512
# 16 GB: batchsize_atoms=1024 (default)
# 24 GB: batchsize_atoms=1536
# 40+ GB: batchsize_atoms=2048
if torch.cuda.is_available():
total_mem = torch.cuda.get_device_properties(0).total_memory / 1e9
if total_mem < 12:
recommended = 512
elif total_mem < 20:
recommended = 1024
elif total_mem < 32:
recommended = 1536
else:
recommended = 2048
print(f"GPU memory: {total_mem:.1f} GB")
print(f"Recommended batchsize_atoms: {recommended}")
6. Convergence Tuning
Trade off accuracy for speed:
[ ]:
# Fast (screening)
fast_config = Auto3DOptions(
k=1,
convergence_threshold=0.02, # Loose threshold
patience=100, # Quick dropout
opt_steps=1000, # Fewer max steps
use_gpu=False,
)
# Default (balanced)
default_config = Auto3DOptions(
k=1,
convergence_threshold=0.01, # Default
patience=250,
opt_steps=2000,
use_gpu=False,
)
# Accurate (production)
accurate_config = Auto3DOptions(
k=1,
convergence_threshold=0.003, # Tight threshold
patience=500,
opt_steps=5000,
use_gpu=False,
)
# Compare
for name, config in [("Fast", fast_config), ("Default", default_config), ("Accurate", accurate_config)]:
start = time.time()
mols = smiles2mols(["CCCCc1ccccc1"], config)
elapsed = time.time() - start
energy = float(mols[0].GetProp("E_tot"))
print(f"{name}: {elapsed:.2f}s, E={energy:.6f} Hartree")
7. Reducing Initial Conformers
Limit the number of initial conformers generated:
[ ]:
# For flexible molecules, limit initial conformers
config = Auto3DOptions(
k=1,
max_confs=50, # Limit initial conformers (None = dynamic)
use_gpu=False,
)
start = time.time()
mols = smiles2mols(["CCCCCCCCCC"], config) # decane
print(f"Time: {time.time() - start:.2f}s")
8. Multi-GPU Processing
Distribute work across multiple GPUs:
[ ]:
if torch.cuda.is_available():
n_gpus = torch.cuda.device_count()
print(f"Available GPUs: {n_gpus}")
if n_gpus > 1:
# Use all GPUs
config = Auto3DOptions(
k=1,
use_gpu=True,
gpu_idx=list(range(n_gpus)), # [0, 1, 2, ...]
)
print(f"Using GPUs: {list(range(n_gpus))}")
else:
print("Single GPU mode")
9. Memory Profiling
[ ]:
if torch.cuda.is_available():
torch.cuda.reset_peak_memory_stats()
config = Auto3DOptions(k=1, use_gpu=True)
mols = smiles2mols(["c1ccc2c(c1)cccc2"], config)
peak_memory = torch.cuda.max_memory_allocated() / 1e9
print(f"Peak GPU memory: {peak_memory:.2f} GB")
Summary: Optimal Settings by Use Case
Use Case |
Engine |
GPU |
TF32 |
batchsize |
threshold |
|---|---|---|---|---|---|
Quick screening |
ANI2xt |
Yes |
Yes |
1024 |
0.02 |
Standard workflow |
AIMNET |
Yes |
Yes |
1024 |
0.01 |
High accuracy |
AIMNET + ensemble |
Yes |
No |
512 |
0.003 |
Limited GPU memory |
ANI2xt |
Yes |
Yes |
256 |
0.01 |
CPU only |
ANI2xt |
No |
N/A |
1024 |
0.01 |
CLI Quick Reference for Performance
# Quick screening (fastest)
auto3d run input.smi --k=1 --engine=ANI2xt --gpu
# Standard workflow
auto3d run input.smi --k=1 --engine=AIMNET --gpu
# High accuracy (with ensemble)
AUTO3D_USE_ENSEMBLE=1 auto3d run input.smi --k=1 --engine=AIMNET --gpu
# With torch.compile optimization (ANI models)
AUTO3D_COMPILE_MODEL=1 auto3d run input.smi --k=1 --engine=ANI2x --gpu
# Multi-GPU processing
auto3d run large_dataset.smi --k=1 --gpu --gpu-idx="0,1,2,3"
# Generate preset configurations
auto3d config init -p quick -o quick.yaml # Fast screening
auto3d config init -p balanced -o balanced.yaml # Default settings
auto3d config init -p thorough -o thorough.yaml # High accuracy
# Run with configuration file
auto3d run input.smi -c quick.yaml
Example performance.yaml for HPC:
optimizing_engine: ANI2xt
use_gpu: true
gpu_idx: [0, 1, 2, 3]
batchsize_atoms: 2048
allow_tf32: true
convergence_threshold: 0.01
patience: 200