Running VERONA with GPU Acceleration for Large-Scale Verification
TLDR: VERONA automatically detects CUDA-capable devices and routes tensors, models, and verification calls to GPU-accelerated backends like AB-CROWN without requiring manual device configuration.
VERONA (VERification Of Neural Architectures) is a modular Python library developed by ada-research/verona that streamlines robustness verification pipelines for neural networks. When executing large-scale experiments—such as verifying thousands of images or running computationally intensive verifiers like AB-CROWN—GPU acceleration is crucial for performance. The framework abstracts CUDA detection across its components, automatically placing tensors and models on torch.device("cuda") when available while delegating heavy computations to GPU-aware verification backends.
How VERONA Automatically Detects CUDA Devices
The library implements automatic device selection at multiple stages of the verification pipeline. Each component checks torch.cuda.is_available() independently, ensuring seamless GPU utilization without manual intervention.
Data Sampling on GPU
The PredictionsBasedSampler handles moving input tensors to the appropriate device before processing. In ada_verona/dataset_sampler/predictions_based_sampler.py (line 54), the device selection logic initializes as:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
This ensures that sampled data points are immediately transferred to CUDA memory when hardware acceleration is present, reducing CPU-GPU transfer overhead during verification.
Model Loading for GPU Execution
Neural network wrappers in VERONA automatically place models on the detected CUDA device. Both PytorchNetwork and OnnxNetwork implement identical device-selection patterns in ada_verona/database/machine_learning_model/pytorch_network.py (line 89) and .../onnx_network.py (line 102). When the experiment repository loads a network, it resides on the same CUDA device as the input tensors, eliminating device mismatch errors during forward passes.
Configuring GPU-Enabled Verification Backends
VERONA delegates GPU-intensive computations to specialized verification backends through the AutoVerifyModule wrapper, which inherits from the abstract VerificationModule base class in ada_verona/verification_module/verification_module.py.
AutoVerifyModule and AB-CROWN Integration
The AutoVerifyModule class in ada_verona/verification_module/auto_verify_module.py serves as the primary interface for GPU-accelerated verifiers. When configured with AB-CROWN, the module forwards verification calls to the auto-verify framework, which automatically utilizes CUDA for underlying MILP/LP solves. The execution flow proceeds as follows:
- Property Generation:
One2OnePropertyGeneratororOne2AnyPropertyGeneratorcreates VNN-LIB specifications describing the ε-ball (CPU-bound operation). - Verification Dispatch:
AutoVerifyModule.verifyhands the VNN-LIB and model path to the verifier. - GPU Computation: AB-CROWN executes linear programming operations on CUDA cores.
- Result Parsing: SAT/UNSAT outcomes return as
CompleteVerificationDataobjects.
Adversarial Attacks on GPU
For optional adversarial robustness testing, the AutoAttack wrapper in ada_verona/verification_module/attacks/auto_attack_wrapper.py defaults to CUDA execution:
self.device = device
This allows fast adversarial attacks to run on GPU when available, providing rapid counter-example generation before formal verification begins.
Complete GPU Verification Pipeline Example
The following minimal example demonstrates a full GPU-enabled verification loop using AB-CROWN. Install the GPU variant first:
uv pip install "ada-verona[gpu]"
Verify CUDA detection before running:
import torch
print("CUDA available:", torch.cuda.is_available())
Execute the complete pipeline:
from pathlib import Path
import torch, torchvision.transforms as transforms
import torchvision
from ada_verona.database.experiment_repository import ExperimentRepository
from ada_verona.dataset_sampler.predictions_based_sampler import PredictionsBasedSampler
from ada_verona.verification_module.auto_verify_module import AutoVerifyModule
from ada_verona.verification_module.property_generator.one2any_property_generator import One2AnyPropertyGenerator
from ada_verona.epsilon_value_estimator.binary_search_epsilon_value_estimator import BinarySearchEpsilonValueEstimator
from autoverify.verifier import AbCrown
# 1️⃣ Load dataset
mnist = torchvision.datasets.MNIST(root="./data", train=True, download=True,
transform=transforms.ToTensor())
# 2️⃣ Prepare experiment repository
repo = ExperimentRepository(base_path=Path("./my_experiment"), network_folder=Path("./networks"))
repo.initialize_new_experiment("gpu_ab_crown_demo")
# 3️⃣ Configure components
prop_gen = One2AnyPropertyGenerator()
verifier = AutoVerifyModule(verifier=AbCrown(), timeout=600)
eps_estimator = BinarySearchEpsilonValueEstimator(
epsilon_value_list=[0.001, 0.005, 0.01, 0.02],
verifier=verifier
)
sampler = PredictionsBasedSampler(sample_correct_predictions=True)
# 4️⃣ Run verification
network = repo.get_network_list()[0]
for data_point in sampler.sample(network, mnist):
ctx = repo.create_verification_context(network, data_point, prop_gen)
result = eps_estimator.compute_epsilon_value(ctx)
repo.save_result(result)
repo.save_plots()
Key implementation details:
PredictionsBasedSamplermovesdata_pointto CUDA viatorch.device("cuda").PytorchNetworkloads onto the same CUDA device internally through the experiment repository.AutoVerifyModuleforwards to AB-CROWN, which performs MILP computations on GPU.
Scaling to Multi-Node GPU Clusters
For massive parallelization across multiple compute nodes, VERONA supports SLURM array jobs. The multiple_jobs/one_multiple_jobs.py script dispatches individual verification contexts as separate tasks, with each node executing the same GPU detection logic:
python examples/scripts/multiple_jobs/one_multiple_jobs.py \
--file_verification_context path/to/context.yaml \
--base_path_experiment_repository ./my_experiment \
--network_folder ./networks \
--experiment_name gpu_ab_crown_demo \
--epsilon_list 0.001 0.005 0.01 0.02
Each compute node independently loads the model onto its local GPU via pytorch_network.py, runs AB-CROWN verification, and writes results back to the shared experiment repository. This architecture enables horizontal scaling from single-GPU workstations to multi-node clusters without code modification.
Summary
- Automatic detection: VERONA checks
torch.cuda.is_available()inPredictionsBasedSamplerand model wrappers, eliminating manual device management. - Backend integration:
AutoVerifyModuleinada_verona/verification_module/auto_verify_module.pyroutes computations to GPU-enabled verifiers like AB-CROWN. - Full pipeline support: Data loading, model placement, adversarial attacks (
auto_attack_wrapper.py), and verification all respect CUDA availability. - Cluster scaling: The
one_multiple_jobs.pyscript enables distributed GPU verification across SLURM-managed clusters. - Installation: Use
pip install "ada-verona[gpu]"to ensure GPU dependencies are present.
Frequently Asked Questions
Does VERONA require manual CUDA device management?
No. VERONA automatically detects CUDA-capable hardware in ada_verona/dataset_sampler/predictions_based_sampler.py (line 54) and ada_verona/database/machine_learning_model/pytorch_network.py (line 89), placing tensors and models on the appropriate device without user intervention. You only need to ensure PyTorch with CUDA support is installed.
Which verification backends support GPU acceleration in VERONA?
VERONA supports GPU acceleration through the AutoVerifyModule wrapper for any auto-verify compatible verifier. AB-CROWN is the primary GPU-accelerated backend, automatically utilizing CUDA for MILP/LP solves. The AutoAttack wrapper in ada_verona/verification_module/attacks/auto_attack_wrapper.py also defaults to GPU execution for adversarial robustness testing.
How do I verify that VERONA is using my GPU?
Run the sanity check shown in examples/scripts/create_robustness_dist_on_pytorch_dataset.py:
import torch
print("CUDA available:", torch.cuda.is_available())
Additionally, monitor GPU utilization during verification runs. AB-CROWN will show significant GPU activity when solving linear programs, while the PredictionsBasedSampler will allocate CUDA memory for model and tensor storage.
Can I run CPU-only verification if CUDA is available?
Yes. While VERONA defaults to CUDA when detected, the device selection logic torch.device("cuda" if torch.cuda.is_available() else "cpu") in the sampler and model loaders will fall back to CPU if CUDA is unavailable or disabled. To force CPU execution on a CUDA-enabled system, modify the device assignment in the respective source files or set environment variables that hide CUDA devices from PyTorch.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →